diff --git a/scripting/javascript/spidermonkey-android/include/ds/BitArray.h b/scripting/javascript/spidermonkey-android/include/ds/BitArray.h index 91165f919d..1be12fc881 100644 --- a/scripting/javascript/spidermonkey-android/include/ds/BitArray.h +++ b/scripting/javascript/spidermonkey-android/include/ds/BitArray.h @@ -1,42 +1,9 @@ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=4 sw=4 et tw=99 ft=cpp: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is SpiderMonkey JavaScript engine. - * - * The Initial Developer of the Original Code is - * Mozilla Corporation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Terrence Cole - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef BitArray_h__ #define BitArray_h__ diff --git a/scripting/javascript/spidermonkey-android/include/gc/Barrier.h b/scripting/javascript/spidermonkey-android/include/gc/Barrier.h index 0654ec7dee..08c8de8f0d 100644 --- a/scripting/javascript/spidermonkey-android/include/gc/Barrier.h +++ b/scripting/javascript/spidermonkey-android/include/gc/Barrier.h @@ -1,48 +1,16 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=78: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is SpiderMonkey global object code. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsgc_barrier_h___ #define jsgc_barrier_h___ #include "jsapi.h" -#include "jscell.h" +#include "gc/Heap.h" #include "js/HashTable.h" /* @@ -140,12 +108,10 @@ * and jsid, respectively. * * One additional note: not all object writes need to be barriered. Writes to - * newly allocated objects do not need a barrier as long as the GC is not - * allowed to run in between the allocation and the write. In these cases, we - * use the "obj->field.init(value)" method instead of "obj->field = value". - * We use the init naming idiom in many places to signify that a field is being - * assigned for the first time, and that no GCs have taken place between the - * object allocation and the assignment. + * newly allocated objects do not need a pre-barrier. In these cases, we use + * the "obj->field.init(value)" method instead of "obj->field = value". We use + * the init naming idiom in many places to signify that a field is being + * assigned for the first time. */ struct JSXML; @@ -153,31 +119,39 @@ struct JSXML; namespace js { template -class HeapPtr +class EncapsulatedPtr { + protected: union { T *value; Unioned other; }; public: - HeapPtr() : value(NULL) {} - explicit HeapPtr(T *v) : value(v) { post(); } - explicit HeapPtr(const HeapPtr &v) : value(v.value) { post(); } + EncapsulatedPtr() : value(NULL) {} + explicit EncapsulatedPtr(T *v) : value(v) {} + explicit EncapsulatedPtr(const EncapsulatedPtr &v) : value(v.value) {} - ~HeapPtr() { pre(); } - - /* Use this to install a ptr into a newly allocated object. */ - void init(T *v) { - JS_ASSERT(!IsPoisonedPtr(v)); - value = v; - post(); - } + ~EncapsulatedPtr() { pre(); } /* Use to set the pointer to NULL. */ void clear() { - pre(); - value = NULL; + pre(); + value = NULL; + } + + EncapsulatedPtr &operator=(T *v) { + pre(); + JS_ASSERT(!IsPoisonedPtr(v)); + value = v; + return *this; + } + + EncapsulatedPtr &operator=(const EncapsulatedPtr &v) { + pre(); + JS_ASSERT(!IsPoisonedPtr(v.value)); + value = v.value; + return *this; } /* Use this if the automatic coercion to T* isn't working. */ @@ -192,30 +166,48 @@ class HeapPtr Unioned *unsafeGetUnioned() { return &other; } - HeapPtr &operator=(T *v) { - pre(); - JS_ASSERT(!IsPoisonedPtr(v)); - value = v; - post(); - return *this; - } - - HeapPtr &operator=(const HeapPtr &v) { - pre(); - JS_ASSERT(!IsPoisonedPtr(v.value)); - value = v.value; - post(); - return *this; - } - T &operator*() const { return *value; } T *operator->() const { return value; } operator T*() const { return value; } - private: + protected: void pre() { T::writeBarrierPre(value); } - void post() { T::writeBarrierPost(value, (void *)&value); } +}; + +template +class HeapPtr : public EncapsulatedPtr +{ + public: + HeapPtr() : EncapsulatedPtr(NULL) {} + explicit HeapPtr(T *v) : EncapsulatedPtr(v) { post(); } + explicit HeapPtr(const HeapPtr &v) + : EncapsulatedPtr(v) { post(); } + + void init(T *v) { + JS_ASSERT(!IsPoisonedPtr(v)); + this->value = v; + post(); + } + + HeapPtr &operator=(T *v) { + this->pre(); + JS_ASSERT(!IsPoisonedPtr(v)); + this->value = v; + post(); + return *this; + } + + HeapPtr &operator=(const HeapPtr &v) { + this->pre(); + JS_ASSERT(!IsPoisonedPtr(v.value)); + this->value = v.value; + post(); + return *this; + } + + protected: + void post() { T::writeBarrierPost(this->value, (void *)&this->value); } /* Make this friend so it can access pre() and post(). */ template @@ -225,6 +217,41 @@ class HeapPtr HeapPtr &v2, T2 *val2); }; +template +class RelocatablePtr : public EncapsulatedPtr +{ + public: + RelocatablePtr() : EncapsulatedPtr(NULL) {} + explicit RelocatablePtr(T *v) : EncapsulatedPtr(v) { post(); } + explicit RelocatablePtr(const RelocatablePtr &v) + : EncapsulatedPtr(v) { post(); } + + ~RelocatablePtr() { + this->pre(); + relocate(); + } + + RelocatablePtr &operator=(T *v) { + this->pre(); + JS_ASSERT(!IsPoisonedPtr(v)); + this->value = v; + post(); + return *this; + } + + RelocatablePtr &operator=(const RelocatablePtr &v) { + this->pre(); + JS_ASSERT(!IsPoisonedPtr(v.value)); + this->value = v.value; + post(); + return *this; + } + + protected: + void post() { T::writeBarrierRelocPost(this->value, (void *)&this->value); } + void relocate() { T::writeBarrierRelocated(this->value, (void *)&this->value); } +}; + /* * This is a hack for RegExpStatics::updateFromMatch. It allows us to do two * barriers with only one branch to check if we're in an incremental GC. @@ -249,7 +276,9 @@ struct Shape; class BaseShape; namespace types { struct TypeObject; } -typedef HeapPtr HeapPtrAtom; +typedef RelocatablePtr RelocatablePtrObject; +typedef RelocatablePtr RelocatablePtrScript; + typedef HeapPtr HeapPtrObject; typedef HeapPtr HeapPtrFunction; typedef HeapPtr HeapPtrString; @@ -272,9 +301,9 @@ struct HeapPtrHasher /* Specialized hashing policy for HeapPtrs. */ template -struct DefaultHasher< HeapPtr >: HeapPtrHasher { }; +struct DefaultHasher< HeapPtr > : HeapPtrHasher { }; -class EncapsulatedValue +class EncapsulatedValue : public ValueOperations { protected: Value value; @@ -292,47 +321,27 @@ class EncapsulatedValue ~EncapsulatedValue() {} public: + bool operator==(const EncapsulatedValue &v) const { return value == v.value; } + bool operator!=(const EncapsulatedValue &v) const { return value != v.value; } + const Value &get() const { return value; } Value *unsafeGet() { return &value; } operator const Value &() const { return value; } - bool isUndefined() const { return value.isUndefined(); } - bool isNull() const { return value.isNull(); } - bool isBoolean() const { return value.isBoolean(); } - bool isTrue() const { return value.isTrue(); } - bool isFalse() const { return value.isFalse(); } - bool isNumber() const { return value.isNumber(); } - bool isInt32() const { return value.isInt32(); } - bool isDouble() const { return value.isDouble(); } - bool isString() const { return value.isString(); } - bool isObject() const { return value.isObject(); } - bool isMagic(JSWhyMagic why) const { return value.isMagic(why); } - bool isGCThing() const { return value.isGCThing(); } - bool isMarkable() const { return value.isMarkable(); } - - bool toBoolean() const { return value.toBoolean(); } - double toNumber() const { return value.toNumber(); } - int32_t toInt32() const { return value.toInt32(); } - double toDouble() const { return value.toDouble(); } - JSString *toString() const { return value.toString(); } - JSObject &toObject() const { return value.toObject(); } - JSObject *toObjectOrNull() const { return value.toObjectOrNull(); } - void *toGCThing() const { return value.toGCThing(); } - JSGCTraceKind gcKind() const { return value.gcKind(); } uint64_t asRawBits() const { return value.asRawBits(); } -#ifdef DEBUG - JSWhyMagic whyMagic() const { return value.whyMagic(); } -#endif - static inline void writeBarrierPre(const Value &v); static inline void writeBarrierPre(JSCompartment *comp, const Value &v); protected: inline void pre(); inline void pre(JSCompartment *comp); + + private: + friend class ValueOperations; + const Value * extract() const { return &value; } }; class HeapValue : public EncapsulatedValue @@ -357,14 +366,31 @@ class HeapValue : public EncapsulatedValue */ inline void set(JSCompartment *comp, const Value &v); - static inline void writeBarrierPost(const Value &v, void *addr); - static inline void writeBarrierPost(JSCompartment *comp, const Value &v, void *addr); + static inline void writeBarrierPost(const Value &v, Value *addr); + static inline void writeBarrierPost(JSCompartment *comp, const Value &v, Value *addr); private: inline void post(); inline void post(JSCompartment *comp); }; +class RelocatableValue : public EncapsulatedValue +{ + public: + explicit inline RelocatableValue(); + explicit inline RelocatableValue(const Value &v); + explicit inline RelocatableValue(const RelocatableValue &v); + inline ~RelocatableValue(); + + inline RelocatableValue &operator=(const Value &v); + inline RelocatableValue &operator=(const RelocatableValue &v); + + private: + inline void post(); + inline void post(JSCompartment *comp); + inline void relocate(); +}; + class HeapSlot : public EncapsulatedValue { /* @@ -401,7 +427,7 @@ class HeapSlot : public EncapsulatedValue * Run a post write barrier that encompasses multiple contiguous slots in a * single step. */ -static inline void +inline void SlotRangeWriteBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t start, uint32_t count) { } @@ -414,6 +440,14 @@ Valueify(const EncapsulatedValue *array) return (const Value *)array; } +static inline HeapValue * +HeapValueify(Value *v) +{ + JS_STATIC_ASSERT(sizeof(HeapValue) == sizeof(Value)); + JS_STATIC_ASSERT(sizeof(HeapSlot) == sizeof(Value)); + return (HeapValue *)v; +} + class HeapSlotArray { HeapSlot *array; @@ -428,21 +462,20 @@ class HeapSlotArray HeapSlotArray operator +(uint32_t offset) const { return HeapSlotArray(array + offset); } }; -class HeapId +class EncapsulatedId { + protected: jsid value; + explicit EncapsulatedId() : value(JSID_VOID) {} + explicit inline EncapsulatedId(jsid id) : value(id) {} + ~EncapsulatedId() {} + + private: + EncapsulatedId(const EncapsulatedId &v) MOZ_DELETE; + EncapsulatedId &operator=(const EncapsulatedId &v) MOZ_DELETE; + public: - explicit HeapId() : value(JSID_VOID) {} - explicit inline HeapId(jsid id); - - inline ~HeapId(); - - inline void init(jsid id); - - inline HeapId &operator=(jsid id); - inline HeapId &operator=(const HeapId &v); - bool operator==(jsid id) const { return value == id; } bool operator!=(jsid id) const { return value != id; } @@ -450,11 +483,37 @@ class HeapId jsid *unsafeGet() { return &value; } operator jsid() const { return value; } - private: + protected: inline void pre(); +}; + +class RelocatableId : public EncapsulatedId +{ + public: + explicit RelocatableId() : EncapsulatedId() {} + explicit inline RelocatableId(jsid id) : EncapsulatedId(id) {} + inline ~RelocatableId(); + + inline RelocatableId &operator=(jsid id); + inline RelocatableId &operator=(const RelocatableId &v); +}; + +class HeapId : public EncapsulatedId +{ + public: + explicit HeapId() : EncapsulatedId() {} + explicit inline HeapId(jsid id); + inline ~HeapId(); + + inline void init(jsid id); + + inline HeapId &operator=(jsid id); + inline HeapId &operator=(const HeapId &v); + + private: inline void post(); - HeapId(const HeapId &v); + HeapId(const HeapId &v) MOZ_DELETE; }; /* @@ -488,7 +547,7 @@ class ReadBarriered T &operator*() const { return *get(); } T *operator->() const { return get(); } - T *unsafeGet() { return value; } + T **unsafeGet() { return &value; } void set(T *v) { value = v; } @@ -504,6 +563,7 @@ class ReadBarrieredValue ReadBarrieredValue(const Value &value) : value(value) {} inline const Value &get() const; + Value *unsafeGet() { return &value; } inline operator const Value &() const; inline JSObject &toObject() const; @@ -511,11 +571,11 @@ class ReadBarrieredValue namespace tl { -template struct IsPostBarrieredType > { - static const bool result = true; }; -template <> struct IsPostBarrieredType { static const bool result = true; }; -template <> struct IsPostBarrieredType { static const bool result = true; }; -template <> struct IsPostBarrieredType { static const bool result = true; }; +template struct IsRelocatableHeapType > + { static const bool result = false; }; +template <> struct IsRelocatableHeapType { static const bool result = false; }; +template <> struct IsRelocatableHeapType { static const bool result = false; }; +template <> struct IsRelocatableHeapType { static const bool result = false; }; } /* namespace tl */ } /* namespace js */ diff --git a/scripting/javascript/spidermonkey-android/include/gc/Heap.h b/scripting/javascript/spidermonkey-android/include/gc/Heap.h new file mode 100644 index 0000000000..5e9b939c12 --- /dev/null +++ b/scripting/javascript/spidermonkey-android/include/gc/Heap.h @@ -0,0 +1,978 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef gc_heap_h___ +#define gc_heap_h___ + +#include "mozilla/Attributes.h" +#include "mozilla/StandardInteger.h" + +#include + +#include "jstypes.h" +#include "jsutil.h" + +#include "ds/BitArray.h" + +struct JSCompartment; + +extern "C" { +struct JSRuntime; +} + +namespace js { + +class FreeOp; + +namespace gc { + +struct Arena; +struct ArenaHeader; +struct Chunk; + +/* + * Live objects are marked black. How many other additional colors are available + * depends on the size of the GCThing. Objects marked gray are eligible for + * cycle collection. + */ +static const uint32_t BLACK = 0; +static const uint32_t GRAY = 1; + +/* The GC allocation kinds. */ +enum AllocKind { + FINALIZE_OBJECT0, + FINALIZE_OBJECT0_BACKGROUND, + FINALIZE_OBJECT2, + FINALIZE_OBJECT2_BACKGROUND, + FINALIZE_OBJECT4, + FINALIZE_OBJECT4_BACKGROUND, + FINALIZE_OBJECT8, + FINALIZE_OBJECT8_BACKGROUND, + FINALIZE_OBJECT12, + FINALIZE_OBJECT12_BACKGROUND, + FINALIZE_OBJECT16, + FINALIZE_OBJECT16_BACKGROUND, + FINALIZE_OBJECT_LAST = FINALIZE_OBJECT16_BACKGROUND, + FINALIZE_SCRIPT, + FINALIZE_SHAPE, + FINALIZE_BASE_SHAPE, + FINALIZE_TYPE_OBJECT, +#if JS_HAS_XML_SUPPORT + FINALIZE_XML, +#endif + FINALIZE_SHORT_STRING, + FINALIZE_STRING, + FINALIZE_EXTERNAL_STRING, + FINALIZE_LAST = FINALIZE_EXTERNAL_STRING +}; + +static const unsigned FINALIZE_LIMIT = FINALIZE_LAST + 1; +static const unsigned FINALIZE_OBJECT_LIMIT = FINALIZE_OBJECT_LAST + 1; + +/* + * This must be an upper bound, but we do not need the least upper bound, so + * we just exclude non-background objects. + */ +static const size_t MAX_BACKGROUND_FINALIZE_KINDS = FINALIZE_LIMIT - FINALIZE_OBJECT_LIMIT / 2; + +/* + * A GC cell is the base class for all GC things. + */ +struct Cell +{ + static const size_t CellShift = 3; + static const size_t CellSize = size_t(1) << CellShift; + static const size_t CellMask = CellSize - 1; + + inline uintptr_t address() const; + inline ArenaHeader *arenaHeader() const; + inline Chunk *chunk() const; + inline AllocKind getAllocKind() const; + MOZ_ALWAYS_INLINE bool isMarked(uint32_t color = BLACK) const; + MOZ_ALWAYS_INLINE bool markIfUnmarked(uint32_t color = BLACK) const; + MOZ_ALWAYS_INLINE void unmark(uint32_t color) const; + + inline JSCompartment *compartment() const; + +#ifdef DEBUG + inline bool isAligned() const; +#endif +}; + +/* + * Page size is 4096 by default, except for SPARC, where it is 8192. + * Note: Do not use JS_CPU_SPARC here, this header is used outside JS. + * Bug 692267: Move page size definition to gc/Memory.h and include it + * directly once jsgc.h is no longer an installed header. + */ +#if defined(SOLARIS) && (defined(__sparc) || defined(__sparcv9)) +const size_t PageShift = 13; +#else +const size_t PageShift = 12; +#endif +const size_t PageSize = size_t(1) << PageShift; + +const size_t ChunkShift = 20; +const size_t ChunkSize = size_t(1) << ChunkShift; +const size_t ChunkMask = ChunkSize - 1; + +const size_t ArenaShift = PageShift; +const size_t ArenaSize = PageSize; +const size_t ArenaMask = ArenaSize - 1; + +/* + * This is the maximum number of arenas we allow in the FreeCommitted state + * before we trigger a GC_SHRINK to release free arenas to the OS. + */ +const static uint32_t FreeCommittedArenasThreshold = (32 << 20) / ArenaSize; + +/* + * The mark bitmap has one bit per each GC cell. For multi-cell GC things this + * wastes space but allows to avoid expensive devisions by thing's size when + * accessing the bitmap. In addition this allows to use some bits for colored + * marking during the cycle GC. + */ +const size_t ArenaCellCount = size_t(1) << (ArenaShift - Cell::CellShift); +const size_t ArenaBitmapBits = ArenaCellCount; +const size_t ArenaBitmapBytes = ArenaBitmapBits / 8; +const size_t ArenaBitmapWords = ArenaBitmapBits / JS_BITS_PER_WORD; + +/* + * A FreeSpan represents a contiguous sequence of free cells in an Arena. + * |first| is the address of the first free cell in the span. |last| is the + * address of the last free cell in the span. This last cell holds a FreeSpan + * data structure for the next span unless this is the last span on the list + * of spans in the arena. For this last span |last| points to the last byte of + * the last thing in the arena and no linkage is stored there, so + * |last| == arenaStart + ArenaSize - 1. If the space at the arena end is + * fully used this last span is empty and |first| == |last + 1|. + * + * Thus |first| < |last| implies that we have either the last span with at least + * one element or that the span is not the last and contains at least 2 + * elements. In both cases to allocate a thing from this span we need simply + * to increment |first| by the allocation size. + * + * |first| == |last| implies that we have a one element span that records the + * next span. So to allocate from it we need to update the span list head + * with a copy of the span stored at |last| address so the following + * allocations will use that span. + * + * |first| > |last| implies that we have an empty last span and the arena is + * fully used. + * + * Also only for the last span (|last| & 1)! = 0 as all allocation sizes are + * multiples of Cell::CellSize. + */ +struct FreeSpan +{ + uintptr_t first; + uintptr_t last; + + public: + FreeSpan() {} + + FreeSpan(uintptr_t first, uintptr_t last) + : first(first), last(last) { + checkSpan(); + } + + /* + * To minimize the size of the arena header the first span is encoded + * there as offsets from the arena start. + */ + static size_t encodeOffsets(size_t firstOffset, size_t lastOffset) { + /* Check that we can pack the offsets into uint16. */ + JS_STATIC_ASSERT(ArenaShift < 16); + JS_ASSERT(firstOffset <= ArenaSize); + JS_ASSERT(lastOffset < ArenaSize); + JS_ASSERT(firstOffset <= ((lastOffset + 1) & ~size_t(1))); + return firstOffset | (lastOffset << 16); + } + + /* + * Encoded offsets for a full arena when its first span is the last one + * and empty. + */ + static const size_t FullArenaOffsets = ArenaSize | ((ArenaSize - 1) << 16); + + static FreeSpan decodeOffsets(uintptr_t arenaAddr, size_t offsets) { + JS_ASSERT(!(arenaAddr & ArenaMask)); + + size_t firstOffset = offsets & 0xFFFF; + size_t lastOffset = offsets >> 16; + JS_ASSERT(firstOffset <= ArenaSize); + JS_ASSERT(lastOffset < ArenaSize); + + /* + * We must not use | when calculating first as firstOffset is + * ArenaMask + 1 for the empty span. + */ + return FreeSpan(arenaAddr + firstOffset, arenaAddr | lastOffset); + } + + void initAsEmpty(uintptr_t arenaAddr = 0) { + JS_ASSERT(!(arenaAddr & ArenaMask)); + first = arenaAddr + ArenaSize; + last = arenaAddr | (ArenaSize - 1); + JS_ASSERT(isEmpty()); + } + + bool isEmpty() const { + checkSpan(); + return first > last; + } + + bool hasNext() const { + checkSpan(); + return !(last & uintptr_t(1)); + } + + const FreeSpan *nextSpan() const { + JS_ASSERT(hasNext()); + return reinterpret_cast(last); + } + + FreeSpan *nextSpanUnchecked(size_t thingSize) const { +#ifdef DEBUG + uintptr_t lastOffset = last & ArenaMask; + JS_ASSERT(!(lastOffset & 1)); + JS_ASSERT((ArenaSize - lastOffset) % thingSize == 0); +#endif + return reinterpret_cast(last); + } + + uintptr_t arenaAddressUnchecked() const { + return last & ~ArenaMask; + } + + uintptr_t arenaAddress() const { + checkSpan(); + return arenaAddressUnchecked(); + } + + ArenaHeader *arenaHeader() const { + return reinterpret_cast(arenaAddress()); + } + + bool isSameNonEmptySpan(const FreeSpan *another) const { + JS_ASSERT(!isEmpty()); + JS_ASSERT(!another->isEmpty()); + return first == another->first && last == another->last; + } + + bool isWithinArena(uintptr_t arenaAddr) const { + JS_ASSERT(!(arenaAddr & ArenaMask)); + + /* Return true for the last empty span as well. */ + return arenaAddress() == arenaAddr; + } + + size_t encodeAsOffsets() const { + /* + * We must use first - arenaAddress(), not first & ArenaMask as + * first == ArenaMask + 1 for an empty span. + */ + uintptr_t arenaAddr = arenaAddress(); + return encodeOffsets(first - arenaAddr, last & ArenaMask); + } + + /* See comments before FreeSpan for details. */ + MOZ_ALWAYS_INLINE void *allocate(size_t thingSize) { + JS_ASSERT(thingSize % Cell::CellSize == 0); + checkSpan(); + uintptr_t thing = first; + if (thing < last) { + /* Bump-allocate from the current span. */ + first = thing + thingSize; + } else if (JS_LIKELY(thing == last)) { + /* + * Move to the next span. We use JS_LIKELY as without PGO + * compilers mis-predict == here as unlikely to succeed. + */ + *this = *reinterpret_cast(thing); + } else { + return NULL; + } + checkSpan(); + return reinterpret_cast(thing); + } + + /* A version of allocate when we know that the span is not empty. */ + MOZ_ALWAYS_INLINE void *infallibleAllocate(size_t thingSize) { + JS_ASSERT(thingSize % Cell::CellSize == 0); + checkSpan(); + uintptr_t thing = first; + if (thing < last) { + first = thing + thingSize; + } else { + JS_ASSERT(thing == last); + *this = *reinterpret_cast(thing); + } + checkSpan(); + return reinterpret_cast(thing); + } + + /* + * Allocate from a newly allocated arena. We do not move the free list + * from the arena. Rather we set the arena up as fully used during the + * initialization so to allocate we simply return the first thing in the + * arena and set the free list to point to the second. + */ + MOZ_ALWAYS_INLINE void *allocateFromNewArena(uintptr_t arenaAddr, size_t firstThingOffset, + size_t thingSize) { + JS_ASSERT(!(arenaAddr & ArenaMask)); + uintptr_t thing = arenaAddr | firstThingOffset; + first = thing + thingSize; + last = arenaAddr | ArenaMask; + checkSpan(); + return reinterpret_cast(thing); + } + + void checkSpan() const { +#ifdef DEBUG + /* We do not allow spans at the end of the address space. */ + JS_ASSERT(last != uintptr_t(-1)); + JS_ASSERT(first); + JS_ASSERT(last); + JS_ASSERT(first - 1 <= last); + uintptr_t arenaAddr = arenaAddressUnchecked(); + if (last & 1) { + /* The span is the last. */ + JS_ASSERT((last & ArenaMask) == ArenaMask); + + if (first - 1 == last) { + /* The span is last and empty. The above start != 0 check + * implies that we are not at the end of the address space. + */ + return; + } + size_t spanLength = last - first + 1; + JS_ASSERT(spanLength % Cell::CellSize == 0); + + /* Start and end must belong to the same arena. */ + JS_ASSERT((first & ~ArenaMask) == arenaAddr); + return; + } + + /* The span is not the last and we have more spans to follow. */ + JS_ASSERT(first <= last); + size_t spanLengthWithoutOneThing = last - first; + JS_ASSERT(spanLengthWithoutOneThing % Cell::CellSize == 0); + + JS_ASSERT((first & ~ArenaMask) == arenaAddr); + + /* + * If there is not enough space before the arena end to allocate one + * more thing, then the span must be marked as the last one to avoid + * storing useless empty span reference. + */ + size_t beforeTail = ArenaSize - (last & ArenaMask); + JS_ASSERT(beforeTail >= sizeof(FreeSpan) + Cell::CellSize); + + FreeSpan *next = reinterpret_cast(last); + + /* + * The GC things on the list of free spans come from one arena + * and the spans are linked in ascending address order with + * at least one non-free thing between spans. + */ + JS_ASSERT(last < next->first); + JS_ASSERT(arenaAddr == next->arenaAddressUnchecked()); + + if (next->first > next->last) { + /* + * The next span is the empty span that terminates the list for + * arenas that do not have any free things at the end. + */ + JS_ASSERT(next->first - 1 == next->last); + JS_ASSERT(arenaAddr + ArenaSize == next->first); + } +#endif + } + +}; + +/* Every arena has a header. */ +struct ArenaHeader +{ + friend struct FreeLists; + + JSCompartment *compartment; + + /* + * ArenaHeader::next has two purposes: when unallocated, it points to the + * next available Arena's header. When allocated, it points to the next + * arena of the same size class and compartment. + */ + ArenaHeader *next; + + private: + /* + * The first span of free things in the arena. We encode it as the start + * and end offsets within the arena, not as FreeSpan structure, to + * minimize the header size. + */ + size_t firstFreeSpanOffsets; + + /* + * One of AllocKind constants or FINALIZE_LIMIT when the arena does not + * contain any GC things and is on the list of empty arenas in the GC + * chunk. The latter allows to quickly check if the arena is allocated + * during the conservative GC scanning without searching the arena in the + * list. + */ + size_t allocKind : 8; + + /* + * When recursive marking uses too much stack the marking is delayed and + * the corresponding arenas are put into a stack using the following field + * as a linkage. To distinguish the bottom of the stack from the arenas + * not present in the stack we use an extra flag to tag arenas on the + * stack. + * + * Delayed marking is also used for arenas that we allocate into during an + * incremental GC. In this case, we intend to mark all the objects in the + * arena, and it's faster to do this marking in bulk. + * + * To minimize the ArenaHeader size we record the next delayed marking + * linkage as arenaAddress() >> ArenaShift and pack it with the allocKind + * field and hasDelayedMarking flag. We use 8 bits for the allocKind, not + * ArenaShift - 1, so the compiler can use byte-level memory instructions + * to access it. + */ + public: + size_t hasDelayedMarking : 1; + size_t allocatedDuringIncremental : 1; + size_t markOverflow : 1; + size_t nextDelayedMarking : JS_BITS_PER_WORD - 8 - 1 - 1 - 1; + + static void staticAsserts() { + /* We must be able to fit the allockind into uint8_t. */ + JS_STATIC_ASSERT(FINALIZE_LIMIT <= 255); + + /* + * nextDelayedMarkingpacking assumes that ArenaShift has enough bits + * to cover allocKind and hasDelayedMarking. + */ + JS_STATIC_ASSERT(ArenaShift >= 8 + 1 + 1 + 1); + } + + inline uintptr_t address() const; + inline Chunk *chunk() const; + + bool allocated() const { + JS_ASSERT(allocKind <= size_t(FINALIZE_LIMIT)); + return allocKind < size_t(FINALIZE_LIMIT); + } + + void init(JSCompartment *comp, AllocKind kind) { + JS_ASSERT(!allocated()); + JS_ASSERT(!markOverflow); + JS_ASSERT(!allocatedDuringIncremental); + JS_ASSERT(!hasDelayedMarking); + compartment = comp; + + JS_STATIC_ASSERT(FINALIZE_LIMIT <= 255); + allocKind = size_t(kind); + + /* See comments in FreeSpan::allocateFromNewArena. */ + firstFreeSpanOffsets = FreeSpan::FullArenaOffsets; + } + + void setAsNotAllocated() { + allocKind = size_t(FINALIZE_LIMIT); + markOverflow = 0; + allocatedDuringIncremental = 0; + hasDelayedMarking = 0; + nextDelayedMarking = 0; + } + + inline uintptr_t arenaAddress() const; + inline Arena *getArena(); + + AllocKind getAllocKind() const { + JS_ASSERT(allocated()); + return AllocKind(allocKind); + } + + inline size_t getThingSize() const; + + bool hasFreeThings() const { + return firstFreeSpanOffsets != FreeSpan::FullArenaOffsets; + } + + inline bool isEmpty() const; + + void setAsFullyUsed() { + firstFreeSpanOffsets = FreeSpan::FullArenaOffsets; + } + + inline FreeSpan getFirstFreeSpan() const; + inline void setFirstFreeSpan(const FreeSpan *span); + +#ifdef DEBUG + void checkSynchronizedWithFreeList() const; +#endif + + inline ArenaHeader *getNextDelayedMarking() const; + inline void setNextDelayedMarking(ArenaHeader *aheader); +}; + +struct Arena +{ + /* + * Layout of an arena: + * An arena is 4K in size and 4K-aligned. It starts with the ArenaHeader + * descriptor followed by some pad bytes. The remainder of the arena is + * filled with the array of T things. The pad bytes ensure that the thing + * array ends exactly at the end of the arena. + * + * +-------------+-----+----+----+-----+----+ + * | ArenaHeader | pad | T0 | T1 | ... | Tn | + * +-------------+-----+----+----+-----+----+ + * + * <----------------------------------------> = ArenaSize bytes + * <-------------------> = first thing offset + */ + ArenaHeader aheader; + uint8_t data[ArenaSize - sizeof(ArenaHeader)]; + + private: + static JS_FRIEND_DATA(const uint32_t) ThingSizes[]; + static JS_FRIEND_DATA(const uint32_t) FirstThingOffsets[]; + + public: + static void staticAsserts(); + + static size_t thingSize(AllocKind kind) { + return ThingSizes[kind]; + } + + static size_t firstThingOffset(AllocKind kind) { + return FirstThingOffsets[kind]; + } + + static size_t thingsPerArena(size_t thingSize) { + JS_ASSERT(thingSize % Cell::CellSize == 0); + + /* We should be able to fit FreeSpan in any GC thing. */ + JS_ASSERT(thingSize >= sizeof(FreeSpan)); + + return (ArenaSize - sizeof(ArenaHeader)) / thingSize; + } + + static size_t thingsSpan(size_t thingSize) { + return thingsPerArena(thingSize) * thingSize; + } + + static bool isAligned(uintptr_t thing, size_t thingSize) { + /* Things ends at the arena end. */ + uintptr_t tailOffset = (ArenaSize - thing) & ArenaMask; + return tailOffset % thingSize == 0; + } + + uintptr_t address() const { + return aheader.address(); + } + + uintptr_t thingsStart(AllocKind thingKind) { + return address() | firstThingOffset(thingKind); + } + + uintptr_t thingsEnd() { + return address() + ArenaSize; + } + + template + bool finalize(FreeOp *fop, AllocKind thingKind, size_t thingSize); +}; + +inline size_t +ArenaHeader::getThingSize() const +{ + JS_ASSERT(allocated()); + return Arena::thingSize(getAllocKind()); +} + +/* The chunk header (located at the end of the chunk to preserve arena alignment). */ +struct ChunkInfo +{ + Chunk *next; + Chunk **prevp; + + /* Free arenas are linked together with aheader.next. */ + ArenaHeader *freeArenasHead; + + /* + * Decommitted arenas are tracked by a bitmap in the chunk header. We use + * this offset to start our search iteration close to a decommitted arena + * that we can allocate. + */ + uint32_t lastDecommittedArenaOffset; + + /* Number of free arenas, either committed or decommitted. */ + uint32_t numArenasFree; + + /* Number of free, committed arenas. */ + uint32_t numArenasFreeCommitted; + + /* Number of GC cycles this chunk has survived. */ + uint32_t age; +}; + +/* + * Calculating ArenasPerChunk: + * + * In order to figure out how many Arenas will fit in a chunk, we need to know + * how much extra space is available after we allocate the header data. This + * is a problem because the header size depends on the number of arenas in the + * chunk. The two dependent fields are bitmap and decommittedArenas. + * + * For the mark bitmap, we know that each arena will use a fixed number of full + * bytes: ArenaBitmapBytes. The full size of the header data is this number + * multiplied by the eventual number of arenas we have in the header. We, + * conceptually, distribute this header data among the individual arenas and do + * not include it in the header. This way we do not have to worry about its + * variable size: it gets attached to the variable number we are computing. + * + * For the decommitted arena bitmap, we only have 1 bit per arena, so this + * technique will not work. Instead, we observe that we do not have enough + * header info to fill 8 full arenas: it is currently 4 on 64bit, less on + * 32bit. Thus, with current numbers, we need 64 bytes for decommittedArenas. + * This will not become 63 bytes unless we double the data required in the + * header. Therefore, we just compute the number of bytes required to track + * every possible arena and do not worry about slop bits, since there are too + * few to usefully allocate. + * + * To actually compute the number of arenas we can allocate in a chunk, we + * divide the amount of available space less the header info (not including + * the mark bitmap which is distributed into the arena size) by the size of + * the arena (with the mark bitmap bytes it uses). + */ +const size_t BytesPerArenaWithHeader = ArenaSize + ArenaBitmapBytes; +const size_t ChunkDecommitBitmapBytes = ChunkSize / ArenaSize / JS_BITS_PER_BYTE; +const size_t ChunkBytesAvailable = ChunkSize - sizeof(ChunkInfo) - ChunkDecommitBitmapBytes; +const size_t ArenasPerChunk = ChunkBytesAvailable / BytesPerArenaWithHeader; + +/* A chunk bitmap contains enough mark bits for all the cells in a chunk. */ +struct ChunkBitmap +{ + uintptr_t bitmap[ArenaBitmapWords * ArenasPerChunk]; + + MOZ_ALWAYS_INLINE void getMarkWordAndMask(const Cell *cell, uint32_t color, + uintptr_t **wordp, uintptr_t *maskp); + + MOZ_ALWAYS_INLINE bool isMarked(const Cell *cell, uint32_t color) { + uintptr_t *word, mask; + getMarkWordAndMask(cell, color, &word, &mask); + return *word & mask; + } + + MOZ_ALWAYS_INLINE bool markIfUnmarked(const Cell *cell, uint32_t color) { + uintptr_t *word, mask; + getMarkWordAndMask(cell, BLACK, &word, &mask); + if (*word & mask) + return false; + *word |= mask; + if (color != BLACK) { + /* + * We use getMarkWordAndMask to recalculate both mask and word as + * doing just mask << color may overflow the mask. + */ + getMarkWordAndMask(cell, color, &word, &mask); + if (*word & mask) + return false; + *word |= mask; + } + return true; + } + + MOZ_ALWAYS_INLINE void unmark(const Cell *cell, uint32_t color) { + uintptr_t *word, mask; + getMarkWordAndMask(cell, color, &word, &mask); + *word &= ~mask; + } + + void clear() { + PodArrayZero(bitmap); + } + + uintptr_t *arenaBits(ArenaHeader *aheader) { + /* + * We assume that the part of the bitmap corresponding to the arena + * has the exact number of words so we do not need to deal with a word + * that covers bits from two arenas. + */ + JS_STATIC_ASSERT(ArenaBitmapBits == ArenaBitmapWords * JS_BITS_PER_WORD); + + uintptr_t *word, unused; + getMarkWordAndMask(reinterpret_cast(aheader->address()), BLACK, &word, &unused); + return word; + } +}; + +JS_STATIC_ASSERT(ArenaBitmapBytes * ArenasPerChunk == sizeof(ChunkBitmap)); + +typedef BitArray PerArenaBitmap; + +const size_t ChunkPadSize = ChunkSize + - (sizeof(Arena) * ArenasPerChunk) + - sizeof(ChunkBitmap) + - sizeof(PerArenaBitmap) + - sizeof(ChunkInfo); +JS_STATIC_ASSERT(ChunkPadSize < BytesPerArenaWithHeader); + +/* + * Chunks contain arenas and associated data structures (mark bitmap, delayed + * marking state). + */ +struct Chunk +{ + Arena arenas[ArenasPerChunk]; + + /* Pad to full size to ensure cache alignment of ChunkInfo. */ + uint8_t padding[ChunkPadSize]; + + ChunkBitmap bitmap; + PerArenaBitmap decommittedArenas; + ChunkInfo info; + + static Chunk *fromAddress(uintptr_t addr) { + addr &= ~ChunkMask; + return reinterpret_cast(addr); + } + + static bool withinArenasRange(uintptr_t addr) { + uintptr_t offset = addr & ChunkMask; + return offset < ArenasPerChunk * ArenaSize; + } + + static size_t arenaIndex(uintptr_t addr) { + JS_ASSERT(withinArenasRange(addr)); + return (addr & ChunkMask) >> ArenaShift; + } + + uintptr_t address() const { + uintptr_t addr = reinterpret_cast(this); + JS_ASSERT(!(addr & ChunkMask)); + return addr; + } + + bool unused() const { + return info.numArenasFree == ArenasPerChunk; + } + + bool hasAvailableArenas() const { + return info.numArenasFree != 0; + } + + inline void addToAvailableList(JSCompartment *compartment); + inline void insertToAvailableList(Chunk **insertPoint); + inline void removeFromAvailableList(); + + ArenaHeader *allocateArena(JSCompartment *comp, AllocKind kind); + + void releaseArena(ArenaHeader *aheader); + + static Chunk *allocate(JSRuntime *rt); + + /* Must be called with the GC lock taken. */ + static inline void release(JSRuntime *rt, Chunk *chunk); + static inline void releaseList(JSRuntime *rt, Chunk *chunkListHead); + + /* Must be called with the GC lock taken. */ + inline void prepareToBeFreed(JSRuntime *rt); + + /* + * Assuming that the info.prevp points to the next field of the previous + * chunk in a doubly-linked list, get that chunk. + */ + Chunk *getPrevious() { + JS_ASSERT(info.prevp); + return fromPointerToNext(info.prevp); + } + + /* Get the chunk from a pointer to its info.next field. */ + static Chunk *fromPointerToNext(Chunk **nextFieldPtr) { + uintptr_t addr = reinterpret_cast(nextFieldPtr); + JS_ASSERT((addr & ChunkMask) == offsetof(Chunk, info.next)); + return reinterpret_cast(addr - offsetof(Chunk, info.next)); + } + + private: + inline void init(); + + /* Search for a decommitted arena to allocate. */ + unsigned findDecommittedArenaOffset(); + ArenaHeader* fetchNextDecommittedArena(); + + public: + /* Unlink and return the freeArenasHead. */ + inline ArenaHeader* fetchNextFreeArena(JSRuntime *rt); + + inline void addArenaToFreeList(JSRuntime *rt, ArenaHeader *aheader); +}; + +JS_STATIC_ASSERT(sizeof(Chunk) == ChunkSize); + +inline uintptr_t +Cell::address() const +{ + uintptr_t addr = uintptr_t(this); + JS_ASSERT(addr % Cell::CellSize == 0); + JS_ASSERT(Chunk::withinArenasRange(addr)); + return addr; +} + +inline uintptr_t +ArenaHeader::address() const +{ + uintptr_t addr = reinterpret_cast(this); + JS_ASSERT(!(addr & ArenaMask)); + JS_ASSERT(Chunk::withinArenasRange(addr)); + return addr; +} + +inline Chunk * +ArenaHeader::chunk() const +{ + return Chunk::fromAddress(address()); +} + +inline uintptr_t +ArenaHeader::arenaAddress() const +{ + return address(); +} + +inline Arena * +ArenaHeader::getArena() +{ + return reinterpret_cast(arenaAddress()); +} + +inline bool +ArenaHeader::isEmpty() const +{ + /* Arena is empty if its first span covers the whole arena. */ + JS_ASSERT(allocated()); + size_t firstThingOffset = Arena::firstThingOffset(getAllocKind()); + return firstFreeSpanOffsets == FreeSpan::encodeOffsets(firstThingOffset, ArenaMask); +} + +FreeSpan +ArenaHeader::getFirstFreeSpan() const +{ +#ifdef DEBUG + checkSynchronizedWithFreeList(); +#endif + return FreeSpan::decodeOffsets(arenaAddress(), firstFreeSpanOffsets); +} + +void +ArenaHeader::setFirstFreeSpan(const FreeSpan *span) +{ + JS_ASSERT(span->isWithinArena(arenaAddress())); + firstFreeSpanOffsets = span->encodeAsOffsets(); +} + +inline ArenaHeader * +ArenaHeader::getNextDelayedMarking() const +{ + return &reinterpret_cast(nextDelayedMarking << ArenaShift)->aheader; +} + +inline void +ArenaHeader::setNextDelayedMarking(ArenaHeader *aheader) +{ + JS_ASSERT(!(uintptr_t(aheader) & ArenaMask)); + hasDelayedMarking = 1; + nextDelayedMarking = aheader->arenaAddress() >> ArenaShift; +} + +JS_ALWAYS_INLINE void +ChunkBitmap::getMarkWordAndMask(const Cell *cell, uint32_t color, + uintptr_t **wordp, uintptr_t *maskp) +{ + size_t bit = (cell->address() & ChunkMask) / Cell::CellSize + color; + JS_ASSERT(bit < ArenaBitmapBits * ArenasPerChunk); + *maskp = uintptr_t(1) << (bit % JS_BITS_PER_WORD); + *wordp = &bitmap[bit / JS_BITS_PER_WORD]; +} + +static void +AssertValidColor(const void *thing, uint32_t color) +{ +#ifdef DEBUG + ArenaHeader *aheader = reinterpret_cast(thing)->arenaHeader(); + JS_ASSERT_IF(color, color < aheader->getThingSize() / Cell::CellSize); +#endif +} + +inline ArenaHeader * +Cell::arenaHeader() const +{ + uintptr_t addr = address(); + addr &= ~ArenaMask; + return reinterpret_cast(addr); +} + +Chunk * +Cell::chunk() const +{ + uintptr_t addr = uintptr_t(this); + JS_ASSERT(addr % Cell::CellSize == 0); + addr &= ~(ChunkSize - 1); + return reinterpret_cast(addr); +} + +AllocKind +Cell::getAllocKind() const +{ + return arenaHeader()->getAllocKind(); +} + +bool +Cell::isMarked(uint32_t color /* = BLACK */) const +{ + AssertValidColor(this, color); + return chunk()->bitmap.isMarked(this, color); +} + +bool +Cell::markIfUnmarked(uint32_t color /* = BLACK */) const +{ + AssertValidColor(this, color); + return chunk()->bitmap.markIfUnmarked(this, color); +} + +void +Cell::unmark(uint32_t color) const +{ + JS_ASSERT(color != BLACK); + AssertValidColor(this, color); + chunk()->bitmap.unmark(this, color); +} + +JSCompartment * +Cell::compartment() const +{ + return arenaHeader()->compartment; +} + +#ifdef DEBUG +bool +Cell::isAligned() const +{ + return Arena::isAligned(address(), arenaHeader()->getThingSize()); +} +#endif + +} /* namespace gc */ + +} /* namespace js */ + +#endif /* gc_heap_h___ */ diff --git a/scripting/javascript/spidermonkey-android/include/gc/Root.h b/scripting/javascript/spidermonkey-android/include/gc/Root.h index 8a5bd699fc..4ada9966b8 100644 --- a/scripting/javascript/spidermonkey-android/include/gc/Root.h +++ b/scripting/javascript/spidermonkey-android/include/gc/Root.h @@ -1,51 +1,22 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=78: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is SpiderMonkey global object code. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2012 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsgc_root_h__ #define jsgc_root_h__ -#include "jspubtd.h" - -#include "js/Utility.h" - #ifdef __cplusplus +#include "mozilla/TypeTraits.h" + +#include "jsapi.h" + +#include "js/TemplateLib.h" +#include "js/Utility.h" + namespace JS { /* @@ -76,75 +47,159 @@ namespace JS { * on the type T of the value being rooted, for which RootMethods must * have an instantiation. * - * - Root roots an existing stack allocated variable or other location of - * type T. This is typically used either when a variable only needs to be - * rooted on certain rare paths, or when a function takes a bare GC thing - * pointer as an argument and needs to root it. In the latter case a - * Handle is generally preferred, see below. + * - Rooted declares a variable of type T, whose value is always rooted. + * Rooted may be automatically coerced to a Handle, below. Rooted + * should be used whenever a local variable's value may be held live across a + * call which can allocate GC things or otherwise trigger a GC. * - * - RootedVar declares a variable of type T, whose value is always rooted. - * - * - Handle is a const reference to a Root or RootedVar. Handles are - * coerced automatically from such a Root or RootedVar. Functions which - * take GC things or values as arguments and need to root those arguments - * should generally replace those arguments with handles and avoid any - * explicit rooting. This has two benefits. First, when several such - * functions call each other then redundant rooting of multiple copies of the - * GC thing can be avoided. Second, if the caller does not pass a rooted - * value a compile error will be generated, which is quicker and easier to - * fix than when relying on a separate rooting analysis. + * - Handle is a const reference to a Rooted. Functions which take GC + * things or values as arguments and need to root those arguments should + * generally use handles for those arguments and avoid any explicit rooting. + * This has two benefits. First, when several such functions call each other + * then redundant rooting of multiple copies of the GC thing can be avoided. + * Second, if the caller does not pass a rooted value a compile error will be + * generated, which is quicker and easier to fix than when relying on a + * separate rooting analysis. */ -template class Root; -template class RootedVar; +template class Rooted; template struct RootMethods { }; /* - * Reference to a stack location rooted for GC. See the "Moving GC Stack - * Rooting" comment above. + * Handle provides an implicit constructor for NullPtr so that, given: + * foo(Handle h); + * callers can simply write: + * foo(NullPtr()); + * which avoids creating a Rooted just to pass NULL. + */ +struct NullPtr +{ + static void * const constNullValue; +}; + +template +class HandleBase {}; + +/* + * Reference to a T that has been rooted elsewhere. This is most useful + * as a parameter type, which guarantees that the T lvalue is properly + * rooted. See "Move GC Stack Rooting" above. + * + * If you want to add additional methods to Handle for a specific + * specialization, define a HandleBase specialization containing them. */ template -class Handle +class Handle : public HandleBase { public: - /* Copy handles of different types, with implicit coercion. */ - template Handle(Handle handle) { - testAssign(); + /* Creates a handle from a handle of a type convertible to T. */ + template + Handle(Handle handle, + typename mozilla::EnableIf::value, int>::Type dummy = 0) + { ptr = reinterpret_cast(handle.address()); } - /* Get a handle from a rooted stack location, with implicit coercion. */ - template inline Handle(const Root &root); - template inline Handle(const RootedVar &root); + /* Create a handle for a NULL pointer. */ + Handle(NullPtr) { + typedef typename js::tl::StaticAssert::result>::result _; + ptr = reinterpret_cast(&NullPtr::constNullValue); + } - const T *address() { return ptr; } + /* + * This may be called only if the location of the T is guaranteed + * to be marked (for some reason other than being a Rooted), + * e.g., if it is guaranteed to be reachable from an implicit root. + * + * Create a Handle from a raw location of a T. + */ + static Handle fromMarkedLocation(const T *p) { + Handle h; + h.ptr = p; + return h; + } - operator T () { return value(); } - T operator ->() { return value(); } + /* + * Construct a handle from an explicitly rooted location. This is the + * normal way to create a handle, and normally happens implicitly. + */ + template + inline + Handle(Rooted &root, + typename mozilla::EnableIf::value, int>::Type dummy = 0); + + const T *address() const { return ptr; } + T get() const { return *ptr; } + + operator T () const { return get(); } + T operator ->() const { return get(); } private: + Handle() {} + const T *ptr; - T value() { return *ptr; } template - void testAssign() { -#ifdef DEBUG - T a = RootMethods::initial(); - S b = RootMethods::initial(); - a = b; - (void)a; -#endif - } + void operator =(S v) MOZ_DELETE; }; typedef Handle HandleObject; typedef Handle HandleFunction; +typedef Handle HandleScript; typedef Handle HandleString; typedef Handle HandleId; typedef Handle HandleValue; +template +class MutableHandleBase {}; + +/* + * Similar to a handle, but the underlying storage can be changed. This is + * useful for outparams. + * + * If you want to add additional methods to MutableHandle for a specific + * specialization, define a MutableHandleBase specialization containing + * them. + */ +template +class MutableHandle : public MutableHandleBase +{ + public: + template + MutableHandle(MutableHandle handle, + typename mozilla::EnableIf::value, int>::Type dummy = 0) + { + this->ptr = reinterpret_cast(handle.address()); + } + + template + inline + MutableHandle(Rooted *root, + typename mozilla::EnableIf::value, int>::Type dummy = 0); + + void set(T v) + { + JS_ASSERT(!RootMethods::poisoned(v)); + *ptr = v; + } + + T *address() const { return ptr; } + T get() const { return *ptr; } + + operator T () const { return get(); } + T operator ->() const { return get(); } + + private: + MutableHandle() {} + + T *ptr; +}; + +typedef MutableHandle MutableHandleObject; +typedef MutableHandle MutableHandleValue; + template struct RootMethods { @@ -153,76 +208,103 @@ struct RootMethods static bool poisoned(T *v) { return IsPoisonedPtr(v); } }; +template +class RootedBase {}; + /* - * Root a stack location holding a GC thing. This takes a stack pointer - * and ensures that throughout its lifetime the referenced variable - * will remain pinned against a moving GC. + * Local variable of type T whose value is always rooted. This is typically + * used for local variables, or for non-rooted values being passed to a + * function that requires a handle, e.g. Foo(Root(cx, x)). * - * It is important to ensure that the location referenced by a Root is - * initialized, as otherwise the GC may try to use the the uninitialized value. - * It is generally preferable to use either RootedVar for local variables, or - * Handle for arguments. + * If you want to add additional methods to Rooted for a specific + * specialization, define a RootedBase specialization containing them. */ template -class Root +class Rooted : public RootedBase { - public: - Root(JSContext *cx_, const T *ptr - JS_GUARD_OBJECT_NOTIFIER_PARAM) + void init(JSContext *cx_) { -#ifdef JSGC_ROOT_ANALYSIS +#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING) ContextFriendFields *cx = ContextFriendFields::get(cx_); ThingRootKind kind = RootMethods::kind(); - this->stack = reinterpret_cast**>(&cx->thingGCRooters[kind]); + this->stack = reinterpret_cast**>(&cx->thingGCRooters[kind]); this->prev = *stack; *stack = this; + + JS_ASSERT(!RootMethods::poisoned(ptr)); #endif - - JS_ASSERT(!RootMethods::poisoned(*ptr)); - - this->ptr = ptr; - - JS_GUARD_OBJECT_NOTIFIER_INIT; } - ~Root() + public: + Rooted(JSContext *cx) : ptr(RootMethods::initial()) { init(cx); } + Rooted(JSContext *cx, T initial) : ptr(initial) { init(cx); } + + ~Rooted() { -#ifdef JSGC_ROOT_ANALYSIS +#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING) JS_ASSERT(*stack == this); *stack = prev; #endif } -#ifdef JSGC_ROOT_ANALYSIS - Root *previous() { return prev; } +#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING) + Rooted *previous() { return prev; } #endif - const T *address() const { return ptr; } + operator T () const { return ptr; } + T operator ->() const { return ptr; } + T * address() { return &ptr; } + const T * address() const { return &ptr; } + T & get() { return ptr; } + const T & get() const { return ptr; } + + T & operator =(T value) + { + JS_ASSERT(!RootMethods::poisoned(value)); + ptr = value; + return ptr; + } + + T & operator =(const Rooted &value) + { + ptr = value; + return ptr; + } private: -#ifdef JSGC_ROOT_ANALYSIS - Root **stack, *prev; +#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING) + Rooted **stack, *prev; #endif - const T *ptr; + T ptr; - JS_DECL_USE_GUARD_OBJECT_NOTIFIER + Rooted() MOZ_DELETE; + Rooted(const Rooted &) MOZ_DELETE; }; template template inline -Handle::Handle(const Root &root) +Handle::Handle(Rooted &root, + typename mozilla::EnableIf::value, int>::Type dummy) { - testAssign(); ptr = reinterpret_cast(root.address()); } -typedef Root RootObject; -typedef Root RootFunction; -typedef Root RootString; -typedef Root RootId; -typedef Root RootValue; +template template +inline +MutableHandle::MutableHandle(Rooted *root, + typename mozilla::EnableIf::value, int>::Type dummy) +{ + ptr = root->address(); +} + +typedef Rooted RootedObject; +typedef Rooted RootedFunction; +typedef Rooted RootedScript; +typedef Rooted RootedString; +typedef Rooted RootedId; +typedef Rooted RootedValue; /* * Mark a stack location as a root for the rooting analysis, without actually @@ -238,18 +320,30 @@ class SkipRoot const uint8_t *start; const uint8_t *end; - public: template - SkipRoot(JSContext *cx_, const T *ptr - JS_GUARD_OBJECT_NOTIFIER_PARAM) + void init(ContextFriendFields *cx, const T *ptr, size_t count) { - ContextFriendFields *cx = ContextFriendFields::get(cx_); - this->stack = &cx->skipGCRooters; this->prev = *stack; *stack = this; this->start = (const uint8_t *) ptr; - this->end = this->start + sizeof(T); + this->end = this->start + (sizeof(T) * count); + } + + public: + template + SkipRoot(JSContext *cx, const T *ptr + JS_GUARD_OBJECT_NOTIFIER_PARAM) + { + init(ContextFriendFields::get(cx), ptr, 1); + JS_GUARD_OBJECT_NOTIFIER_INIT; + } + + template + SkipRoot(JSContext *cx, const T *ptr, size_t count + JS_GUARD_OBJECT_NOTIFIER_PARAM) + { + init(ContextFriendFields::get(cx), ptr, count); JS_GUARD_OBJECT_NOTIFIER_INIT; } @@ -275,74 +369,66 @@ class SkipRoot JS_GUARD_OBJECT_NOTIFIER_INIT; } + template + SkipRoot(JSContext *cx, const T *ptr, size_t count + JS_GUARD_OBJECT_NOTIFIER_PARAM) + { + JS_GUARD_OBJECT_NOTIFIER_INIT; + } + #endif /* DEBUG && JSGC_ROOT_ANALYSIS */ JS_DECL_USE_GUARD_OBJECT_NOTIFIER }; -/* Make a local variable which stays rooted throughout its lifetime. */ -template -class RootedVar -{ - public: - RootedVar(JSContext *cx) - : ptr(RootMethods::initial()), root(cx, &ptr) - {} +#ifdef DEBUG +JS_FRIEND_API(bool) IsRootingUnnecessaryForContext(JSContext *cx); +JS_FRIEND_API(void) SetRootingUnnecessaryForContext(JSContext *cx, bool value); +JS_FRIEND_API(bool) RelaxRootChecksForContext(JSContext *cx); +#endif - RootedVar(JSContext *cx, T initial) - : ptr(initial), root(cx, &ptr) - {} - - operator T () const { return ptr; } - T operator ->() const { return ptr; } - T * address() { return &ptr; } - const T * address() const { return &ptr; } - T & reference() { return ptr; } - T raw() { return ptr; } - - /* - * This method is only necessary due to an obscure C++98 requirement (that - * there be an accessible, usable copy constructor when passing a temporary - * to an implicitly-called constructor for use with a const-ref parameter). - * (Head spinning yet?) We can remove this when we build the JS engine - * with -std=c++11. - */ - operator Handle () const { return Handle(*this); } - - T & operator =(T value) +class AssertRootingUnnecessary { + JS_DECL_USE_GUARD_OBJECT_NOTIFIER + JSContext *cx; + bool prev; +public: + AssertRootingUnnecessary(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM) + : cx(cx) { - JS_ASSERT(!RootMethods::poisoned(value)); - ptr = value; - return ptr; + JS_GUARD_OBJECT_NOTIFIER_INIT; +#ifdef DEBUG + prev = IsRootingUnnecessaryForContext(cx); + SetRootingUnnecessaryForContext(cx, true); +#endif } - T & operator =(const RootedVar &value) - { - ptr = value; - return ptr; + ~AssertRootingUnnecessary() { +#ifdef DEBUG + SetRootingUnnecessaryForContext(cx, prev); +#endif } - - private: - T ptr; - Root root; - - RootedVar() MOZ_DELETE; - RootedVar(const RootedVar &) MOZ_DELETE; }; -template template -inline -Handle::Handle(const RootedVar &root) -{ - testAssign(); - ptr = reinterpret_cast(root.address()); -} +#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE) +extern void +CheckStackRoots(JSContext *cx); +#endif -typedef RootedVar RootedVarObject; -typedef RootedVar RootedVarFunction; -typedef RootedVar RootedVarString; -typedef RootedVar RootedVarId; -typedef RootedVar RootedVarValue; +/* + * Hook for dynamic root analysis. Checks the native stack and poisons + * references to GC things which have not been rooted. + */ +inline void MaybeCheckStackRoots(JSContext *cx, bool relax = true) +{ +#ifdef DEBUG + JS_ASSERT(!IsRootingUnnecessaryForContext(cx)); +# if defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE) + if (relax && RelaxRootChecksForContext(cx)) + return; + CheckStackRoots(cx); +# endif +#endif +} } /* namespace JS */ diff --git a/scripting/javascript/spidermonkey-android/include/gc/Statistics.h b/scripting/javascript/spidermonkey-android/include/gc/Statistics.h index cbc6d637a0..5b4e355f0b 100644 --- a/scripting/javascript/spidermonkey-android/include/gc/Statistics.h +++ b/scripting/javascript/spidermonkey-android/include/gc/Statistics.h @@ -1,41 +1,9 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=78: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is SpiderMonkey JavaScript engine. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsgc_statistics_h___ #define jsgc_statistics_h___ @@ -56,19 +24,26 @@ enum Phase { PHASE_WAIT_BACKGROUND_THREAD, PHASE_PURGE, PHASE_MARK, + PHASE_MARK_DISCARD_CODE, PHASE_MARK_ROOTS, + PHASE_MARK_TYPES, PHASE_MARK_DELAYED, - PHASE_MARK_OTHER, + PHASE_MARK_WEAK, + PHASE_MARK_GRAY, + PHASE_MARK_GRAY_WEAK, PHASE_FINALIZE_START, PHASE_SWEEP, + PHASE_SWEEP_ATOMS, PHASE_SWEEP_COMPARTMENTS, + PHASE_SWEEP_TABLES, PHASE_SWEEP_OBJECT, PHASE_SWEEP_STRING, PHASE_SWEEP_SCRIPT, PHASE_SWEEP_SHAPE, - PHASE_DISCARD_CODE, + PHASE_SWEEP_DISCARD_CODE, PHASE_DISCARD_ANALYSIS, PHASE_DISCARD_TI, + PHASE_FREE_TI_ARENA, PHASE_SWEEP_TYPES, PHASE_CLEAR_SCRIPT_ANALYSIS, PHASE_FINALIZE_END, @@ -116,13 +91,19 @@ struct Statistics { FILE *fp; bool fullFormat; + /* + * GCs can't really nest, but a second GC can be triggered from within the + * JSGC_END callback. + */ + int gcDepth; + int collectedCount; int compartmentCount; const char *nonincrementalReason; struct SliceData { - SliceData(gcreason::Reason reason, int64_t start) - : reason(reason), resetReason(NULL), start(start) + SliceData(gcreason::Reason reason, int64_t start, size_t startFaults) + : reason(reason), resetReason(NULL), start(start), startFaults(startFaults) { PodArrayZero(phaseTimes); } @@ -130,6 +111,7 @@ struct Statistics { gcreason::Reason reason; const char *resetReason; int64_t start, end; + size_t startFaults, endFaults; int64_t phaseTimes[PHASE_LIMIT]; int64_t duration() const { return end - start; } @@ -138,7 +120,7 @@ struct Statistics { Vector slices; /* Most recent time when the given phase started. */ - int64_t phaseStarts[PHASE_LIMIT]; + int64_t phaseStartTimes[PHASE_LIMIT]; /* Total time in a given phase for this GC. */ int64_t phaseTimes[PHASE_LIMIT]; diff --git a/scripting/javascript/spidermonkey-android/include/js-config.h b/scripting/javascript/spidermonkey-android/include/js-config.h index 21141c208f..87155a91fa 100644 --- a/scripting/javascript/spidermonkey-android/include/js-config.h +++ b/scripting/javascript/spidermonkey-android/include/js-config.h @@ -2,42 +2,9 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=78: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef js_config_h___ #define js_config_h___ @@ -54,7 +21,7 @@ /* Define to 1 if SpiderMonkey should support the ability to perform entirely too much GC. */ -/* #undef JS_GC_ZEAL */ +#define JS_GC_ZEAL 1 /* Define to 1 if the header is present and useable. See jscpucfg.h. */ @@ -96,4 +63,7 @@ correct. */ /* #undef JS_METHODJIT */ +/* Define to 1 to enable support for E4X (ECMA-357), 0 to disable it. */ +#define JS_HAS_XML_SUPPORT 1 + #endif /* js_config_h___ */ diff --git a/scripting/javascript/spidermonkey-android/include/js.msg b/scripting/javascript/spidermonkey-android/include/js.msg index befefd571c..e30c87b1f0 100644 --- a/scripting/javascript/spidermonkey-android/include/js.msg +++ b/scripting/javascript/spidermonkey-android/include/js.msg @@ -1,41 +1,8 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This is the JavaScript error message file. @@ -147,8 +114,8 @@ MSG_DEF(JSMSG_CANT_OPEN, 60, 2, JSEXN_ERR, "can't open {0}: {1}") MSG_DEF(JSMSG_TOO_MANY_FUN_APPLY_ARGS, 61, 0, JSEXN_RANGEERR, "arguments array passed to Function.prototype.apply is too large") MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 62, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression") MSG_DEF(JSMSG_TOO_BIG_TO_ENCODE, 63, 0, JSEXN_INTERNALERR, "data are to big to encode") -MSG_DEF(JSMSG_UNUSED64, 64, 0, JSEXN_NONE, "") -MSG_DEF(JSMSG_UNUSED65, 65, 0, JSEXN_NONE, "") +MSG_DEF(JSMSG_ARG_INDEX_OUT_OF_RANGE, 64, 1, JSEXN_RANGEERR, "argument {0} accesses an index that is out of range") +MSG_DEF(JSMSG_SPREAD_TOO_LARGE, 65, 0, JSEXN_RANGEERR, "array too large due to spread operand(s)") MSG_DEF(JSMSG_UNUSED66, 66, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_UNUSED67, 67, 0, JSEXN_NONE, "") MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC, 68, 0, JSEXN_INTERNALERR, "bad script XDR magic number") @@ -258,7 +225,7 @@ MSG_DEF(JSMSG_BAD_XML_CHARACTER, 171, 0, JSEXN_SYNTAXERR, "illegal XML char MSG_DEF(JSMSG_BAD_DEFAULT_XML_NAMESPACE,172,0,JSEXN_SYNTAXERR, "invalid default XML namespace") MSG_DEF(JSMSG_BAD_XML_NAME_SYNTAX, 173, 0, JSEXN_SYNTAXERR, "invalid XML name") MSG_DEF(JSMSG_BRACKET_AFTER_ATTR_EXPR,174, 0, JSEXN_SYNTAXERR, "missing ] after attribute expression") -MSG_DEF(JSMSG_NESTING_GENERATOR, 175, 1, JSEXN_TYPEERR, "already executing generator {0}") +MSG_DEF(JSMSG_NESTING_GENERATOR, 175, 0, JSEXN_TYPEERR, "already executing generator") MSG_DEF(JSMSG_CURLY_IN_XML_EXPR, 176, 0, JSEXN_SYNTAXERR, "missing } in XML expression") MSG_DEF(JSMSG_BAD_XML_NAMESPACE, 177, 1, JSEXN_TYPEERR, "invalid XML namespace {0}") MSG_DEF(JSMSG_BAD_XML_ATTR_NAME, 178, 1, JSEXN_TYPEERR, "invalid XML attribute name {0}") @@ -378,4 +345,10 @@ MSG_DEF(JSMSG_NOT_ITERABLE, 291, 1, JSEXN_TYPEERR, "{0} is not iterabl MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 292, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'url' property") MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 293, 0, JSEXN_TYPEERR, "findScripts query object has 'innermost' property without both 'url' and 'line' properties") MSG_DEF(JSMSG_DEBUG_VARIABLE_NOT_FOUND, 294, 0, JSEXN_TYPEERR, "variable not found in environment") - +MSG_DEF(JSMSG_PARAMETER_AFTER_REST, 295, 0, JSEXN_SYNTAXERR, "parameter after rest parameter") +MSG_DEF(JSMSG_NO_REST_NAME, 296, 0, JSEXN_SYNTAXERR, "no parameter name after ...") +MSG_DEF(JSMSG_ARGUMENTS_AND_REST, 297, 0, JSEXN_SYNTAXERR, "'arguments' object may not be used in conjunction with a rest parameter") +MSG_DEF(JSMSG_FUNCTION_ARGUMENTS_AND_REST, 298, 0, JSEXN_ERR, "the 'arguments' property of a function with a rest parameter may not be used") +MSG_DEF(JSMSG_REST_WITH_DEFAULT, 299, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default") +MSG_DEF(JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT, 300, 0, JSEXN_SYNTAXERR, "parameter(s) with default followed by parameter without default") +MSG_DEF(JSMSG_YIELD_IN_DEFAULT, 301, 0, JSEXN_SYNTAXERR, "yield in default expression") diff --git a/scripting/javascript/spidermonkey-android/include/js/HashTable.h b/scripting/javascript/spidermonkey-android/include/js/HashTable.h index 259725f3a8..bc1f446b1a 100644 --- a/scripting/javascript/spidermonkey-android/include/js/HashTable.h +++ b/scripting/javascript/spidermonkey-android/include/js/HashTable.h @@ -1,44 +1,9 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=99 ft=cpp: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released - * November 13, 2009. - * - * The Initial Developer of the Original Code is - * the Mozilla Corporation. - * - * Contributor(s): - * Brendan Eich (Original Author) - * Chris Waterson - * L. David Baron , Mozilla Corporation - * Luke Wagner - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jshashtable_h_ #define jshashtable_h_ @@ -97,7 +62,7 @@ class HashTableEntry { JS_ASSERT(isLive()); keyHash |= collisionBit; } void unsetCollision() { keyHash &= ~sCollisionBit; } - bool hasCollision() const { JS_ASSERT(isLive()); return keyHash & sCollisionBit; } + bool hasCollision() const { return keyHash & sCollisionBit; } bool matchHash(HashNumber hn) { return (keyHash & ~sCollisionBit) == hn; } HashNumber getKeyHash() const { JS_ASSERT(!hasCollision()); return keyHash; } }; @@ -177,21 +142,23 @@ class HashTable : private AllocPolicy protected: friend class HashTable; - Range(Entry *c, Entry *e) : cur(c), end(e) { + Range(Entry *c, Entry *e) : cur(c), end(e), validEntry(true) { while (cur < end && !cur->isLive()) ++cur; } Entry *cur, *end; + DebugOnly validEntry; public: - Range() : cur(NULL), end(NULL) {} + Range() : cur(NULL), end(NULL), validEntry(false) {} bool empty() const { return cur == end; } T &front() const { + JS_ASSERT(validEntry); JS_ASSERT(!empty()); return cur->t; } @@ -200,6 +167,7 @@ class HashTable : private AllocPolicy JS_ASSERT(!empty()); while (++cur < end && !cur->isLive()) continue; + validEntry = true; } }; @@ -217,7 +185,7 @@ class HashTable : private AllocPolicy friend class HashTable; HashTable &table; - bool added; + bool rekeyed; bool removed; /* Not copyable. */ @@ -226,7 +194,7 @@ class HashTable : private AllocPolicy public: template explicit - Enum(Map &map) : Range(map.all()), table(map.impl), added(false), removed(false) {} + Enum(Map &map) : Range(map.all()), table(map.impl), rekeyed(false), removed(false) {} /* * Removes the |front()| element from the table, leaving |front()| @@ -240,6 +208,7 @@ class HashTable : private AllocPolicy void removeFront() { table.remove(*this->cur); removed = true; + this->validEntry = false; } /* @@ -247,35 +216,29 @@ class HashTable : private AllocPolicy * a new key at the new Lookup position. |front()| is invalid after * this operation until the next call to |popFront()|. */ - void rekeyFront(Key &k) { + void rekeyFront(const Lookup &l, const Key &k) { JS_ASSERT(&k != &HashPolicy::getKey(this->cur->t)); - JS_ASSERT(!table.match(*this->cur, k)); - Entry e = *this->cur; - HashPolicy::setKey(e.t, k); + if (match(*this->cur, l)) + return; + typename HashTableEntry::NonConstT t = this->cur->t; + HashPolicy::setKey(t, const_cast(k)); table.remove(*this->cur); - table.add(k, e); - added = true; + table.putNewInfallible(l, t); + rekeyed = true; + this->validEntry = false; + } + + void rekeyFront(const Key &k) { + rekeyFront(k, k); } /* Potentially rehashes the table. */ ~Enum() { - if (added) - table.checkOverloaded(); + if (rekeyed) + table.checkOverRemoved(); if (removed) table.checkUnderloaded(); } - - /* Can be used to end the enumeration before the destructor. */ - void endEnumeration() { - if (added) { - table.checkOverloaded(); - added = false; - } - if (removed) { - table.checkUnderloaded(); - removed = false; - } - } }; private: @@ -301,6 +264,7 @@ class HashTable : private AllocPolicy uint32_t grows; /* table expansions */ uint32_t shrinks; /* table contractions */ uint32_t compresses; /* table compressions */ + uint32_t rehashes; /* tombstone decontaminations */ } stats; # define METER(x) x #else @@ -384,7 +348,7 @@ class HashTable : private AllocPolicy mutationCount(0) {} - bool init(uint32_t length) + MOZ_WARN_UNUSED_RESULT bool init(uint32_t length) { /* Make sure that init isn't called twice. */ JS_ASSERT(table == NULL); @@ -533,8 +497,9 @@ class HashTable : private AllocPolicy */ Entry &findFreeEntry(HashNumber keyHash) { - METER(stats.searches++); JS_ASSERT(!(keyHash & sCollisionBit)); + JS_ASSERT(table); + METER(stats.searches++); /* N.B. the |keyHash| has already been distributed. */ @@ -543,7 +508,7 @@ class HashTable : private AllocPolicy Entry *entry = &table[h1]; /* Miss: return space for a new entry. */ - if (entry->isFree()) { + if (!entry->isLive()) { METER(stats.misses++); return *entry; } @@ -559,14 +524,16 @@ class HashTable : private AllocPolicy h1 = applyDoubleHash(h1, dh); entry = &table[h1]; - if (entry->isFree()) { + if (!entry->isLive()) { METER(stats.misses++); return *entry; } } } - bool changeTableSize(int deltaLog2) + enum RebuildStatus { NotOverloaded, Rehashed, RehashFailed }; + + RebuildStatus changeTableSize(int deltaLog2) { /* Look, but don't touch, until we succeed in getting new entry store. */ Entry *oldTable = table; @@ -575,12 +542,12 @@ class HashTable : private AllocPolicy uint32_t newCapacity = JS_BIT(newLog2); if (newCapacity > sMaxCapacity) { this->reportAllocOverflow(); - return false; + return RehashFailed; } Entry *newTable = createTable(*this, newCapacity); if (!newTable) - return false; + return RehashFailed; /* We can't fail from here on, so update table parameters. */ setTableSizeLog2(newLog2); @@ -597,30 +564,13 @@ class HashTable : private AllocPolicy } destroyTable(*this, oldTable, oldCap); - return true; + return Rehashed; } - void add(const Lookup &l, const Entry &e) - { - HashNumber keyHash = prepareHash(l); - Entry &entry = lookup(l, keyHash, sCollisionBit); - - if (entry.isRemoved()) { - METER(stats.addOverRemoved++); - removedCount--; - keyHash |= sCollisionBit; - } - - entry.t = e.t; - entry.setLive(keyHash); - entryCount++; - mutationCount++; - } - - bool checkOverloaded() + RebuildStatus checkOverloaded() { if (!overloaded()) - return false; + return NotOverloaded; /* Compress if a quarter or more of all entries are removed. */ int deltaLog2; @@ -635,9 +585,21 @@ class HashTable : private AllocPolicy return changeTableSize(deltaLog2); } + /* Infallibly rehash the table if we are overloaded with removals. */ + void checkOverRemoved() + { + if (overloaded()) { + METER(stats.rehashes++); + rehashTable(); + JS_ASSERT(!overloaded()); + } + } + void remove(Entry &e) { + JS_ASSERT(table); METER(stats.removes++); + if (e.hasCollision()) { e.setRemoved(); removedCount++; @@ -657,6 +619,52 @@ class HashTable : private AllocPolicy } } + /* + * This is identical to changeTableSize(currentSize), but without requiring + * a second table. We do this by recycling the collision bits to tell us if + * the element is already inserted or still waiting to be inserted. Since + * already-inserted elements win any conflicts, we get the same table as we + * would have gotten through random insertion order. + */ + void rehashTable() + { + removedCount = 0; + for (size_t i = 0; i < capacity(); ++i) + table[i].unsetCollision(); + + for (size_t i = 0; i < capacity();) { + Entry *src = &table[i]; + + if (!src->isLive() || src->hasCollision()) { + ++i; + continue; + } + + HashNumber keyHash = src->getKeyHash(); + HashNumber h1 = hash1(keyHash, hashShift); + DoubleHash dh = hash2(keyHash, hashShift); + Entry *tgt = &table[h1]; + while (true) { + if (!tgt->hasCollision()) { + Swap(*src, *tgt); + tgt->setCollision(); + break; + } + + h1 = applyDoubleHash(h1, dh); + tgt = &table[h1]; + } + } + + /* + * TODO: this algorithm leaves collision bits on *all* elements, even if + * they are on no collision path. We have the option of setting the + * collision bits correctly on a subsequent pass or skipping the rehash + * unless we are totally filled with tombstones: benchmark to find out + * which approach is best. + */ + } + public: void clear() { @@ -688,22 +696,27 @@ class HashTable : private AllocPolicy } Range all() const { + JS_ASSERT(table); return Range(table, table + capacity()); } bool empty() const { + JS_ASSERT(table); return !entryCount; } uint32_t count() const { + JS_ASSERT(table); return entryCount; } uint32_t capacity() const { + JS_ASSERT(table); return JS_BIT(sHashBits - hashShift); } uint32_t generation() const { + JS_ASSERT(table); return gen; } @@ -747,8 +760,11 @@ class HashTable : private AllocPolicy removedCount--; p.keyHash |= sCollisionBit; } else { - if (checkOverloaded()) - /* Preserve the validity of |p.entry|. */ + /* Preserve the validity of |p.entry|. */ + RebuildStatus status = checkOverloaded(); + if (status == RehashFailed) + return false; + if (status == Rehashed) p.entry = &findFreeEntry(p.keyHash); } @@ -779,6 +795,34 @@ class HashTable : private AllocPolicy return true; } + void putNewInfallible(const Lookup &l, const T &t) + { + JS_ASSERT(table); + + HashNumber keyHash = prepareHash(l); + Entry *entry = &findFreeEntry(keyHash); + + if (entry->isRemoved()) { + METER(stats.addOverRemoved++); + removedCount--; + keyHash |= sCollisionBit; + } + + entry->t = t; + entry->setLive(keyHash); + entryCount++; + mutationCount++; + } + + bool putNew(const Lookup &l, const T &t) + { + if (checkOverloaded() == RehashFailed) + return false; + + putNewInfallible(l, t); + return true; + } + bool relookupOrAdd(AddPtr& p, const Lookup &l, const T& t) { p.mutationCount = mutationCount; @@ -791,6 +835,7 @@ class HashTable : private AllocPolicy void remove(Ptr p) { + JS_ASSERT(table); ReentrancyGuard g(*this); JS_ASSERT(p.found()); remove(*p.entry); @@ -1163,9 +1208,7 @@ class HashMap /* Like put, but assert that the given key is not already present. */ bool putNew(const Key &k, const Value &v) { - AddPtr p = lookupForAdd(k); - JS_ASSERT(!p); - return add(p, k, v); + return impl.putNew(k, Entry(k, v)); } /* Add (k,defaultValue) if k no found. Return false-y Ptr on oom. */ @@ -1371,15 +1414,11 @@ class HashSet /* Like put, but assert that the given key is not already present. */ bool putNew(const T &t) { - AddPtr p = lookupForAdd(t); - JS_ASSERT(!p); - return add(p, t); + return impl.putNew(t, t); } bool putNew(const Lookup &l, const T &t) { - AddPtr p = lookupForAdd(l); - JS_ASSERT(!p); - return add(p, t); + return impl.putNew(l, t); } void remove(const Lookup &l) { diff --git a/scripting/javascript/spidermonkey-android/include/js/LegacyIntTypes.h b/scripting/javascript/spidermonkey-android/include/js/LegacyIntTypes.h index 6f6a37bc03..30944efda6 100644 --- a/scripting/javascript/spidermonkey-android/include/js/LegacyIntTypes.h +++ b/scripting/javascript/spidermonkey-android/include/js/LegacyIntTypes.h @@ -1,40 +1,7 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * This section typedefs the old 'native' types to the new types. diff --git a/scripting/javascript/spidermonkey-android/include/js/MemoryMetrics.h b/scripting/javascript/spidermonkey-android/include/js/MemoryMetrics.h index 513db5b5e2..20edc08705 100644 --- a/scripting/javascript/spidermonkey-android/include/js/MemoryMetrics.h +++ b/scripting/javascript/spidermonkey-android/include/js/MemoryMetrics.h @@ -1,41 +1,9 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=99 ft=cpp: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is about:memory glue. - * - * The Initial Developer of the Original Code is - * Ms2ger . - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef js_MemoryMetrics_h #define js_MemoryMetrics_h @@ -62,6 +30,53 @@ struct TypeInferenceSizes size_t objects; size_t tables; size_t temporary; + + void add(TypeInferenceSizes &sizes) { + this->scripts += sizes.scripts; + this->objects += sizes.objects; + this->tables += sizes.tables; + this->temporary += sizes.temporary; + } +}; + +// These measurements relate directly to the JSRuntime, and not to +// compartments within it. +struct RuntimeSizes +{ + RuntimeSizes() + : object(0) + , atomsTable(0) + , contexts(0) + , dtoa(0) + , temporary(0) + , mjitCode(0) + , regexpCode(0) + , unusedCodeMemory(0) + , stackCommitted(0) + , gcMarker(0) + , mathCache(0) + , scriptFilenames(0) + , compartmentObjects(0) + {} + + size_t object; + size_t atomsTable; + size_t contexts; + size_t dtoa; + size_t temporary; + size_t mjitCode; + size_t regexpCode; + size_t unusedCodeMemory; + size_t stackCommitted; + size_t gcMarker; + size_t mathCache; + size_t scriptFilenames; + + // This is the exception to the "RuntimeSizes doesn't measure things within + // compartments" rule. We combine the sizes of all the JSCompartment + // objects into a single measurement because each one is fairly small, and + // they're all the same size. + size_t compartmentObjects; }; struct CompartmentStats @@ -70,10 +85,14 @@ struct CompartmentStats memset(this, 0, sizeof(*this)); } - void *extra; - size_t gcHeapArenaHeaders; - size_t gcHeapArenaPadding; - size_t gcHeapArenaUnused; + // These fields can be used by embedders. + void *extra1; + void *extra2; + + // If you add a new number, remember to update add() and maybe + // gcHeapThingsSize()! + size_t gcHeapArenaAdmin; + size_t gcHeapUnusedGcThings; size_t gcHeapObjectsNonFunction; size_t gcHeapObjectsFunction; @@ -83,84 +102,117 @@ struct CompartmentStats size_t gcHeapShapesBase; size_t gcHeapScripts; size_t gcHeapTypeObjects; +#if JS_HAS_XML_SUPPORT size_t gcHeapXML; +#endif size_t objectSlots; size_t objectElements; size_t objectMisc; + size_t objectPrivate; size_t stringChars; size_t shapesExtraTreeTables; size_t shapesExtraDictTables; size_t shapesExtraTreeShapeKids; size_t shapesCompartmentTables; size_t scriptData; - -#ifdef JS_METHODJIT - size_t mjitCode; size_t mjitData; -#endif + size_t crossCompartmentWrappers; + TypeInferenceSizes typeInferenceSizes; + + // Add cStats's numbers to this object's numbers. + void add(CompartmentStats &cStats) { + #define ADD(x) this->x += cStats.x + + ADD(gcHeapArenaAdmin); + ADD(gcHeapUnusedGcThings); + + ADD(gcHeapObjectsNonFunction); + ADD(gcHeapObjectsFunction); + ADD(gcHeapStrings); + ADD(gcHeapShapesTree); + ADD(gcHeapShapesDict); + ADD(gcHeapShapesBase); + ADD(gcHeapScripts); + ADD(gcHeapTypeObjects); + #if JS_HAS_XML_SUPPORT + ADD(gcHeapXML); + #endif + + ADD(objectSlots); + ADD(objectElements); + ADD(objectMisc); + ADD(objectPrivate); + ADD(stringChars); + ADD(shapesExtraTreeTables); + ADD(shapesExtraDictTables); + ADD(shapesExtraTreeShapeKids); + ADD(shapesCompartmentTables); + ADD(scriptData); + ADD(mjitData); + ADD(crossCompartmentWrappers); + + #undef ADD + + typeInferenceSizes.add(cStats.typeInferenceSizes); + } + + // The size of all the live things in the GC heap. + size_t gcHeapThingsSize(); }; struct RuntimeStats { RuntimeStats(JSMallocSizeOfFun mallocSizeOf) - : runtimeObject(0) - , runtimeAtomsTable(0) - , runtimeContexts(0) - , runtimeNormal(0) - , runtimeTemporary(0) - , runtimeRegexpCode(0) - , runtimeStackCommitted(0) - , runtimeGCMarker(0) + : runtime() , gcHeapChunkTotal(0) - , gcHeapChunkCleanUnused(0) - , gcHeapChunkDirtyUnused(0) - , gcHeapChunkCleanDecommitted(0) - , gcHeapChunkDirtyDecommitted(0) - , gcHeapArenaUnused(0) + , gcHeapDecommittedArenas(0) + , gcHeapUnusedChunks(0) + , gcHeapUnusedArenas(0) + , gcHeapUnusedGcThings(0) , gcHeapChunkAdmin(0) - , gcHeapUnusedPercentage(0) - , totalObjects(0) - , totalShapes(0) - , totalScripts(0) - , totalStrings(0) -#ifdef JS_METHODJIT - , totalMjit(0) -#endif - , totalTypeInference(0) - , totalAnalysisTemp(0) + , gcHeapGcThings(0) + , totals() , compartmentStatsVector() , currCompartmentStats(NULL) , mallocSizeOf(mallocSizeOf) {} - size_t runtimeObject; - size_t runtimeAtomsTable; - size_t runtimeContexts; - size_t runtimeNormal; - size_t runtimeTemporary; - size_t runtimeRegexpCode; - size_t runtimeStackCommitted; - size_t runtimeGCMarker; - size_t gcHeapChunkTotal; - size_t gcHeapChunkCleanUnused; - size_t gcHeapChunkDirtyUnused; - size_t gcHeapChunkCleanDecommitted; - size_t gcHeapChunkDirtyDecommitted; - size_t gcHeapArenaUnused; - size_t gcHeapChunkAdmin; - size_t gcHeapUnusedPercentage; - size_t totalObjects; - size_t totalShapes; - size_t totalScripts; - size_t totalStrings; -#ifdef JS_METHODJIT - size_t totalMjit; -#endif - size_t totalTypeInference; - size_t totalAnalysisTemp; + RuntimeSizes runtime; + // If you add a new number, remember to update the constructor! + + // Here's a useful breakdown of the GC heap. + // + // - rtStats.gcHeapChunkTotal + // - decommitted bytes + // - rtStats.gcHeapDecommittedArenas (decommitted arenas in non-empty chunks) + // - unused bytes + // - rtStats.gcHeapUnusedChunks (empty chunks) + // - rtStats.gcHeapUnusedArenas (empty arenas within non-empty chunks) + // - rtStats.total.gcHeapUnusedGcThings (empty GC thing slots within non-empty arenas) + // - used bytes + // - rtStats.gcHeapChunkAdmin + // - rtStats.total.gcHeapArenaAdmin + // - rtStats.gcHeapGcThings (in-use GC things) + // + // It's possible that some arenas in empty chunks may be decommitted, but + // we don't count those under rtStats.gcHeapDecommittedArenas because (a) + // it's rare, and (b) this means that rtStats.gcHeapUnusedChunks is a + // multiple of the chunk size, which is good. + + size_t gcHeapChunkTotal; + size_t gcHeapDecommittedArenas; + size_t gcHeapUnusedChunks; + size_t gcHeapUnusedArenas; + size_t gcHeapUnusedGcThings; + size_t gcHeapChunkAdmin; + size_t gcHeapGcThings; + + // The sum of all compartment's measurements. + CompartmentStats totals; + js::Vector compartmentStatsVector; CompartmentStats *currCompartmentStats; @@ -171,8 +223,16 @@ struct RuntimeStats #ifdef JS_THREADSAFE +class ObjectPrivateVisitor +{ +public: + // Within CollectRuntimeStats, this method is called for each JS object + // that has a private slot containing an nsISupports pointer. + virtual size_t sizeOfIncludingThis(void *aSupports) = 0; +}; + extern JS_PUBLIC_API(bool) -CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats); +CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisitor *opv); extern JS_PUBLIC_API(int64_t) GetExplicitNonHeapForRuntime(JSRuntime *rt, JSMallocSizeOfFun mallocSizeOf); diff --git a/scripting/javascript/spidermonkey-android/include/js/TemplateLib.h b/scripting/javascript/spidermonkey-android/include/js/TemplateLib.h index 9010b10f72..b72b8f51e9 100644 --- a/scripting/javascript/spidermonkey-android/include/js/TemplateLib.h +++ b/scripting/javascript/spidermonkey-android/include/js/TemplateLib.h @@ -1,42 +1,9 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=99 ft=cpp: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla SpiderMonkey JavaScript code. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Luke Wagner - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef js_template_lib_h__ #define js_template_lib_h__ @@ -174,10 +141,13 @@ template struct IsPodType { static const bool result = template struct If { static const T result = v1; }; template struct If { static const T result = v2; }; +template struct IsPointerType { static const bool result = false; }; +template struct IsPointerType { static const bool result = true; }; + /* * Traits class for identifying types that are implicitly barriered. */ -template struct IsPostBarrieredType { static const bool result = false; }; +template struct IsRelocatableHeapType { static const bool result = true; }; } /* namespace tl */ } /* namespace js */ diff --git a/scripting/javascript/spidermonkey-android/include/js/Utility.h b/scripting/javascript/spidermonkey-android/include/js/Utility.h index c4eb5964d3..327fce3e99 100644 --- a/scripting/javascript/spidermonkey-android/include/js/Utility.h +++ b/scripting/javascript/spidermonkey-android/include/js/Utility.h @@ -1,46 +1,15 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=99 ft=cpp: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla SpiderMonkey JavaScript code. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef js_utility_h__ #define js_utility_h__ #include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" #include #include @@ -53,6 +22,7 @@ #include "jstypes.h" #ifdef __cplusplus +# include "mozilla/Scoped.h" /* The public JS engine namespace. */ namespace JS {} @@ -97,6 +67,9 @@ JS_BEGIN_EXTERN_C #define JS_STATIC_ASSERT(cond) MOZ_STATIC_ASSERT(cond, "JS_STATIC_ASSERT") #define JS_STATIC_ASSERT_IF(cond, expr) MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF") +extern MOZ_NORETURN JS_PUBLIC_API(void) +JS_Assert(const char *s, const char *file, int ln); + /* * Abort the process in a non-graceful manner. This will cause a core file, * call to the debugger or other moral equivalent as well as causing the @@ -626,6 +599,15 @@ public: class UnwantedForeground : public Foreground { }; +template +struct ScopedDeletePtrTraits +{ + typedef T *type; + static T *empty() { return NULL; } + static void release(T *ptr) { Foreground::delete_(ptr); } +}; +SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits) + } /* namespace js */ /* @@ -847,7 +829,7 @@ class MoveRef { explicit MoveRef(T &t) : pointer(&t) { } T &operator*() const { return *pointer; } T *operator->() const { return pointer; } -#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#if defined(__GXX_EXPERIMENTAL_CXX0X__) && defined(__clang__) /* * If MoveRef is used in a rvalue position (which is expected), we can * end up in a situation where, without this ifdef, we would try to pass diff --git a/scripting/javascript/spidermonkey-android/include/js/Vector.h b/scripting/javascript/spidermonkey-android/include/js/Vector.h index e2d91349ea..e06e01ef2a 100644 --- a/scripting/javascript/spidermonkey-android/include/js/Vector.h +++ b/scripting/javascript/spidermonkey-android/include/js/Vector.h @@ -1,42 +1,9 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=99 ft=cpp: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released - * June 12, 2009. - * - * The Initial Developer of the Original Code is - * the Mozilla Corporation. - * - * Contributor(s): - * Luke Wagner - * Nicholas Nethercote - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsvector_h_ #define jsvector_h_ @@ -213,7 +180,7 @@ struct VectorImpl template class Vector : private AllocPolicy { - typedef typename tl::StaticAssert::result>::result _; + typedef typename tl::StaticAssert::result>::result _; /* utilities */ @@ -596,7 +563,12 @@ Vector::~Vector() */ template STATIC_POSTCONDITION(!return || newCap >= curLength + lengthInc) +#ifdef DEBUG +/* gcc (ARM, x86) compiler bug workaround - See bug 694694 */ +JS_NEVER_INLINE bool +#else inline bool +#endif Vector::calculateNewCapacity(size_t curLength, size_t lengthInc, size_t &newCap) { diff --git a/scripting/javascript/spidermonkey-android/include/jsalloc.h b/scripting/javascript/spidermonkey-android/include/jsalloc.h index aefc7aac45..a5eeca7534 100644 --- a/scripting/javascript/spidermonkey-android/include/jsalloc.h +++ b/scripting/javascript/spidermonkey-android/include/jsalloc.h @@ -1,40 +1,9 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=99 ft=cpp: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released - * July 16, 2009. - * - * The Initial Developer of the Original Code is - * the Mozilla Corporation. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsalloc_h_ #define jsalloc_h_ diff --git a/scripting/javascript/spidermonkey-android/include/jsapi.h.REMOVED.git-id b/scripting/javascript/spidermonkey-android/include/jsapi.h.REMOVED.git-id index c2f1e4dfe4..5c56f3b1fe 100644 --- a/scripting/javascript/spidermonkey-android/include/jsapi.h.REMOVED.git-id +++ b/scripting/javascript/spidermonkey-android/include/jsapi.h.REMOVED.git-id @@ -1 +1 @@ -e71bf3943ff22eeb475acd419c7005556859f6c4 \ No newline at end of file +37b6af08d1e6059f152ae515d8d7422a346cf7ed \ No newline at end of file diff --git a/scripting/javascript/spidermonkey-android/include/jsatom.h b/scripting/javascript/spidermonkey-android/include/jsatom.h index 361c03504c..a3447e06b4 100644 --- a/scripting/javascript/spidermonkey-android/include/jsatom.h +++ b/scripting/javascript/spidermonkey-android/include/jsatom.h @@ -1,41 +1,8 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsatom_h___ #define jsatom_h___ @@ -67,14 +34,37 @@ JSID_FROM_BITS(size_t bits) return id; } +/* + * Must not be used on atoms that are representable as integer jsids. + * Prefer NameToId or AtomToId over this function: + * + * A PropertyName is an atom that does not contain an integer in the range + * [0, UINT32_MAX]. However, jsid can only hold an integer in the range + * [0, JSID_INT_MAX] (where JSID_INT_MAX == 2^31-1). Thus, for the range of + * integers (JSID_INT_MAX, UINT32_MAX], to represent as a jsid 'id', it must be + * the case JSID_IS_ATOM(id) and !JSID_TO_ATOM(id)->isPropertyName(). In most + * cases when creating a jsid, code does not have to care about this corner + * case because: + * + * - When given an arbitrary JSAtom*, AtomToId must be used, which checks for + * integer atoms representable as integer jsids, and does this conversion. + * + * - When given a PropertyName*, NameToId can be used which which does not need + * to do any dynamic checks. + * + * Thus, it is only the rare third case which needs this function, which + * handles any JSAtom* that is known not to be representable with an int jsid. + */ static JS_ALWAYS_INLINE jsid -ATOM_TO_JSID(JSAtom *atom) +NON_INTEGER_ATOM_TO_JSID(JSAtom *atom) { JS_ASSERT(((size_t)atom & 0x7) == 0); - return JSID_FROM_BITS((size_t)atom); + jsid id = JSID_FROM_BITS((size_t)atom); + JS_ASSERT(id == INTERNED_STRING_TO_JSID(NULL, (JSString*)atom)); + return id; } -/* All strings stored in jsids are atomized. */ +/* All strings stored in jsids are atomized, but are not necessarily property names. */ static JS_ALWAYS_INLINE JSBool JSID_IS_ATOM(jsid id) { @@ -84,7 +74,7 @@ JSID_IS_ATOM(jsid id) static JS_ALWAYS_INLINE JSBool JSID_IS_ATOM(jsid id, JSAtom *atom) { - return JSID_BITS(id) == JSID_BITS(ATOM_TO_JSID(atom)); + return id == JSID_FROM_BITS((size_t)atom); } static JS_ALWAYS_INLINE JSAtom * @@ -93,9 +83,6 @@ JSID_TO_ATOM(jsid id) return (JSAtom *)JSID_TO_STRING(id); } -extern jsid -js_CheckForStringIndex(jsid id); - JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4); JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD); @@ -104,7 +91,6 @@ namespace js { static JS_ALWAYS_INLINE JSHashNumber HashId(jsid id) { - JS_ASSERT(js_CheckForStringIndex(id) == id); JSHashNumber n = #if JS_BYTES_PER_WORD == 4 JSHashNumber(JSID_BITS(id)); @@ -140,11 +126,9 @@ struct DefaultHasher { typedef jsid Lookup; static HashNumber hash(const Lookup &l) { - JS_ASSERT(l == js_CheckForStringIndex(l)); return HashNumber(JSID_BITS(l)); } static bool match(const jsid &id, const Lookup &l) { - JS_ASSERT(l == js_CheckForStringIndex(l)); return id == l; } }; @@ -231,7 +215,7 @@ typedef HashSet AtomSet; * On encodings: * * - Some string functions have an optional FlationCoding argument that allow - * the caller to force CESU-8 encoding handling. + * the caller to force CESU-8 encoding handling. * - Functions that don't take a FlationCoding base their NormalEncoding * behavior on the js_CStringsAreUTF8 value. NormalEncoding is either raw * (simple zero-extension) or UTF-8 depending on js_CStringsAreUTF8. @@ -291,38 +275,7 @@ struct JSAtomState #undef DEFINE_PROTOTYPE_ATOM #undef DEFINE_KEYWORD_ATOM - /* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */ - struct { - js::PropertyName *XMLListAtom; - js::PropertyName *decodeURIAtom; - js::PropertyName *decodeURIComponentAtom; - js::PropertyName *defineGetterAtom; - js::PropertyName *defineSetterAtom; - js::PropertyName *encodeURIAtom; - js::PropertyName *encodeURIComponentAtom; - js::PropertyName *escapeAtom; - js::PropertyName *hasOwnPropertyAtom; - js::PropertyName *isFiniteAtom; - js::PropertyName *isNaNAtom; - js::PropertyName *isPrototypeOfAtom; - js::PropertyName *isXMLNameAtom; - js::PropertyName *lookupGetterAtom; - js::PropertyName *lookupSetterAtom; - js::PropertyName *parseFloatAtom; - js::PropertyName *parseIntAtom; - js::PropertyName *propertyIsEnumerableAtom; - js::PropertyName *unescapeAtom; - js::PropertyName *unevalAtom; - js::PropertyName *unwatchAtom; - js::PropertyName *watchAtom; - } lazy; - static const size_t commonAtomsOffset; - static const size_t lazyAtomsOffset; - - void clearLazyAtoms() { - memset(&lazy, 0, sizeof(lazy)); - } void junkAtoms() { #ifdef DEBUG @@ -340,7 +293,7 @@ struct JSAtomState extern bool AtomIsInterned(JSContext *cx, JSAtom *atom); -#define ATOM(name) cx->runtime->atomState.name##Atom +#define ATOM(name) js::HandlePropertyName::fromMarkedLocation(&cx->runtime->atomState.name##Atom) #define COMMON_ATOM_INDEX(name) \ ((offsetof(JSAtomState, name##Atom) - JSAtomState::commonAtomsOffset) \ @@ -349,10 +302,10 @@ AtomIsInterned(JSContext *cx, JSAtom *atom); ((offsetof(JSAtomState, typeAtoms[type]) - JSAtomState::commonAtomsOffset)\ / sizeof(JSAtom*)) -#define ATOM_OFFSET(name) offsetof(JSAtomState, name##Atom) -#define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off))) -#define CLASS_ATOM_OFFSET(name) offsetof(JSAtomState, classAtoms[JSProto_##name]) -#define CLASS_ATOM(cx,name) ((cx)->runtime->atomState.classAtoms[JSProto_##name]) +#define NAME_OFFSET(name) offsetof(JSAtomState, name##Atom) +#define OFFSET_TO_NAME(rt,off) (*(js::PropertyName **)((char*)&(rt)->atomState + (off))) +#define CLASS_NAME_OFFSET(name) offsetof(JSAtomState, classAtoms[JSProto_##name]) +#define CLASS_NAME(cx,name) ((cx)->runtime->atomState.classAtoms[JSProto_##name]) extern const char *const js_common_atom_names[]; extern const size_t js_common_atom_count; @@ -457,28 +410,29 @@ js_DumpAtoms(JSContext *cx, FILE *fp); #endif -inline bool -js_ValueToAtom(JSContext *cx, const js::Value &v, JSAtom **atomp); - -inline bool -js_ValueToStringId(JSContext *cx, const js::Value &v, jsid *idp); - -inline bool -js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval, - jsid *idp); -inline bool -js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval, - jsid *idp, js::Value *vp); - namespace js { +inline JSAtom * +ToAtom(JSContext *cx, const js::Value &v); + +bool +InternNonIntElementId(JSContext *cx, JSObject *obj, const Value &idval, + jsid *idp, Value *vp); + +inline bool +InternNonIntElementId(JSContext *cx, JSObject *obj, const Value &idval, jsid *idp) +{ + Value dummy; + return InternNonIntElementId(cx, obj, idval, idp, &dummy); +} + /* * For all unmapped atoms recorded in al, add a mapping from the atom's index * to its address. map->length must already be set to the number of atoms in * the list and map->vector must point to pre-allocated memory. */ extern void -InitAtomMap(JSContext *cx, AtomIndexMap *indices, HeapPtrAtom *atoms); +InitAtomMap(JSContext *cx, AtomIndexMap *indices, HeapPtr *atoms); template bool diff --git a/scripting/javascript/spidermonkey-android/include/jsatom.tbl b/scripting/javascript/spidermonkey-android/include/jsatom.tbl index e2c6f3ba73..3c2e47f450 100644 --- a/scripting/javascript/spidermonkey-android/include/jsatom.tbl +++ b/scripting/javascript/spidermonkey-android/include/jsatom.tbl @@ -18,7 +18,7 @@ * * DEFINE_ATOM(id, name) * Define an atom whose JavaScript string's value is |name|. - * + * * DEFINE_PROTOTYPE_ATOM(id) * Define an atom whose name is the same as one of those defined in * jsproto.tbl. The code that processes that has already declared and @@ -30,7 +30,7 @@ * jskeyword.tbl. The code that processes that has already declared and * defined the js__str global, so this defines only the JSAtomState * member. - */ + */ @@ -118,8 +118,33 @@ DEFINE_ATOM(hasOwn, "hasOwn") DEFINE_ATOM(keys, "keys") DEFINE_ATOM(iterate, "iterate") DEFINE_PROTOTYPE_ATOM(WeakMap) +DEFINE_ATOM(buffer, "buffer") DEFINE_ATOM(byteLength, "byteLength") +DEFINE_ATOM(byteOffset, "byteOffset") DEFINE_KEYWORD_ATOM(return) DEFINE_KEYWORD_ATOM(throw) DEFINE_ATOM(url, "url") DEFINE_ATOM(innermost, "innermost") + +DEFINE_ATOM(XMLList, "XMLList") +DEFINE_ATOM(decodeURI, "decodeURI") +DEFINE_ATOM(decodeURIComponent, "decodeURIComponent") +DEFINE_ATOM(defineGetter, "__defineGetter__") +DEFINE_ATOM(defineSetter, "__defineSetter__") +DEFINE_ATOM(encodeURI, "encodeURI") +DEFINE_ATOM(encodeURIComponent, "encodeURIComponent") +DEFINE_ATOM(escape, "escape") +DEFINE_ATOM(hasOwnProperty, "hasOwnProperty") +DEFINE_ATOM(isFinite, "isFinite") +DEFINE_ATOM(isNaN, "isNaN") +DEFINE_ATOM(isPrototypeOf, "isPrototypeOf") +DEFINE_ATOM(isXMLName, "isXMLName") +DEFINE_ATOM(lookupGetter, "__lookupGetter__") +DEFINE_ATOM(lookupSetter, "__lookupSetter__") +DEFINE_ATOM(parseFloat, "parseFloat") +DEFINE_ATOM(parseInt, "parseInt") +DEFINE_ATOM(propertyIsEnumerable, "propertyIsEnumerable") +DEFINE_ATOM(unescape, "unescape") +DEFINE_ATOM(uneval, "uneval") +DEFINE_ATOM(unwatch, "unwatch") +DEFINE_ATOM(watch, "watch") diff --git a/scripting/javascript/spidermonkey-android/include/jscell.h b/scripting/javascript/spidermonkey-android/include/jscell.h deleted file mode 100644 index b7f931671d..0000000000 --- a/scripting/javascript/spidermonkey-android/include/jscell.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is SpiderMonkey code. - * - * The Initial Developer of the Original Code is - * Mozilla Corporation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Gregor Wagner - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jscell_h___ -#define jscell_h___ - -#include "jspubtd.h" - -struct JSCompartment; - -namespace js { -namespace gc { - -struct ArenaHeader; -struct Chunk; - -/* The GC allocation kinds. */ -enum AllocKind { - FINALIZE_OBJECT0, - FINALIZE_OBJECT0_BACKGROUND, - FINALIZE_OBJECT2, - FINALIZE_OBJECT2_BACKGROUND, - FINALIZE_OBJECT4, - FINALIZE_OBJECT4_BACKGROUND, - FINALIZE_OBJECT8, - FINALIZE_OBJECT8_BACKGROUND, - FINALIZE_OBJECT12, - FINALIZE_OBJECT12_BACKGROUND, - FINALIZE_OBJECT16, - FINALIZE_OBJECT16_BACKGROUND, - FINALIZE_OBJECT_LAST = FINALIZE_OBJECT16_BACKGROUND, - FINALIZE_SCRIPT, - FINALIZE_SHAPE, - FINALIZE_BASE_SHAPE, - FINALIZE_TYPE_OBJECT, -#if JS_HAS_XML_SUPPORT - FINALIZE_XML, -#endif - FINALIZE_SHORT_STRING, - FINALIZE_STRING, - FINALIZE_EXTERNAL_STRING, - FINALIZE_LAST = FINALIZE_EXTERNAL_STRING -}; - -static const unsigned FINALIZE_LIMIT = FINALIZE_LAST + 1; -static const unsigned FINALIZE_OBJECT_LIMIT = FINALIZE_OBJECT_LAST + 1; - -/* - * Live objects are marked black. How many other additional colors are available - * depends on the size of the GCThing. Objects marked gray are eligible for - * cycle collection. - */ -static const uint32_t BLACK = 0; -static const uint32_t GRAY = 1; - -/* - * A GC cell is the base class for all GC things. - */ -struct Cell { - static const size_t CellShift = 3; - static const size_t CellSize = size_t(1) << CellShift; - static const size_t CellMask = CellSize - 1; - - inline uintptr_t address() const; - inline ArenaHeader *arenaHeader() const; - inline Chunk *chunk() const; - inline AllocKind getAllocKind() const; - - JS_ALWAYS_INLINE bool isMarked(uint32_t color = BLACK) const; - JS_ALWAYS_INLINE bool markIfUnmarked(uint32_t color = BLACK) const; - JS_ALWAYS_INLINE void unmark(uint32_t color) const; - - inline JSCompartment *compartment() const; - -#ifdef DEBUG - inline bool isAligned() const; -#endif -}; - -} /* namespace gc */ -} /* namespace js */ - -#endif /* jscell_h___ */ diff --git a/scripting/javascript/spidermonkey-android/include/jsclass.h b/scripting/javascript/spidermonkey-android/include/jsclass.h index 1c98f44dd2..e5bcacc05e 100644 --- a/scripting/javascript/spidermonkey-android/include/jsclass.h +++ b/scripting/javascript/spidermonkey-android/include/jsclass.h @@ -1,41 +1,9 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=4 sw=4 et tw=79 ft=cpp: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is SpiderMonkey JavaScript engine. - * - * The Initial Developer of the Original Code is - * Mozilla Corporation. - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsclass_h__ #define jsclass_h__ @@ -54,6 +22,7 @@ namespace js { class PropertyName; class SpecialId; +class PropertyId; static JS_ALWAYS_INLINE jsid SPECIALID_TO_JSID(const SpecialId &sid); @@ -69,12 +38,13 @@ SPECIALID_TO_JSID(const SpecialId &sid); * does not occur in JS scripts but may be used to indicate the absence of a * valid identifier; or JS_DEFAULT_XML_NAMESPACE_ID, if E4X is enabled. */ - -class SpecialId { +class SpecialId +{ uintptr_t bits; /* Needs access to raw bits. */ friend JS_ALWAYS_INLINE jsid SPECIALID_TO_JSID(const SpecialId &sid); + friend class PropertyId; static const uintptr_t TYPE_VOID = JSID_TYPE_VOID; static const uintptr_t TYPE_OBJECT = JSID_TYPE_OBJECT; @@ -174,83 +144,75 @@ JSID_TO_SPECIALID(jsid id) return SpecialId::defaultXMLNamespace(); } +typedef JS::Handle HandleSpecialId; + /* js::Class operation signatures. */ typedef JSBool -(* LookupGenericOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, - JSProperty **propp); +(* LookupGenericOp)(JSContext *cx, HandleObject obj, HandleId id, + MutableHandleObject objp, MutableHandleShape propp); typedef JSBool -(* LookupPropOp)(JSContext *cx, JSObject *obj, PropertyName *name, JSObject **objp, - JSProperty **propp); +(* LookupPropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, + MutableHandleObject objp, MutableHandleShape propp); typedef JSBool -(* LookupElementOp)(JSContext *cx, JSObject *obj, uint32_t index, JSObject **objp, - JSProperty **propp); +(* LookupElementOp)(JSContext *cx, HandleObject obj, uint32_t index, + MutableHandleObject objp, MutableHandleShape propp); typedef JSBool -(* LookupSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp, - JSProperty **propp); +(* LookupSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, + MutableHandleObject objp, MutableHandleShape propp); typedef JSBool -(* DefineGenericOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value, +(* DefineGenericOp)(JSContext *cx, HandleObject obj, HandleId id, const Value *value, PropertyOp getter, StrictPropertyOp setter, unsigned attrs); typedef JSBool -(* DefinePropOp)(JSContext *cx, JSObject *obj, PropertyName *name, const Value *value, +(* DefinePropOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, const Value *value, PropertyOp getter, StrictPropertyOp setter, unsigned attrs); typedef JSBool -(* DefineElementOp)(JSContext *cx, JSObject *obj, uint32_t index, const Value *value, +(* DefineElementOp)(JSContext *cx, HandleObject obj, uint32_t index, const Value *value, PropertyOp getter, StrictPropertyOp setter, unsigned attrs); typedef JSBool -(* DefineSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, const Value *value, +(* DefineSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, const Value *value, PropertyOp getter, StrictPropertyOp setter, unsigned attrs); typedef JSBool -(* GenericIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp); +(* GenericIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, Value *vp); typedef JSBool -(* PropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, Value *vp); +(* PropertyIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name, Value *vp); typedef JSBool -(* ElementIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp); +(* ElementIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp); typedef JSBool -(* ElementIfPresentOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp, bool* present); +(* ElementIfPresentOp)(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, Value *vp, bool* present); typedef JSBool -(* SpecialIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp); +(* SpecialIdOp)(JSContext *cx, HandleObject obj, HandleObject receiver, HandleSpecialId sid, Value *vp); typedef JSBool -(* StrictGenericIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict); +(* StrictGenericIdOp)(JSContext *cx, HandleObject obj, HandleId id, Value *vp, JSBool strict); typedef JSBool -(* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict); +(* StrictPropertyIdOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict); typedef JSBool -(* StrictElementIdOp)(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict); +(* StrictElementIdOp)(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict); typedef JSBool -(* StrictSpecialIdOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict); +(* StrictSpecialIdOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict); typedef JSBool -(* GenericAttributesOp)(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp); +(* GenericAttributesOp)(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp); typedef JSBool -(* PropertyAttributesOp)(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp); +(* PropertyAttributesOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, unsigned *attrsp); typedef JSBool -(* ElementAttributesOp)(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp); +(* ElementAttributesOp)(JSContext *cx, HandleObject obj, uint32_t index, unsigned *attrsp); typedef JSBool -(* SpecialAttributesOp)(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp); +(* SpecialAttributesOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, unsigned *attrsp); typedef JSBool -(* DeletePropertyOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict); +(* DeletePropertyOp)(JSContext *cx, HandleObject obj, HandlePropertyName name, Value *vp, JSBool strict); typedef JSBool -(* DeleteElementOp)(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict); +(* DeleteElementOp)(JSContext *cx, HandleObject obj, uint32_t index, Value *vp, JSBool strict); typedef JSBool -(* DeleteSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict); +(* DeleteSpecialOp)(JSContext *cx, HandleObject obj, HandleSpecialId sid, Value *vp, JSBool strict); typedef JSType -(* TypeOfOp)(JSContext *cx, JSObject *obj); - -/* - * Prepare to make |obj| non-extensible; in particular, fully resolve its properties. - * On error, return false. - * If |obj| is now ready to become non-extensible, set |*fixed| to true and return true. - * If |obj| refuses to become non-extensible, set |*fixed| to false and return true; the - * caller will throw an appropriate error. - */ -typedef JSBool -(* FixOp)(JSContext *cx, JSObject *obj, bool *fixed, AutoIdVector *props); +(* TypeOfOp)(JSContext *cx, HandleObject obj); typedef JSObject * -(* ObjectOp)(JSContext *cx, JSObject *obj); +(* ObjectOp)(JSContext *cx, HandleObject obj); +typedef void +(* ClearOp)(JSContext *cx, HandleObject obj); typedef void (* FinalizeOp)(FreeOp *fop, JSObject *obj); -typedef void -(* ClearOp)(JSContext *cx, JSObject *obj); #define JS_CLASS_MEMBERS \ const char *name; \ @@ -269,8 +231,8 @@ typedef void /* Optionally non-null members start here. */ \ JSCheckAccessOp checkAccess; \ JSNative call; \ - JSNative construct; \ JSHasInstanceOp hasInstance; \ + JSNative construct; \ JSTraceOp trace /* @@ -332,7 +294,6 @@ struct ObjectOps JSNewEnumerateOp enumerate; TypeOfOp typeOf; - FixOp fix; ObjectOp thisObject; ClearOp clear; }; @@ -340,7 +301,7 @@ struct ObjectOps #define JS_NULL_OBJECT_OPS \ {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \ NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \ - NULL,NULL,NULL,NULL,NULL,NULL} + NULL,NULL,NULL,NULL,NULL} struct Class { @@ -406,7 +367,8 @@ Valueify(const JSClass *c) * value of objects. */ enum ESClassValue { - ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean, ESClass_RegExp + ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean, + ESClass_RegExp, ESClass_ArrayBuffer }; /* @@ -424,6 +386,25 @@ IsObjectWithClass(const Value &v, ESClassValue classValue, JSContext *cx); } /* namespace js */ +namespace JS { + +inline bool +IsPoisonedSpecialId(js::SpecialId iden) +{ + if (iden.isObject()) + return IsPoisonedPtr(iden.toObject()); + return false; +} + +template <> struct RootMethods +{ + static js::SpecialId initial() { return js::SpecialId(); } + static ThingRootKind kind() { return THING_ROOT_ID; } + static bool poisoned(js::SpecialId id) { return IsPoisonedSpecialId(id); } +}; + +} /* namespace JS */ + #endif /* __cplusplus */ #endif /* jsclass_h__ */ diff --git a/scripting/javascript/spidermonkey-android/include/jsclist.h b/scripting/javascript/spidermonkey-android/include/jsclist.h index 604ec0ec95..4881104eee 100644 --- a/scripting/javascript/spidermonkey-android/include/jsclist.h +++ b/scripting/javascript/spidermonkey-android/include/jsclist.h @@ -1,40 +1,7 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsclist_h___ #define jsclist_h___ diff --git a/scripting/javascript/spidermonkey-android/include/jscpucfg.h b/scripting/javascript/spidermonkey-android/include/jscpucfg.h index 5fd8415bdd..3d2022dbe2 100644 --- a/scripting/javascript/spidermonkey-android/include/jscpucfg.h +++ b/scripting/javascript/spidermonkey-android/include/jscpucfg.h @@ -1,41 +1,8 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef js_cpucfg___ #define js_cpucfg___ diff --git a/scripting/javascript/spidermonkey-android/include/jsdbgapi.h b/scripting/javascript/spidermonkey-android/include/jsdbgapi.h index 16c8cc7aef..1382b0779a 100644 --- a/scripting/javascript/spidermonkey-android/include/jsdbgapi.h +++ b/scripting/javascript/spidermonkey-android/include/jsdbgapi.h @@ -1,43 +1,9 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=99: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Nick Fitzgerald - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsdbgapi_h___ #define jsdbgapi_h___ @@ -120,6 +86,13 @@ JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug); extern JS_PUBLIC_API(JSBool) JS_GetDebugMode(JSContext *cx); +/* + * Turn on/off debugging mode for all compartments. This returns false if any code + * from any of the runtime's compartments is running or on the stack. + */ +JS_FRIEND_API(JSBool) +JS_SetDebugModeForAllCompartments(JSContext *cx, JSBool debug); + /* * Turn on/off debugging mode for a single compartment. This should only be * used when no code from this compartment is running or on the stack in any @@ -248,6 +221,9 @@ JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp); extern JS_PUBLIC_API(void) JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation); +extern JS_PUBLIC_API(JSPrincipals*) +JS_GetPrincipalIfDummyFrame(JSContext *cx, JSStackFrame *fpArg); + extern JS_PUBLIC_API(JSBool) JS_IsScriptFrame(JSContext *cx, JSStackFrame *fp); @@ -299,6 +275,17 @@ JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp); /************************************************************************/ +/* + * This is almost JS_GetClass(obj)->name except that certain debug-only + * proxies are made transparent. In particular, this function turns the class + * of any scope (returned via JS_GetFrameScopeChain or JS_GetFrameCalleeObject) + * from "Proxy" to "Call", "Block", "With" etc. + */ +extern JS_PUBLIC_API(const char *) +JS_GetDebugClassName(JSObject *obj); + +/************************************************************************/ + extern JS_PUBLIC_API(const char *) JS_GetScriptFilename(JSContext *cx, JSScript *script); @@ -352,7 +339,6 @@ typedef struct JSPropertyDesc { jsval value; /* property value */ uint8_t flags; /* flags, see below */ uint8_t spare; /* unused */ - uint16_t slot; /* argument/variable slot */ jsval alias; /* alias id if JSPD_ALIAS flag */ } JSPropertyDesc; @@ -360,8 +346,6 @@ typedef struct JSPropertyDesc { #define JSPD_READONLY 0x02 /* assignment is error */ #define JSPD_PERMANENT 0x04 /* property cannot be deleted */ #define JSPD_ALIAS 0x08 /* property has an alias id */ -#define JSPD_ARGUMENT 0x10 /* argument to function */ -#define JSPD_VARIABLE 0x20 /* local variable in function */ #define JSPD_EXCEPTION 0x40 /* exception occurred fetching the property, */ /* value is exception */ #define JSPD_ERROR 0x80 /* native getter returned JS_FALSE without */ @@ -374,13 +358,6 @@ typedef struct JSPropertyDescArray { typedef struct JSScopeProperty JSScopeProperty; -extern JS_PUBLIC_API(JSScopeProperty *) -JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp); - -extern JS_PUBLIC_API(JSBool) -JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *shape, - JSPropertyDesc *pd); - extern JS_PUBLIC_API(JSBool) JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda); @@ -418,23 +395,6 @@ JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun); extern JS_PUBLIC_API(size_t) JS_GetScriptTotalSize(JSContext *cx, JSScript *script); -/* - * Return true if obj is a "system" object, that is, one created by - * JS_NewSystemObject with the system flag set and not JS_NewObject. - * - * What "system" means is up to the API client. - */ -extern JS_PUBLIC_API(JSBool) -JS_IsSystemObject(JSContext *cx, JSObject *obj); - -/* - * Mark an object as being a system object. This should be called immediately - * after allocating the object. A system object is an object for which - * JS_IsSystemObject returns true. - */ -extern JS_PUBLIC_API(JSBool) -JS_MakeSystemObject(JSContext *cx, JSObject *obj); - /************************************************************************/ extern JS_FRIEND_API(void) @@ -532,6 +492,16 @@ js_ResumeVtune(); #endif /* MOZ_VTUNE */ +#ifdef __linux__ + +extern JS_FRIEND_API(JSBool) +js_StartPerf(); + +extern JS_FRIEND_API(JSBool) +js_StopPerf(); + +#endif /* __linux__ */ + extern JS_PUBLIC_API(void) JS_DumpBytecode(JSContext *cx, JSScript *script); @@ -547,6 +517,9 @@ JS_DumpCompartmentPCCounts(JSContext *cx); extern JS_PUBLIC_API(JSObject *) JS_UnwrapObject(JSObject *obj); +extern JS_PUBLIC_API(JSObject *) +JS_UnwrapObjectAndInnerize(JSObject *obj); + /* Call the context debug handler on the topmost scripted frame. */ extern JS_FRIEND_API(JSBool) js_CallContextDebugHandler(JSContext *cx); diff --git a/scripting/javascript/spidermonkey-android/include/jsdhash.h b/scripting/javascript/spidermonkey-android/include/jsdhash.h index ec11b83120..7af17046b0 100644 --- a/scripting/javascript/spidermonkey-android/include/jsdhash.h +++ b/scripting/javascript/spidermonkey-android/include/jsdhash.h @@ -1,40 +1,7 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla JavaScript code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1999-2001 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Brendan Eich (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsdhash_h___ #define jsdhash_h___ diff --git a/scripting/javascript/spidermonkey-android/include/jsfriendapi.h b/scripting/javascript/spidermonkey-android/include/jsfriendapi.h index 4df3f883c5..3e28bcaa63 100644 --- a/scripting/javascript/spidermonkey-android/include/jsfriendapi.h +++ b/scripting/javascript/spidermonkey-android/include/jsfriendapi.h @@ -1,41 +1,8 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * - * The Original Code is SpiderMonkey code. - * - * The Initial Developer of the Original Code is - * Mozilla Corporation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsfriendapi_h___ #define jsfriendapi_h___ @@ -87,6 +54,15 @@ JS_GetCustomIteratorCount(JSContext *cx); extern JS_FRIEND_API(JSBool) JS_NondeterministicGetWeakMapKeys(JSContext *cx, JSObject *obj, JSObject **ret); +/* + * Determine whether the given object is backed by a DeadObjectProxy. + * + * Such objects hold no other objects (they have no outgoing reference edges) + * and will throw if you touch them (e.g. by reading/writing a property). + */ +extern JS_FRIEND_API(JSBool) +JS_IsDeadWrapper(JSObject *obj); + /* * Used by the cycle collector to trace through the shape and all * shapes it reaches, marking all non-shape children found in the @@ -117,6 +93,9 @@ JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallba extern JS_FRIEND_API(JSPrincipals *) JS_GetCompartmentPrincipals(JSCompartment *compartment); +extern JS_FRIEND_API(void) +JS_SetCompartmentPrincipals(JSCompartment *compartment, JSPrincipals *principals); + /* Safe to call with input obj == NULL. Returns non-NULL iff obj != NULL. */ extern JS_FRIEND_API(JSObject *) JS_ObjectToInnerObject(JSContext *cx, JSObject *obj); @@ -129,7 +108,7 @@ extern JS_FRIEND_API(JSObject *) JS_CloneObject(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent); extern JS_FRIEND_API(JSBool) -js_GetterOnlyPropertyStub(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp); +js_GetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, jsval *vp); JS_FRIEND_API(void) js_ReportOverRecursed(JSContext *maybecx); @@ -164,7 +143,10 @@ extern JS_FRIEND_API(JSBool) JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc); extern JS_FRIEND_API(JSBool) -JS_EnumerateState(JSContext *cx, JSObject *obj, JSIterateOp enum_op, js::Value *statep, jsid *idp); +JS_WrapAutoIdVector(JSContext *cx, JS::AutoIdVector &props); + +extern JS_FRIEND_API(JSBool) +JS_EnumerateState(JSContext *cx, JSHandleObject obj, JSIterateOp enum_op, js::Value *statep, jsid *idp); struct JSFunctionSpecWithHelp { const char *name; @@ -217,26 +199,13 @@ GetRuntime(const JSContext *cx) typedef bool (* PreserveWrapperCallback)(JSContext *cx, JSObject *obj); -#ifdef DEBUG /* - * DEBUG-only method to dump the complete object graph of heap-allocated things. + * Dump the complete object graph of heap-allocated things. * fp is the file for the dump output. */ extern JS_FRIEND_API(void) DumpHeapComplete(JSRuntime *rt, FILE *fp); -#endif - -class JS_FRIEND_API(AutoPreserveCompartment) { - private: - JSContext *cx; - JSCompartment *oldCompartment; - public: - AutoPreserveCompartment(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM); - ~AutoPreserveCompartment(); - JS_DECL_USE_GUARD_OBJECT_NOTIFIER -}; - class JS_FRIEND_API(AutoSwitchCompartment) { private: JSContext *cx; @@ -296,6 +265,15 @@ TraceWeakMaps(WeakMapTracer *trc); extern JS_FRIEND_API(bool) GCThingIsMarkedGray(void *thing); +extern JS_FRIEND_API(JSCompartment*) +GetGCThingCompartment(void *thing); + +typedef void +(GCThingCallback)(void *closure, void *gcthing); + +extern JS_FRIEND_API(void) +VisitGrayWrapperTargets(JSCompartment *comp, GCThingCallback *callback, void *closure); + /* * Shadow declarations of JS internal structures, for access by inline access * functions below. Do not use these structures in any other way. When adding @@ -388,6 +366,9 @@ GetObjectParentMaybeScope(JSObject *obj); JS_FRIEND_API(JSObject *) GetGlobalForObjectCrossCompartment(JSObject *obj); +JS_FRIEND_API(void) +NotifyAnimationActivity(JSObject *obj); + JS_FRIEND_API(bool) IsOriginalScriptFunction(JSFunction *fun); @@ -498,6 +479,9 @@ CastAsJSStrictPropertyOp(JSObject *object) JS_FRIEND_API(bool) GetPropertyNames(JSContext *cx, JSObject *obj, unsigned flags, js::AutoIdVector *props); +JS_FRIEND_API(bool) +GetGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp); + JS_FRIEND_API(bool) StringIsArrayIndex(JSLinearString *str, uint32_t *indexp); @@ -552,6 +536,34 @@ GetPCCountScriptSummary(JSContext *cx, size_t script); JS_FRIEND_API(JSString *) GetPCCountScriptContents(JSContext *cx, size_t script); +/* + * A call stack can be specified to the JS engine such that all JS entry/exits + * to functions push/pop an entry to/from the specified stack. + * + * For more detailed information, see vm/SPSProfiler.h + */ +struct ProfileEntry { + /* + * These two fields are marked as 'volatile' so that the compiler doesn't + * re-order instructions which modify them. The operation in question is: + * + * stack[i].string = str; + * (*size)++; + * + * If the size increment were re-ordered before the store of the string, + * then if sampling occurred there would be a bogus entry on the stack. + */ + const char * volatile string; + void * volatile sp; +}; + +JS_FRIEND_API(void) +SetRuntimeProfilingStack(JSRuntime *rt, ProfileEntry *stack, uint32_t *size, + uint32_t max); + +JS_FRIEND_API(void) +EnableRuntimeProfilingStack(JSRuntime *rt, bool enabled); + #ifdef JS_THREADSAFE JS_FRIEND_API(void *) GetOwnerThread(const JSContext *cx); @@ -581,7 +593,7 @@ extern JS_FRIEND_API(const JSStructuredCloneCallbacks *) GetContextStructuredCloneCallbacks(JSContext *cx); extern JS_FRIEND_API(JSVersion) -VersionSetXML(JSVersion version, bool enable); +VersionSetMoarXML(JSVersion version, bool enable); extern JS_FRIEND_API(bool) CanCallContextDebugHandler(JSContext *cx); @@ -610,8 +622,8 @@ SizeOfJSContext(); D(TOO_MUCH_MALLOC) \ D(ALLOC_TRIGGER) \ D(DEBUG_GC) \ - D(UNUSED2) /* was SHAPE */ \ - D(UNUSED3) /* was REFILL */ \ + D(DEBUG_MODE_GC) \ + D(TRANSPLANT) \ \ /* Reasons from Firefox */ \ D(DOM_WINDOW_UTILS) \ @@ -629,7 +641,9 @@ SizeOfJSContext(); D(DOM_IPC) \ D(DOM_WORKER) \ D(INTER_SLICE_GC) \ - D(REFRESH_FRAME) + D(REFRESH_FRAME) \ + D(FULL_GC_TIMER) \ + D(SHUTDOWN_CC) namespace gcreason { @@ -639,7 +653,15 @@ enum Reason { GCREASONS(MAKE_REASON) #undef MAKE_REASON NO_REASON, - NUM_REASONS + NUM_REASONS, + + /* + * For telemetry, we want to keep a fixed max bucket size over time so we + * don't have to switch histograms. 100 is conservative; as of this writing + * there are 26. But the cost of extra buckets seems to be low while the + * cost of switching histograms is high. + */ + NUM_TELEMETRY_REASONS = 100 }; } /* namespace gcreason */ @@ -650,6 +672,15 @@ PrepareCompartmentForGC(JSCompartment *comp); extern JS_FRIEND_API(void) PrepareForFullGC(JSRuntime *rt); +extern JS_FRIEND_API(void) +PrepareForIncrementalGC(JSRuntime *rt); + +extern JS_FRIEND_API(bool) +IsGCScheduled(JSRuntime *rt); + +extern JS_FRIEND_API(void) +SkipCompartmentForGC(JSCompartment *comp); + /* * When triggering a GC using one of the functions below, it is first necessary * to select the compartments to be collected. To do this, you can call @@ -667,7 +698,7 @@ extern JS_FRIEND_API(void) IncrementalGC(JSRuntime *rt, gcreason::Reason reason); extern JS_FRIEND_API(void) -SetGCSliceTimeBudget(JSContext *cx, int64_t millis); +FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason); enum GCProgress { /* @@ -724,12 +755,18 @@ IsIncrementalBarrierNeeded(JSContext *cx); extern JS_FRIEND_API(bool) IsIncrementalBarrierNeededOnObject(JSObject *obj); +extern JS_FRIEND_API(bool) +IsIncrementalBarrierNeededOnScript(JSScript *obj); + extern JS_FRIEND_API(void) IncrementalReferenceBarrier(void *ptr); extern JS_FRIEND_API(void) IncrementalValueBarrier(const Value &v); +extern JS_FRIEND_API(void) +PokeGC(JSRuntime *rt); + class ObjectPtr { JSObject *value; @@ -790,6 +827,16 @@ CastToJSFreeOp(FreeOp *fop) extern JS_FRIEND_API(const jschar*) GetErrorTypeNameFromNumber(JSContext* cx, const unsigned errorNumber); +/* Implemented in jswrapper.cpp. */ +typedef enum NukedGlobalHandling { + NukeForGlobalObject, + DontNukeForGlobalObject +} NukedGlobalHandling; + +extern JS_FRIEND_API(JSBool) +NukeChromeCrossCompartmentWrappersForGlobal(JSContext *cx, JSObject *obj, + NukedGlobalHandling nukeGlobal); + } /* namespace js */ #endif @@ -963,6 +1010,16 @@ JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes); extern JS_FRIEND_API(JSBool) JS_IsTypedArrayObject(JSObject *obj, JSContext *cx); +/* + * Check whether obj supports JS_GetArrayBufferView* APIs. Note that this may + * return false if a security wrapper is encountered that denies the + * unwrapping. If this test or one of the more specific tests succeeds, then it + * is safe to call the various ArrayBufferView accessor JSAPI calls defined + * below. cx MUST be non-NULL and valid. + */ +extern JS_FRIEND_API(JSBool) +JS_IsArrayBufferViewObject(JSObject *obj, JSContext *cx); + /* * Test for specific typed array types (ArrayBufferView subtypes) */ @@ -1063,6 +1120,14 @@ JS_GetTypedArrayByteOffset(JSObject *obj, JSContext *cx); extern JS_FRIEND_API(uint32_t) JS_GetTypedArrayByteLength(JSObject *obj, JSContext *cx); +/* + * Check whether obj supports JS_ArrayBufferView* APIs. Note that this may + * return false if a security wrapper is encountered that denies the + * unwrapping. + */ +extern JS_FRIEND_API(JSBool) +JS_IsArrayBufferViewObject(JSObject *obj, JSContext *cx); + /* * More generic name for JS_GetTypedArrayByteLength to cover DataViews as well */ @@ -1106,4 +1171,46 @@ JS_GetFloat64ArrayData(JSObject *obj, JSContext *cx); extern JS_FRIEND_API(void *) JS_GetArrayBufferViewData(JSObject *obj, JSContext *cx); +/* + * Check whether obj supports JS_GetDataView* APIs. Note that this may fail and + * throw an exception if a security wrapper is encountered that denies the + * operation. + */ +JS_FRIEND_API(JSBool) +JS_IsDataViewObject(JSContext *cx, JSObject *obj, JSBool *isDataView); + +/* + * Return the byte offset of a data view into its array buffer. |obj| must be a + * DataView. + * + * |obj| must have passed a JS_IsDataViewObject test, or somehow be known that + * it would pass such a test: it is a data view or a wrapper of a data view, + * and the unwrapping will succeed. If cx is NULL, then DEBUG builds may be + * unable to assert when unwrapping should be disallowed. + */ +JS_FRIEND_API(uint32_t) +JS_GetDataViewByteOffset(JSObject *obj, JSContext *cx); + +/* + * Return the byte length of a data view. + * + * |obj| must have passed a JS_IsDataViewObject test, or somehow be known that + * it would pass such a test: it is a data view or a wrapper of a data view, + * and the unwrapping will succeed. If cx is NULL, then DEBUG builds may be + * unable to assert when unwrapping should be disallowed. + */ +JS_FRIEND_API(uint32_t) +JS_GetDataViewByteLength(JSObject *obj, JSContext *cx); + +/* + * Return a pointer to the beginning of the data referenced by a DataView. + * + * |obj| must have passed a JS_IsDataViewObject test, or somehow be known that + * it would pass such a test: it is a data view or a wrapper of a data view, + * and the unwrapping will succeed. If cx is NULL, then DEBUG builds may be + * unable to assert when unwrapping should be disallowed. + */ +JS_FRIEND_API(void *) +JS_GetDataViewData(JSObject *obj, JSContext *cx); + #endif /* jsfriendapi_h___ */ diff --git a/scripting/javascript/spidermonkey-android/include/jsgc.h b/scripting/javascript/spidermonkey-android/include/jsgc.h index 617afec943..0cb842505c 100644 --- a/scripting/javascript/spidermonkey-android/include/jsgc.h +++ b/scripting/javascript/spidermonkey-android/include/jsgc.h @@ -1,41 +1,8 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsgc_h___ #define jsgc_h___ @@ -54,9 +21,9 @@ #include "jslock.h" #include "jsutil.h" #include "jsversion.h" -#include "jscell.h" #include "ds/BitArray.h" +#include "gc/Heap.h" #include "gc/Statistics.h" #include "js/HashTable.h" #include "js/Vector.h" @@ -64,9 +31,6 @@ struct JSCompartment; -extern "C" void -js_TraceXML(JSTracer *trc, JSXML* thing); - #if JS_STACK_GROWTH_DIRECTION > 0 # define JS_CHECK_STACK_SIZE(limit, lval) ((uintptr_t)(lval) < limit) #else @@ -87,737 +51,6 @@ enum State { INVALID }; -struct Arena; - -/* - * This must be an upper bound, but we do not need the least upper bound, so - * we just exclude non-background objects. - */ -const size_t MAX_BACKGROUND_FINALIZE_KINDS = FINALIZE_LIMIT - FINALIZE_OBJECT_LIMIT / 2; - -/* - * Page size is 4096 by default, except for SPARC, where it is 8192. - * Note: Do not use JS_CPU_SPARC here, this header is used outside JS. - * Bug 692267: Move page size definition to gc/Memory.h and include it - * directly once jsgc.h is no longer an installed header. - */ -#if defined(SOLARIS) && (defined(__sparc) || defined(__sparcv9)) -const size_t PageShift = 13; -#else -const size_t PageShift = 12; -#endif -const size_t PageSize = size_t(1) << PageShift; - -const size_t ChunkShift = 20; -const size_t ChunkSize = size_t(1) << ChunkShift; -const size_t ChunkMask = ChunkSize - 1; - -const size_t ArenaShift = PageShift; -const size_t ArenaSize = PageSize; -const size_t ArenaMask = ArenaSize - 1; - -/* - * This is the maximum number of arenas we allow in the FreeCommitted state - * before we trigger a GC_SHRINK to release free arenas to the OS. - */ -const static uint32_t FreeCommittedArenasThreshold = (32 << 20) / ArenaSize; - -/* - * The mark bitmap has one bit per each GC cell. For multi-cell GC things this - * wastes space but allows to avoid expensive devisions by thing's size when - * accessing the bitmap. In addition this allows to use some bits for colored - * marking during the cycle GC. - */ -const size_t ArenaCellCount = size_t(1) << (ArenaShift - Cell::CellShift); -const size_t ArenaBitmapBits = ArenaCellCount; -const size_t ArenaBitmapBytes = ArenaBitmapBits / 8; -const size_t ArenaBitmapWords = ArenaBitmapBits / JS_BITS_PER_WORD; - -/* - * A FreeSpan represents a contiguous sequence of free cells in an Arena. - * |first| is the address of the first free cell in the span. |last| is the - * address of the last free cell in the span. This last cell holds a FreeSpan - * data structure for the next span unless this is the last span on the list - * of spans in the arena. For this last span |last| points to the last byte of - * the last thing in the arena and no linkage is stored there, so - * |last| == arenaStart + ArenaSize - 1. If the space at the arena end is - * fully used this last span is empty and |first| == |last + 1|. - * - * Thus |first| < |last| implies that we have either the last span with at least - * one element or that the span is not the last and contains at least 2 - * elements. In both cases to allocate a thing from this span we need simply - * to increment |first| by the allocation size. - * - * |first| == |last| implies that we have a one element span that records the - * next span. So to allocate from it we need to update the span list head - * with a copy of the span stored at |last| address so the following - * allocations will use that span. - * - * |first| > |last| implies that we have an empty last span and the arena is - * fully used. - * - * Also only for the last span (|last| & 1)! = 0 as all allocation sizes are - * multiples of Cell::CellSize. - */ -struct FreeSpan { - uintptr_t first; - uintptr_t last; - - public: - FreeSpan() {} - - FreeSpan(uintptr_t first, uintptr_t last) - : first(first), last(last) { - checkSpan(); - } - - /* - * To minimize the size of the arena header the first span is encoded - * there as offsets from the arena start. - */ - static size_t encodeOffsets(size_t firstOffset, size_t lastOffset) { - /* Check that we can pack the offsets into uint16. */ - JS_STATIC_ASSERT(ArenaShift < 16); - JS_ASSERT(firstOffset <= ArenaSize); - JS_ASSERT(lastOffset < ArenaSize); - JS_ASSERT(firstOffset <= ((lastOffset + 1) & ~size_t(1))); - return firstOffset | (lastOffset << 16); - } - - /* - * Encoded offsets for a full arena when its first span is the last one - * and empty. - */ - static const size_t FullArenaOffsets = ArenaSize | ((ArenaSize - 1) << 16); - - static FreeSpan decodeOffsets(uintptr_t arenaAddr, size_t offsets) { - JS_ASSERT(!(arenaAddr & ArenaMask)); - - size_t firstOffset = offsets & 0xFFFF; - size_t lastOffset = offsets >> 16; - JS_ASSERT(firstOffset <= ArenaSize); - JS_ASSERT(lastOffset < ArenaSize); - - /* - * We must not use | when calculating first as firstOffset is - * ArenaMask + 1 for the empty span. - */ - return FreeSpan(arenaAddr + firstOffset, arenaAddr | lastOffset); - } - - void initAsEmpty(uintptr_t arenaAddr = 0) { - JS_ASSERT(!(arenaAddr & ArenaMask)); - first = arenaAddr + ArenaSize; - last = arenaAddr | (ArenaSize - 1); - JS_ASSERT(isEmpty()); - } - - bool isEmpty() const { - checkSpan(); - return first > last; - } - - bool hasNext() const { - checkSpan(); - return !(last & uintptr_t(1)); - } - - const FreeSpan *nextSpan() const { - JS_ASSERT(hasNext()); - return reinterpret_cast(last); - } - - FreeSpan *nextSpanUnchecked(size_t thingSize) const { -#ifdef DEBUG - uintptr_t lastOffset = last & ArenaMask; - JS_ASSERT(!(lastOffset & 1)); - JS_ASSERT((ArenaSize - lastOffset) % thingSize == 0); -#endif - return reinterpret_cast(last); - } - - uintptr_t arenaAddressUnchecked() const { - return last & ~ArenaMask; - } - - uintptr_t arenaAddress() const { - checkSpan(); - return arenaAddressUnchecked(); - } - - ArenaHeader *arenaHeader() const { - return reinterpret_cast(arenaAddress()); - } - - bool isSameNonEmptySpan(const FreeSpan *another) const { - JS_ASSERT(!isEmpty()); - JS_ASSERT(!another->isEmpty()); - return first == another->first && last == another->last; - } - - bool isWithinArena(uintptr_t arenaAddr) const { - JS_ASSERT(!(arenaAddr & ArenaMask)); - - /* Return true for the last empty span as well. */ - return arenaAddress() == arenaAddr; - } - - size_t encodeAsOffsets() const { - /* - * We must use first - arenaAddress(), not first & ArenaMask as - * first == ArenaMask + 1 for an empty span. - */ - uintptr_t arenaAddr = arenaAddress(); - return encodeOffsets(first - arenaAddr, last & ArenaMask); - } - - /* See comments before FreeSpan for details. */ - JS_ALWAYS_INLINE void *allocate(size_t thingSize) { - JS_ASSERT(thingSize % Cell::CellSize == 0); - checkSpan(); - uintptr_t thing = first; - if (thing < last) { - /* Bump-allocate from the current span. */ - first = thing + thingSize; - } else if (JS_LIKELY(thing == last)) { - /* - * Move to the next span. We use JS_LIKELY as without PGO - * compilers mis-predict == here as unlikely to succeed. - */ - *this = *reinterpret_cast(thing); - } else { - return NULL; - } - checkSpan(); - return reinterpret_cast(thing); - } - - /* A version of allocate when we know that the span is not empty. */ - JS_ALWAYS_INLINE void *infallibleAllocate(size_t thingSize) { - JS_ASSERT(thingSize % Cell::CellSize == 0); - checkSpan(); - uintptr_t thing = first; - if (thing < last) { - first = thing + thingSize; - } else { - JS_ASSERT(thing == last); - *this = *reinterpret_cast(thing); - } - checkSpan(); - return reinterpret_cast(thing); - } - - /* - * Allocate from a newly allocated arena. We do not move the free list - * from the arena. Rather we set the arena up as fully used during the - * initialization so to allocate we simply return the first thing in the - * arena and set the free list to point to the second. - */ - JS_ALWAYS_INLINE void *allocateFromNewArena(uintptr_t arenaAddr, size_t firstThingOffset, - size_t thingSize) { - JS_ASSERT(!(arenaAddr & ArenaMask)); - uintptr_t thing = arenaAddr | firstThingOffset; - first = thing + thingSize; - last = arenaAddr | ArenaMask; - checkSpan(); - return reinterpret_cast(thing); - } - - void checkSpan() const { -#ifdef DEBUG - /* We do not allow spans at the end of the address space. */ - JS_ASSERT(last != uintptr_t(-1)); - JS_ASSERT(first); - JS_ASSERT(last); - JS_ASSERT(first - 1 <= last); - uintptr_t arenaAddr = arenaAddressUnchecked(); - if (last & 1) { - /* The span is the last. */ - JS_ASSERT((last & ArenaMask) == ArenaMask); - - if (first - 1 == last) { - /* The span is last and empty. The above start != 0 check - * implies that we are not at the end of the address space. - */ - return; - } - size_t spanLength = last - first + 1; - JS_ASSERT(spanLength % Cell::CellSize == 0); - - /* Start and end must belong to the same arena. */ - JS_ASSERT((first & ~ArenaMask) == arenaAddr); - return; - } - - /* The span is not the last and we have more spans to follow. */ - JS_ASSERT(first <= last); - size_t spanLengthWithoutOneThing = last - first; - JS_ASSERT(spanLengthWithoutOneThing % Cell::CellSize == 0); - - JS_ASSERT((first & ~ArenaMask) == arenaAddr); - - /* - * If there is not enough space before the arena end to allocate one - * more thing, then the span must be marked as the last one to avoid - * storing useless empty span reference. - */ - size_t beforeTail = ArenaSize - (last & ArenaMask); - JS_ASSERT(beforeTail >= sizeof(FreeSpan) + Cell::CellSize); - - FreeSpan *next = reinterpret_cast(last); - - /* - * The GC things on the list of free spans come from one arena - * and the spans are linked in ascending address order with - * at least one non-free thing between spans. - */ - JS_ASSERT(last < next->first); - JS_ASSERT(arenaAddr == next->arenaAddressUnchecked()); - - if (next->first > next->last) { - /* - * The next span is the empty span that terminates the list for - * arenas that do not have any free things at the end. - */ - JS_ASSERT(next->first - 1 == next->last); - JS_ASSERT(arenaAddr + ArenaSize == next->first); - } -#endif - } - -}; - -/* Every arena has a header. */ -struct ArenaHeader { - friend struct FreeLists; - - JSCompartment *compartment; - - /* - * ArenaHeader::next has two purposes: when unallocated, it points to the - * next available Arena's header. When allocated, it points to the next - * arena of the same size class and compartment. - */ - ArenaHeader *next; - - private: - /* - * The first span of free things in the arena. We encode it as the start - * and end offsets within the arena, not as FreeSpan structure, to - * minimize the header size. - */ - size_t firstFreeSpanOffsets; - - /* - * One of AllocKind constants or FINALIZE_LIMIT when the arena does not - * contain any GC things and is on the list of empty arenas in the GC - * chunk. The latter allows to quickly check if the arena is allocated - * during the conservative GC scanning without searching the arena in the - * list. - */ - size_t allocKind : 8; - - /* - * When recursive marking uses too much stack the marking is delayed and - * the corresponding arenas are put into a stack using the following field - * as a linkage. To distinguish the bottom of the stack from the arenas - * not present in the stack we use an extra flag to tag arenas on the - * stack. - * - * Delayed marking is also used for arenas that we allocate into during an - * incremental GC. In this case, we intend to mark all the objects in the - * arena, and it's faster to do this marking in bulk. - * - * To minimize the ArenaHeader size we record the next delayed marking - * linkage as arenaAddress() >> ArenaShift and pack it with the allocKind - * field and hasDelayedMarking flag. We use 8 bits for the allocKind, not - * ArenaShift - 1, so the compiler can use byte-level memory instructions - * to access it. - */ - public: - size_t hasDelayedMarking : 1; - size_t allocatedDuringIncremental : 1; - size_t markOverflow : 1; - size_t nextDelayedMarking : JS_BITS_PER_WORD - 8 - 1 - 1 - 1; - - static void staticAsserts() { - /* We must be able to fit the allockind into uint8_t. */ - JS_STATIC_ASSERT(FINALIZE_LIMIT <= 255); - - /* - * nextDelayedMarkingpacking assumes that ArenaShift has enough bits - * to cover allocKind and hasDelayedMarking. - */ - JS_STATIC_ASSERT(ArenaShift >= 8 + 1 + 1 + 1); - } - - inline uintptr_t address() const; - inline Chunk *chunk() const; - - bool allocated() const { - JS_ASSERT(allocKind <= size_t(FINALIZE_LIMIT)); - return allocKind < size_t(FINALIZE_LIMIT); - } - - void init(JSCompartment *comp, AllocKind kind) { - JS_ASSERT(!allocated()); - JS_ASSERT(!markOverflow); - JS_ASSERT(!allocatedDuringIncremental); - JS_ASSERT(!hasDelayedMarking); - compartment = comp; - - JS_STATIC_ASSERT(FINALIZE_LIMIT <= 255); - allocKind = size_t(kind); - - /* See comments in FreeSpan::allocateFromNewArena. */ - firstFreeSpanOffsets = FreeSpan::FullArenaOffsets; - } - - void setAsNotAllocated() { - allocKind = size_t(FINALIZE_LIMIT); - markOverflow = 0; - allocatedDuringIncremental = 0; - hasDelayedMarking = 0; - nextDelayedMarking = 0; - } - - uintptr_t arenaAddress() const { - return address(); - } - - Arena *getArena() { - return reinterpret_cast(arenaAddress()); - } - - AllocKind getAllocKind() const { - JS_ASSERT(allocated()); - return AllocKind(allocKind); - } - - inline size_t getThingSize() const; - - bool hasFreeThings() const { - return firstFreeSpanOffsets != FreeSpan::FullArenaOffsets; - } - - inline bool isEmpty() const; - - void setAsFullyUsed() { - firstFreeSpanOffsets = FreeSpan::FullArenaOffsets; - } - - FreeSpan getFirstFreeSpan() const { -#ifdef DEBUG - checkSynchronizedWithFreeList(); -#endif - return FreeSpan::decodeOffsets(arenaAddress(), firstFreeSpanOffsets); - } - - void setFirstFreeSpan(const FreeSpan *span) { - JS_ASSERT(span->isWithinArena(arenaAddress())); - firstFreeSpanOffsets = span->encodeAsOffsets(); - } - -#ifdef DEBUG - void checkSynchronizedWithFreeList() const; -#endif - - inline ArenaHeader *getNextDelayedMarking() const; - inline void setNextDelayedMarking(ArenaHeader *aheader); -}; - -struct Arena { - /* - * Layout of an arena: - * An arena is 4K in size and 4K-aligned. It starts with the ArenaHeader - * descriptor followed by some pad bytes. The remainder of the arena is - * filled with the array of T things. The pad bytes ensure that the thing - * array ends exactly at the end of the arena. - * - * +-------------+-----+----+----+-----+----+ - * | ArenaHeader | pad | T0 | T1 | ... | Tn | - * +-------------+-----+----+----+-----+----+ - * - * <----------------------------------------> = ArenaSize bytes - * <-------------------> = first thing offset - */ - ArenaHeader aheader; - uint8_t data[ArenaSize - sizeof(ArenaHeader)]; - - private: - static JS_FRIEND_DATA(const uint32_t) ThingSizes[]; - static JS_FRIEND_DATA(const uint32_t) FirstThingOffsets[]; - - public: - static void staticAsserts(); - - static size_t thingSize(AllocKind kind) { - return ThingSizes[kind]; - } - - static size_t firstThingOffset(AllocKind kind) { - return FirstThingOffsets[kind]; - } - - static size_t thingsPerArena(size_t thingSize) { - JS_ASSERT(thingSize % Cell::CellSize == 0); - - /* We should be able to fit FreeSpan in any GC thing. */ - JS_ASSERT(thingSize >= sizeof(FreeSpan)); - - return (ArenaSize - sizeof(ArenaHeader)) / thingSize; - } - - static size_t thingsSpan(size_t thingSize) { - return thingsPerArena(thingSize) * thingSize; - } - - static bool isAligned(uintptr_t thing, size_t thingSize) { - /* Things ends at the arena end. */ - uintptr_t tailOffset = (ArenaSize - thing) & ArenaMask; - return tailOffset % thingSize == 0; - } - - uintptr_t address() const { - return aheader.address(); - } - - uintptr_t thingsStart(AllocKind thingKind) { - return address() | firstThingOffset(thingKind); - } - - uintptr_t thingsEnd() { - return address() + ArenaSize; - } - - template - bool finalize(FreeOp *fop, AllocKind thingKind, size_t thingSize); -}; - -/* The chunk header (located at the end of the chunk to preserve arena alignment). */ -struct ChunkInfo { - Chunk *next; - Chunk **prevp; - - /* Free arenas are linked together with aheader.next. */ - ArenaHeader *freeArenasHead; - - /* - * Decommitted arenas are tracked by a bitmap in the chunk header. We use - * this offset to start our search iteration close to a decommitted arena - * that we can allocate. - */ - uint32_t lastDecommittedArenaOffset; - - /* Number of free arenas, either committed or decommitted. */ - uint32_t numArenasFree; - - /* Number of free, committed arenas. */ - uint32_t numArenasFreeCommitted; - - /* Number of GC cycles this chunk has survived. */ - uint32_t age; -}; - -/* - * Calculating ArenasPerChunk: - * - * In order to figure out how many Arenas will fit in a chunk, we need to know - * how much extra space is available after we allocate the header data. This - * is a problem because the header size depends on the number of arenas in the - * chunk. The two dependent fields are bitmap and decommittedArenas. - * - * For the mark bitmap, we know that each arena will use a fixed number of full - * bytes: ArenaBitmapBytes. The full size of the header data is this number - * multiplied by the eventual number of arenas we have in the header. We, - * conceptually, distribute this header data among the individual arenas and do - * not include it in the header. This way we do not have to worry about its - * variable size: it gets attached to the variable number we are computing. - * - * For the decommitted arena bitmap, we only have 1 bit per arena, so this - * technique will not work. Instead, we observe that we do not have enough - * header info to fill 8 full arenas: it is currently 4 on 64bit, less on - * 32bit. Thus, with current numbers, we need 64 bytes for decommittedArenas. - * This will not become 63 bytes unless we double the data required in the - * header. Therefore, we just compute the number of bytes required to track - * every possible arena and do not worry about slop bits, since there are too - * few to usefully allocate. - * - * To actually compute the number of arenas we can allocate in a chunk, we - * divide the amount of available space less the header info (not including - * the mark bitmap which is distributed into the arena size) by the size of - * the arena (with the mark bitmap bytes it uses). - */ -const size_t BytesPerArenaWithHeader = ArenaSize + ArenaBitmapBytes; -const size_t ChunkDecommitBitmapBytes = ChunkSize / ArenaSize / JS_BITS_PER_BYTE; -const size_t ChunkBytesAvailable = ChunkSize - sizeof(ChunkInfo) - ChunkDecommitBitmapBytes; -const size_t ArenasPerChunk = ChunkBytesAvailable / BytesPerArenaWithHeader; - -/* A chunk bitmap contains enough mark bits for all the cells in a chunk. */ -struct ChunkBitmap { - uintptr_t bitmap[ArenaBitmapWords * ArenasPerChunk]; - - JS_ALWAYS_INLINE void getMarkWordAndMask(const Cell *cell, uint32_t color, - uintptr_t **wordp, uintptr_t *maskp); - - JS_ALWAYS_INLINE bool isMarked(const Cell *cell, uint32_t color) { - uintptr_t *word, mask; - getMarkWordAndMask(cell, color, &word, &mask); - return *word & mask; - } - - JS_ALWAYS_INLINE bool markIfUnmarked(const Cell *cell, uint32_t color) { - uintptr_t *word, mask; - getMarkWordAndMask(cell, BLACK, &word, &mask); - if (*word & mask) - return false; - *word |= mask; - if (color != BLACK) { - /* - * We use getMarkWordAndMask to recalculate both mask and word as - * doing just mask << color may overflow the mask. - */ - getMarkWordAndMask(cell, color, &word, &mask); - if (*word & mask) - return false; - *word |= mask; - } - return true; - } - - JS_ALWAYS_INLINE void unmark(const Cell *cell, uint32_t color) { - uintptr_t *word, mask; - getMarkWordAndMask(cell, color, &word, &mask); - *word &= ~mask; - } - - void clear() { - PodArrayZero(bitmap); - } - -#ifdef DEBUG - bool noBitsSet(ArenaHeader *aheader) { - /* - * We assume that the part of the bitmap corresponding to the arena - * has the exact number of words so we do not need to deal with a word - * that covers bits from two arenas. - */ - JS_STATIC_ASSERT(ArenaBitmapBits == ArenaBitmapWords * JS_BITS_PER_WORD); - - uintptr_t *word, unused; - getMarkWordAndMask(reinterpret_cast(aheader->address()), BLACK, &word, &unused); - for (size_t i = 0; i != ArenaBitmapWords; i++) { - if (word[i]) - return false; - } - return true; - } -#endif -}; - -JS_STATIC_ASSERT(ArenaBitmapBytes * ArenasPerChunk == sizeof(ChunkBitmap)); - -typedef BitArray PerArenaBitmap; - -const size_t ChunkPadSize = ChunkSize - - (sizeof(Arena) * ArenasPerChunk) - - sizeof(ChunkBitmap) - - sizeof(PerArenaBitmap) - - sizeof(ChunkInfo); -JS_STATIC_ASSERT(ChunkPadSize < BytesPerArenaWithHeader); - -/* - * Chunks contain arenas and associated data structures (mark bitmap, delayed - * marking state). - */ -struct Chunk { - Arena arenas[ArenasPerChunk]; - - /* Pad to full size to ensure cache alignment of ChunkInfo. */ - uint8_t padding[ChunkPadSize]; - - ChunkBitmap bitmap; - PerArenaBitmap decommittedArenas; - ChunkInfo info; - - static Chunk *fromAddress(uintptr_t addr) { - addr &= ~ChunkMask; - return reinterpret_cast(addr); - } - - static bool withinArenasRange(uintptr_t addr) { - uintptr_t offset = addr & ChunkMask; - return offset < ArenasPerChunk * ArenaSize; - } - - static size_t arenaIndex(uintptr_t addr) { - JS_ASSERT(withinArenasRange(addr)); - return (addr & ChunkMask) >> ArenaShift; - } - - uintptr_t address() const { - uintptr_t addr = reinterpret_cast(this); - JS_ASSERT(!(addr & ChunkMask)); - return addr; - } - - bool unused() const { - return info.numArenasFree == ArenasPerChunk; - } - - bool hasAvailableArenas() const { - return info.numArenasFree != 0; - } - - inline void addToAvailableList(JSCompartment *compartment); - inline void insertToAvailableList(Chunk **insertPoint); - inline void removeFromAvailableList(); - - ArenaHeader *allocateArena(JSCompartment *comp, AllocKind kind); - - void releaseArena(ArenaHeader *aheader); - - static Chunk *allocate(JSRuntime *rt); - - /* Must be called with the GC lock taken. */ - static inline void release(JSRuntime *rt, Chunk *chunk); - static inline void releaseList(JSRuntime *rt, Chunk *chunkListHead); - - /* Must be called with the GC lock taken. */ - inline void prepareToBeFreed(JSRuntime *rt); - - /* - * Assuming that the info.prevp points to the next field of the previous - * chunk in a doubly-linked list, get that chunk. - */ - Chunk *getPrevious() { - JS_ASSERT(info.prevp); - return fromPointerToNext(info.prevp); - } - - /* Get the chunk from a pointer to its info.next field. */ - static Chunk *fromPointerToNext(Chunk **nextFieldPtr) { - uintptr_t addr = reinterpret_cast(nextFieldPtr); - JS_ASSERT((addr & ChunkMask) == offsetof(Chunk, info.next)); - return reinterpret_cast(addr - offsetof(Chunk, info.next)); - } - - private: - inline void init(); - - /* Search for a decommitted arena to allocate. */ - unsigned findDecommittedArenaOffset(); - ArenaHeader* fetchNextDecommittedArena(); - - public: - /* Unlink and return the freeArenasHead. */ - inline ArenaHeader* fetchNextFreeArena(JSRuntime *rt); - - inline void addArenaToFreeList(JSRuntime *rt, ArenaHeader *aheader); -}; - -JS_STATIC_ASSERT(sizeof(Chunk) == ChunkSize); - class ChunkPool { Chunk *emptyChunkListHead; size_t emptyCount; @@ -847,143 +80,8 @@ class ChunkPool { /* Must be called with the GC lock taken. */ void expireAndFree(JSRuntime *rt, bool releaseAll); - - /* Must be called either during the GC or with the GC lock taken. */ - JS_FRIEND_API(int64_t) countCleanDecommittedArenas(JSRuntime *rt); }; -inline uintptr_t -Cell::address() const -{ - uintptr_t addr = uintptr_t(this); - JS_ASSERT(addr % Cell::CellSize == 0); - JS_ASSERT(Chunk::withinArenasRange(addr)); - return addr; -} - -inline ArenaHeader * -Cell::arenaHeader() const -{ - uintptr_t addr = address(); - addr &= ~ArenaMask; - return reinterpret_cast(addr); -} - -Chunk * -Cell::chunk() const -{ - uintptr_t addr = uintptr_t(this); - JS_ASSERT(addr % Cell::CellSize == 0); - addr &= ~(ChunkSize - 1); - return reinterpret_cast(addr); -} - -AllocKind -Cell::getAllocKind() const -{ - return arenaHeader()->getAllocKind(); -} - -#ifdef DEBUG -inline bool -Cell::isAligned() const -{ - return Arena::isAligned(address(), arenaHeader()->getThingSize()); -} -#endif - -inline uintptr_t -ArenaHeader::address() const -{ - uintptr_t addr = reinterpret_cast(this); - JS_ASSERT(!(addr & ArenaMask)); - JS_ASSERT(Chunk::withinArenasRange(addr)); - return addr; -} - -inline Chunk * -ArenaHeader::chunk() const -{ - return Chunk::fromAddress(address()); -} - -inline bool -ArenaHeader::isEmpty() const -{ - /* Arena is empty if its first span covers the whole arena. */ - JS_ASSERT(allocated()); - size_t firstThingOffset = Arena::firstThingOffset(getAllocKind()); - return firstFreeSpanOffsets == FreeSpan::encodeOffsets(firstThingOffset, ArenaMask); -} - -inline size_t -ArenaHeader::getThingSize() const -{ - JS_ASSERT(allocated()); - return Arena::thingSize(getAllocKind()); -} - -inline ArenaHeader * -ArenaHeader::getNextDelayedMarking() const -{ - return &reinterpret_cast(nextDelayedMarking << ArenaShift)->aheader; -} - -inline void -ArenaHeader::setNextDelayedMarking(ArenaHeader *aheader) -{ - JS_ASSERT(!(uintptr_t(aheader) & ArenaMask)); - hasDelayedMarking = 1; - nextDelayedMarking = aheader->arenaAddress() >> ArenaShift; -} - -JS_ALWAYS_INLINE void -ChunkBitmap::getMarkWordAndMask(const Cell *cell, uint32_t color, - uintptr_t **wordp, uintptr_t *maskp) -{ - size_t bit = (cell->address() & ChunkMask) / Cell::CellSize + color; - JS_ASSERT(bit < ArenaBitmapBits * ArenasPerChunk); - *maskp = uintptr_t(1) << (bit % JS_BITS_PER_WORD); - *wordp = &bitmap[bit / JS_BITS_PER_WORD]; -} - -static void -AssertValidColor(const void *thing, uint32_t color) -{ -#ifdef DEBUG - ArenaHeader *aheader = reinterpret_cast(thing)->arenaHeader(); - JS_ASSERT_IF(color, color < aheader->getThingSize() / Cell::CellSize); -#endif -} - -inline bool -Cell::isMarked(uint32_t color) const -{ - AssertValidColor(this, color); - return chunk()->bitmap.isMarked(this, color); -} - -bool -Cell::markIfUnmarked(uint32_t color) const -{ - AssertValidColor(this, color); - return chunk()->bitmap.markIfUnmarked(this, color); -} - -void -Cell::unmark(uint32_t color) const -{ - JS_ASSERT(color != BLACK); - AssertValidColor(this, color); - chunk()->bitmap.unmark(this, color); -} - -JSCompartment * -Cell::compartment() const -{ - return arenaHeader()->compartment; -} - static inline JSGCTraceKind MapAllocToTraceKind(AllocKind thingKind) { @@ -1058,7 +156,6 @@ struct ArenaLists { ArenaList arenaLists[FINALIZE_LIMIT]; -#ifdef JS_THREADSAFE /* * The background finalization adds the finalized arenas to the list at * the *cursor position. backgroundFinalizeState controls the interaction @@ -1082,27 +179,22 @@ struct ArenaLists { }; volatile uintptr_t backgroundFinalizeState[FINALIZE_LIMIT]; -#endif public: ArenaLists() { for (size_t i = 0; i != FINALIZE_LIMIT; ++i) freeLists[i].initAsEmpty(); -#ifdef JS_THREADSAFE for (size_t i = 0; i != FINALIZE_LIMIT; ++i) backgroundFinalizeState[i] = BFS_DONE; -#endif } ~ArenaLists() { for (size_t i = 0; i != FINALIZE_LIMIT; ++i) { -#ifdef JS_THREADSAFE /* * We can only call this during the shutdown after the last GC when * the background finalization is disabled. */ JS_ASSERT(backgroundFinalizeState[i] == BFS_DONE); -#endif ArenaHeader **headp = &arenaLists[i].head; while (ArenaHeader *aheader = *headp) { *headp = aheader->next; @@ -1121,42 +213,33 @@ struct ArenaLists { bool arenaListsAreEmpty() const { for (size_t i = 0; i != FINALIZE_LIMIT; ++i) { -#ifdef JS_THREADSAFE /* * The arena cannot be empty if the background finalization is not yet * done. */ if (backgroundFinalizeState[i] != BFS_DONE) return false; -#endif if (arenaLists[i].head) return false; } return true; } -#ifdef DEBUG - bool checkArenaListAllUnmarked() const { + void unmarkAll() { for (size_t i = 0; i != FINALIZE_LIMIT; ++i) { -# ifdef JS_THREADSAFE /* The background finalization must have stopped at this point. */ JS_ASSERT(backgroundFinalizeState[i] == BFS_DONE || backgroundFinalizeState[i] == BFS_JUST_FINISHED); -# endif for (ArenaHeader *aheader = arenaLists[i].head; aheader; aheader = aheader->next) { - if (!aheader->chunk()->bitmap.noBitsSet(aheader)) - return false; + uintptr_t *word = aheader->chunk()->bitmap.arenaBits(aheader); + memset(word, 0, ArenaBitmapWords * sizeof(uintptr_t)); } } - return true; } -#endif -#ifdef JS_THREADSAFE bool doneBackgroundFinalize(AllocKind kind) const { return backgroundFinalizeState[kind] == BFS_DONE; } -#endif /* * Return the free list back to the arena so the GC finalization will not @@ -1255,9 +338,7 @@ struct ArenaLists { void finalizeShapes(FreeOp *fop); void finalizeScripts(FreeOp *fop); -#ifdef JS_THREADSAFE static void backgroundFinalize(FreeOp *fop, ArenaHeader *listHead); -#endif private: inline void finalizeNow(FreeOp *fop, AllocKind thingKind); @@ -1348,12 +429,6 @@ js_LockGCThingRT(JSRuntime *rt, void *thing); extern void js_UnlockGCThingRT(JSRuntime *rt, void *thing); -extern JS_FRIEND_API(bool) -IsAboutToBeFinalized(const js::gc::Cell *thing); - -extern bool -IsAboutToBeFinalized(const js::Value &value); - extern bool js_IsAddressableGCThing(JSRuntime *rt, uintptr_t w, js::gc::AllocKind *thingKind, void **thing); @@ -1383,6 +458,9 @@ extern void ShrinkGCBuffers(JSRuntime *rt); extern void +ReleaseAllJITCode(FreeOp *op); + +extern JS_FRIEND_API(void) PrepareForFullGC(JSRuntime *rt); /* @@ -1402,6 +480,9 @@ GC(JSRuntime *rt, JSGCInvocationKind gckind, js::gcreason::Reason reason); extern void GCSlice(JSRuntime *rt, JSGCInvocationKind gckind, js::gcreason::Reason reason); +extern void +GCFinalSlice(JSRuntime *rt, JSGCInvocationKind gckind, js::gcreason::Reason reason); + extern void GCDebugSlice(JSRuntime *rt, bool limit, int64_t objCount); @@ -1415,8 +496,14 @@ namespace js { void InitTracer(JSTracer *trc, JSRuntime *rt, JSTraceCallback callback); -#ifdef JS_THREADSAFE - +/* + * Helper that implements sweeping and allocation for kinds that can be swept + * and allocated off the main thread. + * + * In non-threadsafe builds, all actual sweeping and allocation is performed + * on the main thread, but GCHelperThread encapsulates this from clients as + * much as possible. + */ class GCHelperThread { enum State { IDLE, @@ -1543,7 +630,6 @@ class GCHelperThread { bool prepareForBackgroundSweep(); }; -#endif /* JS_THREADSAFE */ struct GCChunkHasher { typedef gc::Chunk *Lookup; @@ -1757,6 +843,7 @@ struct GCMarker : public JSTracer { ObjectTag, TypeTag, XmlTag, + ArenaTag, SavedValueArrayTag, LastTag = SavedValueArrayTag }; @@ -1783,13 +870,19 @@ struct GCMarker : public JSTracer { pushTaggedPtr(ObjectTag, obj); } + void pushArenaList(gc::ArenaHeader *firstArena) { + pushTaggedPtr(ArenaTag, firstArena); + } + void pushType(types::TypeObject *type) { pushTaggedPtr(TypeTag, type); } +#if JS_HAS_XML_SUPPORT void pushXML(JSXML *xml) { pushTaggedPtr(XmlTag, xml); } +#endif uint32_t getMarkColor() const { return color; @@ -1880,7 +973,7 @@ struct GCMarker : public JSTracer { bool restoreValueArray(JSObject *obj, void **vpp, void **endp); void saveValueRanges(); inline void processMarkStackTop(SliceBudget &budget); - void processMarkStackOther(uintptr_t tag, uintptr_t addr); + void processMarkStackOther(SliceBudget &budget, uintptr_t tag, uintptr_t addr); void appendGrayRoot(void *thing, JSGCTraceKind kind); @@ -1948,6 +1041,12 @@ extern JS_FRIEND_API(void) IterateCells(JSRuntime *rt, JSCompartment *compartment, gc::AllocKind thingKind, void *data, IterateCellCallback cellCallback); +/* + * Invoke cellCallback on every gray JS_OBJECT in the given compartment. + */ +extern JS_FRIEND_API(void) +IterateGrayObjects(JSCompartment *compartment, GCThingCallback *cellCallback, void *data); + } /* namespace js */ extern void @@ -1972,20 +1071,16 @@ RunDebugGC(JSContext *cx); void SetDeterministicGC(JSContext *cx, bool enabled); -#if defined(JSGC_ROOT_ANALYSIS) && defined(DEBUG) && !defined(JS_THREADSAFE) -/* Overwrites stack references to GC things which have not been rooted. */ -void CheckStackRoots(JSContext *cx); - -inline void MaybeCheckStackRoots(JSContext *cx) { CheckStackRoots(cx); } -#else -inline void MaybeCheckStackRoots(JSContext *cx) {} -#endif - const int ZealPokeValue = 1; const int ZealAllocValue = 2; const int ZealFrameGCValue = 3; const int ZealVerifierValue = 4; const int ZealFrameVerifierValue = 5; +const int ZealStackRootingSafeValue = 6; +const int ZealStackRootingValue = 7; +const int ZealIncrementalRootsThenFinish = 8; +const int ZealIncrementalMarkAllThenFinish = 9; +const int ZealIncrementalMultipleSlices = 10; #ifdef JS_GC_ZEAL diff --git a/scripting/javascript/spidermonkey-android/include/jshash.h b/scripting/javascript/spidermonkey-android/include/jshash.h index acd64af4a9..2b9f8a9e39 100644 --- a/scripting/javascript/spidermonkey-android/include/jshash.h +++ b/scripting/javascript/spidermonkey-android/include/jshash.h @@ -1,41 +1,8 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jshash_h___ #define jshash_h___ diff --git a/scripting/javascript/spidermonkey-android/include/jslock.h b/scripting/javascript/spidermonkey-android/include/jslock.h index adbddd9d2b..15a0e73806 100644 --- a/scripting/javascript/spidermonkey-android/include/jslock.h +++ b/scripting/javascript/spidermonkey-android/include/jslock.h @@ -1,41 +1,8 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jslock_h__ #define jslock_h__ @@ -56,6 +23,10 @@ #else /* JS_THREADSAFE */ +typedef struct PRThread PRThread; +typedef struct PRCondVar PRCondVar; +typedef struct PRLock PRLock; + # define JS_ATOMIC_INCREMENT(p) (++*(p)) # define JS_ATOMIC_DECREMENT(p) (--*(p)) # define JS_ATOMIC_ADD(p,v) (*(p) += (v)) diff --git a/scripting/javascript/spidermonkey-android/include/json.h b/scripting/javascript/spidermonkey-android/include/json.h index 64c36dbca0..af11f9f89c 100644 --- a/scripting/javascript/spidermonkey-android/include/json.h +++ b/scripting/javascript/spidermonkey-android/include/json.h @@ -1,39 +1,6 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is SpiderMonkey JSON. - * - * The Initial Developer of the Original Code is - * Mozilla Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998-1999 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Robert Sayre - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef json_h___ #define json_h___ @@ -50,9 +17,14 @@ extern JSObject * js_InitJSONClass(JSContext *cx, JSObject *obj); extern JSBool -js_Stringify(JSContext *cx, js::Value *vp, JSObject *replacer, js::Value space, +js_Stringify(JSContext *cx, js::MutableHandleValue vp, + JSObject *replacer, js::Value space, js::StringBuffer &sb); +// Avoid build errors on certain platforms that define these names as constants +#undef STRICT +#undef LEGACY + /* * The type of JSON decoding to perform. Strict decoding is to-the-spec; * legacy decoding accepts a few non-JSON syntaxes historically accepted by the diff --git a/scripting/javascript/spidermonkey-android/include/jsperf.h b/scripting/javascript/spidermonkey-android/include/jsperf.h index 4321cc7588..0438bc518e 100644 --- a/scripting/javascript/spidermonkey-android/include/jsperf.h +++ b/scripting/javascript/spidermonkey-android/include/jsperf.h @@ -1,40 +1,7 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Zack Weinberg (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsperf_h___ #define jsperf_h___ diff --git a/scripting/javascript/spidermonkey-android/include/jsprf.h b/scripting/javascript/spidermonkey-android/include/jsprf.h index 9efbd64131..4c72b691f8 100644 --- a/scripting/javascript/spidermonkey-android/include/jsprf.h +++ b/scripting/javascript/spidermonkey-android/include/jsprf.h @@ -1,40 +1,7 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsprf_h___ #define jsprf_h___ diff --git a/scripting/javascript/spidermonkey-android/include/jsproto.tbl b/scripting/javascript/spidermonkey-android/include/jsproto.tbl index 20dbbd24a7..5e37999fac 100644 --- a/scripting/javascript/spidermonkey-android/include/jsproto.tbl +++ b/scripting/javascript/spidermonkey-android/include/jsproto.tbl @@ -1,40 +1,9 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set sw=4 ts=8 et tw=80 ft=c: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is SpiderMonkey 1.7 work in progress, released - * February 14, 2006. - * - * The Initial Developer of the Original Code is - * Brendan Eich - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "jsversion.h" @@ -94,6 +63,7 @@ JS_PROTO(AnyName, 35, js_InitNullClass) JS_PROTO(WeakMap, 36, js_InitWeakMapClass) JS_PROTO(Map, 37, js_InitMapClass) JS_PROTO(Set, 38, js_InitSetClass) +JS_PROTO(DataView, 39, js_InitTypedArrayClasses) #undef XML_INIT #undef NAMESPACE_INIT diff --git a/scripting/javascript/spidermonkey-android/include/jsproxy.h b/scripting/javascript/spidermonkey-android/include/jsproxy.h index d65919b940..5fd5848377 100644 --- a/scripting/javascript/spidermonkey-android/include/jsproxy.h +++ b/scripting/javascript/spidermonkey-android/include/jsproxy.h @@ -1,43 +1,9 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=4 sw=4 et tw=99: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released - * May 28, 2008. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Andreas Gal - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsproxy_h___ #define jsproxy_h___ @@ -47,33 +13,91 @@ namespace js { -/* Base class for all C++ proxy handlers. */ -class JS_FRIEND_API(ProxyHandler) { +class Wrapper; + +/* + * A proxy is a JSObject that implements generic behavior by providing custom + * implementations for each object trap. The implementation for each trap is + * provided by a C++ object stored on the proxy, known as its handler. + * + * A major use case for proxies is to forward each trap to another object, + * known as its target. The target can be an arbitrary C++ object. Not every + * proxy has the notion of a target, however. + * + * Proxy traps are grouped into fundamental and derived traps. Every proxy has + * to at least provide implementations for the fundamental traps, but the + * derived traps can be implemented in terms of the fundamental ones. + * + * To minimize code duplication, a set of abstract proxy handler classes is + * provided, from which other handlers may inherit. These abstract classes + * are organized in the following hierarchy: + * + * BaseProxyHandler + * | + * IndirectProxyHandler + * | + * DirectProxyHandler + */ + +/* + * BaseProxyHandler is the most generic kind of proxy handler. It does not make + * any assumptions about the target. Consequently, it does not provide any + * default implementation for the fundamental traps. It does, however, implement + * the derived traps in terms of the fundamental ones. This allows consumers of + * this class to define any custom behavior they want. + */ +class JS_FRIEND_API(BaseProxyHandler) { void *mFamily; public: - explicit ProxyHandler(void *family); - virtual ~ProxyHandler(); + explicit BaseProxyHandler(void *family); + virtual ~BaseProxyHandler(); + + inline void *family() { + return mFamily; + } + + virtual bool isOuterWindow() { + return false; + } + + /* + * The function Wrapper::wrapperHandler takes a pointer to a + * BaseProxyHandler and returns a pointer to a Wrapper if and only if the + * BaseProxyHandler is a wrapper handler (otherwise, it returns NULL). + * + * Unfortunately, we can't inherit Wrapper from BaseProxyHandler, since that + * would create a dreaded diamond, and we can't use dynamic_cast to cast + * BaseProxyHandler to Wrapper, since that would require us to compile with + * run-time type information. Hence the need for this virtual function. + */ + virtual Wrapper *toWrapper() { + return NULL; + } /* ES5 Harmony fundamental proxy traps. */ - virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set, - PropertyDescriptor *desc) = 0; - virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set, + virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, + bool set, PropertyDescriptor *desc) = 0; + virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, + jsid id, bool set, PropertyDescriptor *desc) = 0; virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, PropertyDescriptor *desc) = 0; - virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props) = 0; + virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, + AutoIdVector &props) = 0; virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) = 0; - virtual bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props) = 0; - virtual bool fix(JSContext *cx, JSObject *proxy, Value *vp) = 0; + virtual bool enumerate(JSContext *cx, JSObject *proxy, + AutoIdVector &props) = 0; /* ES5 Harmony derived proxy traps. */ virtual bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp); virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp); - virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, Value *vp); - virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict, - Value *vp); + virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, + jsid id, Value *vp); + virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, + jsid id, bool strict, Value *vp); virtual bool keys(JSContext *cx, JSObject *proxy, AutoIdVector &props); - virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags, Value *vp); + virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags, + Value *vp); /* Spidermonkey extensions. */ virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp); @@ -88,17 +112,87 @@ class JS_FRIEND_API(ProxyHandler) { virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp); virtual bool iteratorNext(JSContext *cx, JSObject *proxy, Value *vp); virtual void finalize(JSFreeOp *fop, JSObject *proxy); - virtual void trace(JSTracer *trc, JSObject *proxy); virtual bool getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp, bool *present); +}; - virtual bool isOuterWindow() { - return false; - } +/* + * IndirectProxyHandler assumes that a target exists. Moreover, it assumes the + * target is a JSObject. Consequently, it provides default implementations for + * the fundamental traps that forward their behavior to the target. The derived + * traps, however, are inherited from BaseProxyHandler, and therefore still + * implemented in terms of the fundamental ones. This allows consumers of this + * class to define custom behavior without implementing the entire gamut of + * proxy traps. + */ +class JS_PUBLIC_API(IndirectProxyHandler) : public BaseProxyHandler { + public: + explicit IndirectProxyHandler(void *family); - inline void *family() { - return mFamily; - } + /* ES5 Harmony fundamental proxy traps. */ + virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, + bool set, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, + jsid id, bool set, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, + AutoIdVector &props) MOZ_OVERRIDE; + virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, + bool *bp) MOZ_OVERRIDE; + virtual bool enumerate(JSContext *cx, JSObject *proxy, + AutoIdVector &props) MOZ_OVERRIDE; + + /* Spidermonkey extensions. */ + virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc, + Value *vp) MOZ_OVERRIDE; + virtual bool construct(JSContext *cx, JSObject *proxy, unsigned argc, + Value *argv, Value *rval) MOZ_OVERRIDE; + virtual bool nativeCall(JSContext *cx, JSObject *proxy, Class *clasp, + Native native, CallArgs args) MOZ_OVERRIDE; + virtual bool hasInstance(JSContext *cx, JSObject *proxy, const Value *vp, + bool *bp) MOZ_OVERRIDE; + virtual JSType typeOf(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE; + virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, + JSContext *cx) MOZ_OVERRIDE; + virtual JSString *obj_toString(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE; + virtual JSString *fun_toString(JSContext *cx, JSObject *proxy, + unsigned indent) MOZ_OVERRIDE; + virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, + RegExpGuard *g) MOZ_OVERRIDE; + virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint, + Value *vp) MOZ_OVERRIDE; + virtual bool iteratorNext(JSContext *cx, JSObject *proxy, + Value *vp) MOZ_OVERRIDE; +}; + +/* + * DirectProxyHandler has the same assumptions about the target as its base, + * IndirectProxyHandler. Its fundamental traps are inherited from this class, + * and therefore forward their behavior to the target. The derived traps, + * however, are overrided so that, they too, forward their behavior to the + * target. This allows consumers of this class to forward to another object as + * transparently as possible. + */ +class JS_PUBLIC_API(DirectProxyHandler) : public IndirectProxyHandler { +public: + explicit DirectProxyHandler(void *family); + + /* ES5 Harmony derived proxy traps. */ + virtual bool has(JSContext *cx, JSObject *proxy, jsid id, + bool *bp) MOZ_OVERRIDE; + virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id, + bool *bp) MOZ_OVERRIDE; + virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, + jsid id, Value *vp) MOZ_OVERRIDE; + virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, + jsid id, bool strict, Value *vp) MOZ_OVERRIDE; + virtual bool keys(JSContext *cx, JSObject *proxy, + AutoIdVector &props) MOZ_OVERRIDE; + virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags, + Value *vp) MOZ_OVERRIDE; }; /* Dispatch point for handlers that executes the appropriate C++ or scripted traps. */ @@ -117,7 +211,6 @@ class Proxy { static bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props); static bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp); static bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props); - static bool fix(JSContext *cx, JSObject *proxy, Value *vp); /* ES5 Harmony derived proxy traps. */ static bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp); @@ -178,11 +271,11 @@ const uint32_t JSSLOT_PROXY_EXTRA = 2; const uint32_t JSSLOT_PROXY_CALL = 4; const uint32_t JSSLOT_PROXY_CONSTRUCT = 5; -inline ProxyHandler * +inline BaseProxyHandler * GetProxyHandler(const JSObject *obj) { JS_ASSERT(IsProxy(obj)); - return (ProxyHandler *) GetReservedSlot(obj, JSSLOT_PROXY_HANDLER).toPrivate(); + return (BaseProxyHandler *) GetReservedSlot(obj, JSSLOT_PROXY_HANDLER).toPrivate(); } inline const Value & @@ -192,6 +285,20 @@ GetProxyPrivate(const JSObject *obj) return GetReservedSlot(obj, JSSLOT_PROXY_PRIVATE); } +inline JSObject * +GetProxyTargetObject(const JSObject *obj) +{ + JS_ASSERT(IsProxy(obj)); + return GetProxyPrivate(obj).toObjectOrNull(); +} + +inline const Value & +GetProxyCall(const JSObject *obj) +{ + JS_ASSERT(IsFunctionProxy(obj)); + return GetReservedSlot(obj, JSSLOT_PROXY_CALL); +} + inline const Value & GetProxyExtra(const JSObject *obj, size_t n) { @@ -200,16 +307,7 @@ GetProxyExtra(const JSObject *obj, size_t n) } inline void -SetProxyExtra(JSObject *obj, size_t n, const Value &extra) -{ - JS_ASSERT(IsProxy(obj)); - JS_ASSERT(n <= 1); - SetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n, extra); -} - - -inline void -SetProxyHandler(JSObject *obj, ProxyHandler *handler) +SetProxyHandler(JSObject *obj, BaseProxyHandler *handler) { JS_ASSERT(IsProxy(obj)); SetReservedSlot(obj, JSSLOT_PROXY_HANDLER, PrivateValue(handler)); @@ -222,8 +320,16 @@ SetProxyPrivate(JSObject *obj, const Value &value) SetReservedSlot(obj, JSSLOT_PROXY_PRIVATE, value); } +inline void +SetProxyExtra(JSObject *obj, size_t n, const Value &extra) +{ + JS_ASSERT(IsProxy(obj)); + JS_ASSERT(n <= 1); + SetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n, extra); +} + JS_FRIEND_API(JSObject *) -NewProxyObject(JSContext *cx, ProxyHandler *handler, const Value &priv, +NewProxyObject(JSContext *cx, BaseProxyHandler *handler, const Value &priv, JSObject *proto, JSObject *parent, JSObject *call = NULL, JSObject *construct = NULL); diff --git a/scripting/javascript/spidermonkey-android/include/jsprvtd.h b/scripting/javascript/spidermonkey-android/include/jsprvtd.h index ff178e4bf5..19b5aef3c2 100644 --- a/scripting/javascript/spidermonkey-android/include/jsprvtd.h +++ b/scripting/javascript/spidermonkey-android/include/jsprvtd.h @@ -1,41 +1,8 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsprvtd_h___ #define jsprvtd_h___ @@ -84,7 +51,6 @@ typedef struct JSArgumentFormatMap JSArgumentFormatMap; typedef struct JSGCThing JSGCThing; typedef struct JSGenerator JSGenerator; typedef struct JSNativeEnumerator JSNativeEnumerator; -typedef struct JSProperty JSProperty; typedef struct JSSharpObjectMap JSSharpObjectMap; typedef struct JSTryNote JSTryNote; @@ -95,7 +61,10 @@ typedef struct JSPrinter JSPrinter; typedef struct JSStackHeader JSStackHeader; typedef struct JSSubString JSSubString; typedef struct JSSpecializedNative JSSpecializedNative; + +#if JS_HAS_XML_SUPPORT typedef struct JSXML JSXML; +#endif /* * Template declarations. @@ -160,9 +129,7 @@ class StackFrame; class StackSegment; class StackSpace; class ContextStack; -class FrameRegsIter; -class CallReceiver; -class CallArgs; +class ScriptFrameIter; struct BytecodeEmitter; struct Definition; @@ -170,6 +137,7 @@ struct FunctionBox; struct ObjectBox; struct ParseNode; struct Parser; +struct SharedContext; class TokenStream; struct Token; struct TokenPos; @@ -178,8 +146,8 @@ struct TreeContext; class UpvarCookie; class Proxy; -class ProxyHandler; -class Wrapper; +class BaseProxyHandler; +class DirectWrapper; class CrossCompartmentWrapper; class TempAllocPolicy; @@ -206,10 +174,9 @@ struct StackShape; class MultiDeclRange; class ParseMapPool; -class DefnOrHeader; +class DefinitionList; typedef InlineMap AtomDefnMap; typedef InlineMap AtomIndexMap; -typedef InlineMap AtomDOHMap; typedef Vector UpvarCookies; class Breakpoint; @@ -256,17 +223,13 @@ typedef JS::Handle HandleTypeObject; typedef JS::Handle HandleAtom; typedef JS::Handle HandlePropertyName; -typedef JS::Root RootShape; -typedef JS::Root RootBaseShape; -typedef JS::Root RootTypeObject; -typedef JS::Root RootAtom; -typedef JS::Root RootPropertyName; +typedef JS::MutableHandle MutableHandleShape; -typedef JS::RootedVar RootedVarShape; -typedef JS::RootedVar RootedVarBaseShape; -typedef JS::RootedVar RootedVarTypeObject; -typedef JS::RootedVar RootedVarAtom; -typedef JS::RootedVar RootedVarPropertyName; +typedef JS::Rooted RootedShape; +typedef JS::Rooted RootedBaseShape; +typedef JS::Rooted RootedTypeObject; +typedef JS::Rooted RootedAtom; +typedef JS::Rooted RootedPropertyName; enum XDRMode { XDR_ENCODE, @@ -404,41 +367,23 @@ typedef struct JSDebugHooks { /* js::ObjectOps function pointer typedefs. */ -/* - * Look for id in obj and its prototype chain, returning false on error or - * exception, true on success. On success, return null in *propp if id was - * not found. If id was found, return the first object searching from obj - * along its prototype chain in which id names a direct property in *objp, and - * return a non-null, opaque property pointer in *propp. - * - * If JSLookupPropOp succeeds and returns with *propp non-null, that pointer - * may be passed as the prop parameter to a JSAttributesOp, as a short-cut - * that bypasses id re-lookup. - */ -typedef JSBool -(* JSLookupPropOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, - JSProperty **propp); - -/* - * Get or set attributes of the property obj[id]. Return false on error or - * exception, true with current attributes in *attrsp. - */ -typedef JSBool -(* JSAttributesOp)(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp); - /* * A generic type for functions mapping an object to another object, or null * if an error or exception was thrown on cx. */ typedef JSObject * -(* JSObjectOp)(JSContext *cx, JSObject *obj); +(* JSObjectOp)(JSContext *cx, JSHandleObject obj); + +/* Signature for class initialization ops. */ +typedef JSObject * +(* JSClassInitializerOp)(JSContext *cx, JSObject *obj); /* * Hook that creates an iterator object for a given object. Returns the * iterator object or null if an error or exception was thrown on cx. */ typedef JSObject * -(* JSIteratorOp)(JSContext *cx, JSObject *obj, JSBool keysonly); +(* JSIteratorOp)(JSContext *cx, JSHandleObject obj, JSBool keysonly); /* * The following determines whether JS_EncodeCharacters and JS_DecodeBytes diff --git a/scripting/javascript/spidermonkey-android/include/jspubtd.h b/scripting/javascript/spidermonkey-android/include/jspubtd.h index 47fad22a74..45864ca0d6 100644 --- a/scripting/javascript/spidermonkey-android/include/jspubtd.h +++ b/scripting/javascript/spidermonkey-android/include/jspubtd.h @@ -1,41 +1,8 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jspubtd_h___ #define jspubtd_h___ @@ -148,7 +115,11 @@ typedef enum JSProtoKey { /* js_CheckAccess mode enumeration. */ typedef enum JSAccessMode { JSACC_PROTO = 0, /* XXXbe redundant w.r.t. id */ - JSACC_PARENT = 1, /* XXXbe redundant w.r.t. id */ + + /* + * enum value #1 formerly called JSACC_PARENT, + * gap preserved for ABI compatibility. + */ /* * enum value #2 formerly called JSACC_IMPORT, @@ -249,7 +220,7 @@ JS_END_EXTERN_C namespace JS { template -class Root; +class Rooted; class SkipRoot; @@ -261,8 +232,11 @@ enum ThingRootKind THING_ROOT_TYPE_OBJECT, THING_ROOT_STRING, THING_ROOT_SCRIPT, + THING_ROOT_XML, THING_ROOT_ID, + THING_ROOT_PROPERTY_ID, THING_ROOT_VALUE, + THING_ROOT_TYPE, THING_ROOT_LIMIT }; @@ -280,15 +254,15 @@ struct ContextFriendFields { return reinterpret_cast(cx); } -#ifdef JSGC_ROOT_ANALYSIS - +#if defined(JSGC_ROOT_ANALYSIS) || defined(JSGC_USE_EXACT_ROOTING) /* * Stack allocated GC roots for stack GC heap pointers, which may be * overwritten if moved during a GC. */ - Root *thingGCRooters[THING_ROOT_LIMIT]; + Rooted *thingGCRooters[THING_ROOT_LIMIT]; +#endif -#ifdef DEBUG +#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE) /* * Stack allocated list of stack locations which hold non-relocatable * GC heap pointers (where the target is rooted somewhere else) or integer @@ -299,8 +273,6 @@ struct ContextFriendFields { */ SkipRoot *skipGCRooters; #endif - -#endif /* JSGC_ROOT_ANALYSIS */ }; } /* namespace JS */ diff --git a/scripting/javascript/spidermonkey-android/include/jstypedarray.h b/scripting/javascript/spidermonkey-android/include/jstypedarray.h deleted file mode 100644 index bfed3c2c73..0000000000 --- a/scripting/javascript/spidermonkey-android/include/jstypedarray.h +++ /dev/null @@ -1,364 +0,0 @@ -/* -*- Mode: c++; c-basic-offset: 4; tab-width: 40; indent-tabs-mode: nil -*- */ -/* vim: set ts=40 sw=4 et tw=99: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla WebGL impl - * - * The Initial Developer of the Original Code is - * Mozilla Foundation - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Vladimir Vukicevic - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jstypedarray_h -#define jstypedarray_h - -#include "jsapi.h" -#include "jsclass.h" - -#include "gc/Barrier.h" - -typedef struct JSProperty JSProperty; - -namespace js { - -/* - * ArrayBuffer - * - * This class holds the underlying raw buffer that the TypedArray - * subclasses access. It can be created explicitly and passed to a - * TypedArray subclass, or can be created implicitly by constructing a - * TypedArray with a size. - */ -struct JS_FRIEND_API(ArrayBuffer) { - static Class slowClass; - static JSPropertySpec jsprops[]; - static JSFunctionSpec jsfuncs[]; - - static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp); - - static JSBool fun_slice(JSContext *cx, unsigned argc, Value *vp); - - static JSBool class_constructor(JSContext *cx, unsigned argc, Value *vp); - - static JSObject *create(JSContext *cx, int32_t nbytes, uint8_t *contents = NULL); - - static JSObject *createSlice(JSContext *cx, JSObject *arrayBuffer, - uint32_t begin, uint32_t end); - - ArrayBuffer() - { - } - - ~ArrayBuffer(); - - static void - obj_trace(JSTracer *trc, JSObject *obj); - - static JSBool - obj_lookupGeneric(JSContext *cx, JSObject *obj, jsid id, - JSObject **objp, JSProperty **propp); - static JSBool - obj_lookupProperty(JSContext *cx, JSObject *obj, PropertyName *name, - JSObject **objp, JSProperty **propp); - static JSBool - obj_lookupElement(JSContext *cx, JSObject *obj, uint32_t index, - JSObject **objp, JSProperty **propp); - static JSBool - obj_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp, - JSProperty **propp); - - static JSBool - obj_defineGeneric(JSContext *cx, JSObject *obj, jsid id, const Value *v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs); - static JSBool - obj_defineProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value *v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs); - static JSBool - obj_defineElement(JSContext *cx, JSObject *obj, uint32_t index, const Value *v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs); - static JSBool - obj_defineSpecial(JSContext *cx, JSObject *obj, SpecialId sid, const Value *v, - PropertyOp getter, StrictPropertyOp setter, unsigned attrs); - - static JSBool - obj_getGeneric(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp); - - static JSBool - obj_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, - Value *vp); - - static JSBool - obj_getElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp); - static JSBool - obj_getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, - Value *vp, bool *present); - - static JSBool - obj_getSpecial(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp); - - static JSBool - obj_setGeneric(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict); - static JSBool - obj_setProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict); - static JSBool - obj_setElement(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict); - static JSBool - obj_setSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict); - - static JSBool - obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp); - static JSBool - obj_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp); - static JSBool - obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp); - static JSBool - obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp); - - static JSBool - obj_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp); - static JSBool - obj_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp); - static JSBool - obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp); - static JSBool - obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp); - - static JSBool - obj_deleteProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *rval, JSBool strict); - static JSBool - obj_deleteElement(JSContext *cx, JSObject *obj, uint32_t index, Value *rval, JSBool strict); - static JSBool - obj_deleteSpecial(JSContext *cx, JSObject *obj, SpecialId sid, Value *rval, JSBool strict); - - static JSBool - obj_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, - Value *statep, jsid *idp); - - static JSType - obj_typeOf(JSContext *cx, JSObject *obj); - - static JSObject * - getArrayBuffer(JSObject *obj); -}; - -/* - * TypedArray - * - * The non-templated base class for the specific typed implementations. - * This class holds all the member variables that are used by - * the subclasses. - */ - -struct JS_FRIEND_API(TypedArray) { - enum { - TYPE_INT8 = 0, - TYPE_UINT8, - TYPE_INT16, - TYPE_UINT16, - TYPE_INT32, - TYPE_UINT32, - TYPE_FLOAT32, - TYPE_FLOAT64, - - /* - * Special type that's a uint8, but assignments are clamped to 0 .. 255. - * Treat the raw data type as a uint8. - */ - TYPE_UINT8_CLAMPED, - - TYPE_MAX - }; - - enum { - /* Properties of the typed array stored in reserved slots. */ - FIELD_LENGTH = 0, - FIELD_BYTEOFFSET, - FIELD_BYTELENGTH, - FIELD_TYPE, - FIELD_BUFFER, - FIELD_MAX, - NUM_FIXED_SLOTS = 7 - }; - - // and MUST NOT be used to construct new objects. - static Class fastClasses[TYPE_MAX]; - - // These are the slow/original classes, used - // fo constructing new objects - static Class slowClasses[TYPE_MAX]; - - static JSPropertySpec jsprops[]; - - static JSObject *getTypedArray(JSObject *obj); - - static JSBool prop_getBuffer(JSContext *cx, JSObject *obj, jsid id, Value *vp); - static JSBool prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp); - static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp); - static JSBool prop_getLength(JSContext *cx, JSObject *obj, jsid id, Value *vp); - - static JSBool obj_lookupGeneric(JSContext *cx, JSObject *obj, jsid id, - JSObject **objp, JSProperty **propp); - static JSBool obj_lookupProperty(JSContext *cx, JSObject *obj, PropertyName *name, - JSObject **objp, JSProperty **propp); - static JSBool obj_lookupElement(JSContext *cx, JSObject *obj, uint32_t index, - JSObject **objp, JSProperty **propp); - static JSBool obj_lookupSpecial(JSContext *cx, JSObject *obj, SpecialId sid, - JSObject **objp, JSProperty **propp); - - static JSBool obj_getGenericAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp); - static JSBool obj_getPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp); - static JSBool obj_getElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp); - static JSBool obj_getSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp); - - static JSBool obj_setGenericAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp); - static JSBool obj_setPropertyAttributes(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp); - static JSBool obj_setElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp); - static JSBool obj_setSpecialAttributes(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp); - - static uint32_t getLength(JSObject *obj); - static uint32_t getByteOffset(JSObject *obj); - static uint32_t getByteLength(JSObject *obj); - static uint32_t getType(JSObject *obj); - static JSObject * getBuffer(JSObject *obj); - static void * getDataOffset(JSObject *obj); - - public: - static bool - isArrayIndex(JSContext *cx, JSObject *obj, jsid id, uint32_t *ip = NULL); - - static inline uint32_t slotWidth(int atype) { - switch (atype) { - case js::TypedArray::TYPE_INT8: - case js::TypedArray::TYPE_UINT8: - case js::TypedArray::TYPE_UINT8_CLAMPED: - return 1; - case js::TypedArray::TYPE_INT16: - case js::TypedArray::TYPE_UINT16: - return 2; - case js::TypedArray::TYPE_INT32: - case js::TypedArray::TYPE_UINT32: - case js::TypedArray::TYPE_FLOAT32: - return 4; - case js::TypedArray::TYPE_FLOAT64: - return 8; - default: - JS_NOT_REACHED("invalid typed array type"); - return 0; - } - } - - static inline int slotWidth(JSObject *obj) { - return slotWidth(getType(obj)); - } - - static int lengthOffset(); - static int dataOffset(); -}; - -extern bool -IsFastTypedArrayClass(const Class *clasp); - -} // namespace js - -/* Friend API methods */ - -JS_FRIEND_API(JSObject *) -js_InitTypedArrayClasses(JSContext *cx, JSObject *obj); - -JS_FRIEND_API(JSBool) -js_IsTypedArray(JSObject *obj); - -JS_FRIEND_API(JSBool) -js_IsArrayBuffer(JSObject *obj); - -JS_FRIEND_API(JSObject *) -js_CreateArrayBuffer(JSContext *cx, uint32_t nbytes); - -/* - * Create a new typed array of type atype (one of the TypedArray - * enumerant values above), with nelements elements. - */ -JS_FRIEND_API(JSObject *) -js_CreateTypedArray(JSContext *cx, int atype, uint32_t nelements); - -/* - * Create a new typed array of type atype (one of the TypedArray - * enumerant values above), and copy in values from the given JSObject, - * which must either be a typed array or an array-like object. - */ -JS_FRIEND_API(JSObject *) -js_CreateTypedArrayWithArray(JSContext *cx, int atype, JSObject *arrayArg); - -/* - * Create a new typed array of type atype (one of the TypedArray - * enumerant values above), using a given ArrayBuffer for storage. - * The byteoffset and length values are optional; if -1 is passed, an - * offset of 0 and enough elements to use up the remainder of the byte - * array are used as the default values. - */ -JS_FRIEND_API(JSObject *) -js_CreateTypedArrayWithBuffer(JSContext *cx, int atype, JSObject *bufArg, - int byteoffset, int length); - -extern int32_t JS_FASTCALL -js_TypedArray_uint8_clamp_double(const double x); - -JS_FRIEND_API(JSBool) -JS_IsArrayBufferObject(JSObject *obj); - -JS_FRIEND_API(JSObject *) -JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes); - -JS_FRIEND_API(uint32_t) -JS_GetArrayBufferByteLength(JSObject *obj); - -JS_FRIEND_API(uint8_t *) -JS_GetArrayBufferData(JSObject *obj); - -JS_FRIEND_API(uint32_t) -JS_GetTypedArrayLength(JSObject *obj); - -JS_FRIEND_API(uint32_t) -JS_GetTypedArrayByteOffset(JSObject *obj); - -JS_FRIEND_API(uint32_t) -JS_GetTypedArrayByteLength(JSObject *obj); - -JS_FRIEND_API(uint32_t) -JS_GetTypedArrayType(JSObject *obj); - -JS_FRIEND_API(JSObject *) -JS_GetTypedArrayBuffer(JSObject *obj); - -JS_FRIEND_API(void *) -JS_GetTypedArrayData(JSObject *obj); - -#endif /* jstypedarray_h */ diff --git a/scripting/javascript/spidermonkey-android/include/jstypes.h b/scripting/javascript/spidermonkey-android/include/jstypes.h index b2886110ca..8f0489f6f0 100644 --- a/scripting/javascript/spidermonkey-android/include/jstypes.h +++ b/scripting/javascript/spidermonkey-android/include/jstypes.h @@ -1,41 +1,7 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * IBM Corp. - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* ** File: jstypes.h diff --git a/scripting/javascript/spidermonkey-android/include/jsutil.h b/scripting/javascript/spidermonkey-android/include/jsutil.h index 975b0241c4..10debde90b 100644 --- a/scripting/javascript/spidermonkey-android/include/jsutil.h +++ b/scripting/javascript/spidermonkey-android/include/jsutil.h @@ -1,41 +1,8 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * PR assertion checker. @@ -410,14 +377,8 @@ inline __attribute__ ((unused)) void MUST_FLOW_THROUGH(const char *label) {} #endif #ifdef JS_CRASH_DIAGNOSTICS # define JS_POISON(p, val, size) memset((p), (val), (size)) -# define JS_OPT_ASSERT(expr) \ - ((expr) ? (void)0 : MOZ_Assert(#expr, __FILE__, __LINE__)) -# define JS_OPT_ASSERT_IF(cond, expr) \ - ((!(cond) || (expr)) ? (void)0 : MOZ_Assert(#expr, __FILE__, __LINE__)) #else # define JS_POISON(p, val, size) ((void) 0) -# define JS_OPT_ASSERT(expr) ((void) 0) -# define JS_OPT_ASSERT_IF(cond, expr) ((void) 0) #endif /* Basic stats */ diff --git a/scripting/javascript/spidermonkey-android/include/jsval.h b/scripting/javascript/spidermonkey-android/include/jsval.h index 5324d09b23..2ee90a8e4f 100644 --- a/scripting/javascript/spidermonkey-android/include/jsval.h +++ b/scripting/javascript/spidermonkey-android/include/jsval.h @@ -1,41 +1,9 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=4 sw=4 et tw=99 ft=cpp: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released - * June 30, 2010 - * - * The Initial Developer of the Original Code is - * the Mozilla Corporation. - * - * Contributor(s): - * Luke Wagner - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jsvalimpl_h__ #define jsvalimpl_h__ @@ -44,8 +12,6 @@ * Implementation details for js::Value in jsapi.h. */ -#include "mozilla/FloatingPoint.h" - #include "js/Utility.h" JS_BEGIN_EXTERN_C @@ -247,10 +213,11 @@ typedef enum JSWhyMagic JS_ARG_POISON, /* used in debug builds to catch tracing errors */ JS_SERIALIZE_NO_NODE, /* an empty subnode in the AST serializer */ JS_LAZY_ARGUMENTS, /* lazy arguments value on the stack */ - JS_UNASSIGNED_ARGUMENTS, /* the initial value of callobj.arguments */ JS_OPTIMIZED_ARGUMENTS, /* optimized-away 'arguments' value */ JS_IS_CONSTRUCTING, /* magic value passed to natives to indicate construction */ JS_OVERWRITTEN_CALLEE, /* arguments.callee has been overwritten */ + JS_FORWARD_TO_CALL_OBJECT, /* args object element stored in call object */ + JS_BLOCK_NEEDS_CLONE, /* value of static block object slot */ JS_GENERIC_MAGIC /* for local use */ } JSWhyMagic; @@ -269,6 +236,7 @@ typedef union jsval_layout void *ptr; JSWhyMagic why; size_t word; + uintptr_t uintptr; } payload; JSValueTag tag; } s; @@ -296,6 +264,7 @@ typedef union jsval_layout double asDouble; void *asPtr; size_t asWord; + uintptr_t asUIntPtr; } JSVAL_ALIGNMENT jsval_layout; # endif /* JS_BITS_PER_WORD */ #else /* defined(IS_LITTLE_ENDIAN) */ @@ -314,6 +283,7 @@ typedef union jsval_layout void *ptr; JSWhyMagic why; size_t word; + uintptr_t uintptr; } payload; } s; double asDouble; @@ -338,6 +308,7 @@ typedef union jsval_layout double asDouble; void *asPtr; size_t asWord; + uintptr_t asUIntPtr; } JSVAL_ALIGNMENT jsval_layout; # endif /* JS_BITS_PER_WORD */ #endif /* defined(IS_LITTLE_ENDIAN) */ diff --git a/scripting/javascript/spidermonkey-android/include/jsversion.h b/scripting/javascript/spidermonkey-android/include/jsversion.h index 1ecdd0f20b..70e31a3fe5 100644 --- a/scripting/javascript/spidermonkey-android/include/jsversion.h +++ b/scripting/javascript/spidermonkey-android/include/jsversion.h @@ -1,41 +1,8 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * JS configuration macros. @@ -91,7 +58,6 @@ #define JS_HAS_CONST 0 /* has JS2 const as alternative var */ #define JS_HAS_FUN_EXPR_STMT 0 /* has function expression statement */ #define JS_HAS_NO_SUCH_METHOD 0 /* has o.__noSuchMethod__ handler */ -#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */ #define JS_HAS_GENERATORS 0 /* has yield in generator function */ #define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */ #define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */ @@ -113,7 +79,6 @@ #define JS_HAS_CONST 1 /* has JS2 const as alternative var */ #define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */ #define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */ -#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */ #define JS_HAS_GENERATORS 0 /* has yield in generator function */ #define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */ #define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */ @@ -131,7 +96,6 @@ #define JS_HAS_CONST 1 /* has JS2 const as alternative var */ #define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */ #define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */ -#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */ #define JS_HAS_GENERATORS 0 /* has yield in generator function */ #define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */ #define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */ @@ -149,7 +113,6 @@ #define JS_HAS_CONST 1 /* has JS2 const as alternative var */ #define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */ #define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */ -#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */ #define JS_HAS_GENERATORS 1 /* has yield in generator function */ #define JS_HAS_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */ #define JS_HAS_DESTRUCTURING 1 /* has [a,b] = ... or {p:a,q:b} = ... */ @@ -167,7 +130,6 @@ #define JS_HAS_CONST 1 /* has JS2 const as alternative var */ #define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */ #define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */ -#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */ #define JS_HAS_GENERATORS 1 /* has yield in generator function */ #define JS_HAS_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */ #define JS_HAS_DESTRUCTURING 2 /* has [a,b] = ... or {p:a,q:b} = ... */ diff --git a/scripting/javascript/spidermonkey-android/include/jswrapper.h b/scripting/javascript/spidermonkey-android/include/jswrapper.h index ba6ef63ca5..aa0e80ad16 100644 --- a/scripting/javascript/spidermonkey-android/include/jswrapper.h +++ b/scripting/javascript/spidermonkey-android/include/jswrapper.h @@ -1,43 +1,9 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=4 sw=4 et tw=99: * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released - * May 28, 2008. - * - * The Initial Developer of the Original Code is - * Mozilla Foundation - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Andreas Gal - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jswrapper_h___ #define jswrapper_h___ @@ -51,30 +17,76 @@ namespace js { class DummyFrameGuard; -/* Base class that just implements no-op forwarding methods for fundamental - * traps. This is meant to be used as a base class for ProxyHandlers that - * want transparent forwarding behavior but don't want to use the derived - * traps and other baggage of js::Wrapper. +/* + * A wrapper is essentially a proxy that restricts access to certain traps. The + * way in which a wrapper restricts access to its traps depends on the + * particular policy for that wrapper. To allow a wrapper's policy to be + * customized, the Wrapper base class contains two functions, enter/leave, which + * are called as a policy enforcement check before/after each trap is forwarded. + * + * To minimize code duplication, a set of abstract wrapper classes is + * provided, from which other wrappers may inherit. These abstract classes are + * organized in the following hierarchy: + * + * BaseProxyHandler Wrapper + * | | | + * IndirectProxyHandler | | + * | | | | + * | IndirectWrapper | + * | | + * DirectProxyHandler | + * | | + * DirectWrapper */ -class JS_FRIEND_API(AbstractWrapper) : public ProxyHandler +class JS_FRIEND_API(Wrapper) { unsigned mFlags; + public: - unsigned flags() const { return mFlags; } + enum Action { + GET, + SET, + CALL, + PUNCTURE + }; - explicit AbstractWrapper(unsigned flags); + enum Flags { + CROSS_COMPARTMENT = 1 << 0, + LAST_USED_FLAG = CROSS_COMPARTMENT + }; - /* ES5 Harmony fundamental wrapper traps. */ - virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set, - PropertyDescriptor *desc) MOZ_OVERRIDE; - virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set, - PropertyDescriptor *desc) MOZ_OVERRIDE; - virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id, - PropertyDescriptor *desc) MOZ_OVERRIDE; - virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE; - virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE; - virtual bool enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE; - virtual bool fix(JSContext *cx, JSObject *wrapper, Value *vp) MOZ_OVERRIDE; + typedef enum { + PermitObjectAccess, + PermitPropertyAccess, + DenyAccess + } Permission; + + static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto, + JSObject *parent, Wrapper *handler); + + static Wrapper *wrapperHandler(const JSObject *wrapper); + + static JSObject *wrappedObject(const JSObject *wrapper); + + explicit Wrapper(unsigned flags); + + unsigned flags() const { + return mFlags; + } + + /* + * The function Wrapper::New takes a pointer to a Wrapper as the handler + * object. It then passes it on to the function NewProxyObject, which + * expects a pointer to a BaseProxyHandler as the handler object. We don't + * want to change Wrapper::New to take a pointer to a BaseProxyHandler, + * because that would allow the creation of wrappers with non-wrapper + * handlers. Unfortunately, we can't inherit Wrapper from BaseProxyHandler, + * since that would create a dreaded diamond, and we can't use dynamic_cast + * to cast Wrapper to BaseProxyHandler, since that would require us to + * compile with run time type information. Hence the need for this virtual + * function. + */ + virtual BaseProxyHandler *toBaseProxyHandler() = 0; /* Policy enforcement traps. * @@ -82,12 +94,9 @@ class JS_FRIEND_API(AbstractWrapper) : public ProxyHandler * on the underlying object's |id| property. In the case when |act| is CALL, * |id| is generally JSID_VOID. * - * leave() allows the policy to undo various scoped state changes taken in - * enter(). If enter() succeeds, leave() must be called upon completion of - * the approved action. - * * The |act| parameter to enter() specifies the action being performed. GET, - * SET, and CALL are self-explanatory, but PUNCTURE requires more explanation: + * SET, and CALL are self-explanatory, but PUNCTURE requires more + * explanation: * * GET and SET allow for a very fine-grained security membrane, through * which access can be granted or denied on a per-property, per-object, and @@ -103,24 +112,87 @@ class JS_FRIEND_API(AbstractWrapper) : public ProxyHandler * permission, and thus should generally be denied for security wrappers * except under very special circumstances. When |act| is PUNCTURE, |id| * should be JSID_VOID. - * */ - enum Action { GET, SET, CALL, PUNCTURE }; - virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act, bool *bp); - virtual void leave(JSContext *cx, JSObject *wrapper); - - static JSObject *wrappedObject(const JSObject *wrapper); - static AbstractWrapper *wrapperHandler(const JSObject *wrapper); + */ + virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act, + bool *bp); }; -/* No-op wrapper handler base class. */ -class JS_FRIEND_API(Wrapper) : public AbstractWrapper +/* + * IndirectWrapper forwards its traps by forwarding them to + * IndirectProxyHandler. In effect, IndirectWrapper behaves the same as + * IndirectProxyHandler, except that it adds policy enforcement checks to each + * fundamental trap. + */ +class JS_FRIEND_API(IndirectWrapper) : public Wrapper, + public IndirectProxyHandler { public: - explicit Wrapper(unsigned flags); + explicit IndirectWrapper(unsigned flags); - typedef enum { PermitObjectAccess, PermitPropertyAccess, DenyAccess } Permission; + virtual BaseProxyHandler* toBaseProxyHandler() { + return this; + } - virtual ~Wrapper(); + virtual Wrapper *toWrapper() { + return this; + } + + /* ES5 Harmony fundamental wrapper traps. */ + virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, + jsid id, bool set, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, + jsid id, bool set, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, + AutoIdVector &props) MOZ_OVERRIDE; + virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, + bool *bp) MOZ_OVERRIDE; + virtual bool enumerate(JSContext *cx, JSObject *wrapper, + AutoIdVector &props) MOZ_OVERRIDE; + + /* Spidermonkey extensions. */ + virtual bool defaultValue(JSContext *cx, JSObject *wrapper_, JSType hint, + Value *vp) MOZ_OVERRIDE; +}; + +/* + * DirectWrapper forwards its traps by forwarding them to DirectProxyHandler. + * In effect, DirectWrapper behaves the same as DirectProxyHandler, except that + * it adds policy enforcement checks to each trap. + */ +class JS_FRIEND_API(DirectWrapper) : public Wrapper, public DirectProxyHandler +{ + public: + explicit DirectWrapper(unsigned flags); + + virtual ~DirectWrapper(); + + virtual BaseProxyHandler* toBaseProxyHandler() { + return this; + } + + virtual Wrapper *toWrapper() { + return this; + } + + /* ES5 Harmony fundamental wrapper traps. */ + virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, + jsid id, bool set, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, + jsid id, bool set, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, + AutoIdVector &props) MOZ_OVERRIDE; + virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, + bool *bp) MOZ_OVERRIDE; + virtual bool enumerate(JSContext *cx, JSObject *wrapper, + AutoIdVector &props) MOZ_OVERRIDE; /* ES5 Harmony derived wrapper traps. */ virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE; @@ -136,36 +208,18 @@ class JS_FRIEND_API(Wrapper) : public AbstractWrapper virtual bool construct(JSContext *cx, JSObject *wrapper, unsigned argc, Value *argv, Value *rval) MOZ_OVERRIDE; virtual bool nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args) MOZ_OVERRIDE; virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) MOZ_OVERRIDE; - virtual JSType typeOf(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE; - virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE; virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE; virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) MOZ_OVERRIDE; - virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE; - virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE; - virtual bool iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp) MOZ_OVERRIDE; + virtual bool defaultValue(JSContext *cx, JSObject *wrapper_, JSType hint, + Value *vp) MOZ_OVERRIDE; - virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE; - - using AbstractWrapper::Action; - - static Wrapper singleton; - - static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent, - Wrapper *handler); - - using AbstractWrapper::wrappedObject; - using AbstractWrapper::wrapperHandler; - - enum { - CROSS_COMPARTMENT = 1 << 0, - LAST_USED_FLAG = CROSS_COMPARTMENT - }; + static DirectWrapper singleton; static void *getWrapperFamily(); }; /* Base class for all cross compartment wrapper handlers. */ -class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper +class JS_FRIEND_API(CrossCompartmentWrapper) : public DirectWrapper { public: CrossCompartmentWrapper(unsigned flags); @@ -199,11 +253,10 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) MOZ_OVERRIDE; virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE; virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) MOZ_OVERRIDE; + virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE; virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE; virtual bool iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp); - virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE; - static CrossCompartmentWrapper singleton; }; @@ -227,7 +280,7 @@ class JS_FRIEND_API(SecurityWrapper) : public Base virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE; }; -typedef SecurityWrapper SameCompartmentSecurityWrapper; +typedef SecurityWrapper SameCompartmentSecurityWrapper; typedef SecurityWrapper CrossCompartmentSecurityWrapper; /* @@ -248,6 +301,43 @@ class JS_FRIEND_API(ForceFrame) bool enter(); }; + +class JS_FRIEND_API(DeadObjectProxy) : public BaseProxyHandler +{ + public: + static int sDeadObjectFamily; + + explicit DeadObjectProxy(); + + /* ES5 Harmony fundamental wrapper traps. */ + virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE; + virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE; + virtual bool enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE; + + /* Spidermonkey extensions. */ + virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp); + virtual bool construct(JSContext *cx, JSObject *proxy, unsigned argc, Value *argv, Value *rval); + virtual bool nativeCall(JSContext *cx, JSObject *proxy, Class *clasp, Native native, CallArgs args); + virtual bool hasInstance(JSContext *cx, JSObject *proxy, const Value *vp, bool *bp); + virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx); + virtual JSString *obj_toString(JSContext *cx, JSObject *proxy); + virtual JSString *fun_toString(JSContext *cx, JSObject *proxy, unsigned indent); + virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g); + virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp); + virtual bool iteratorNext(JSContext *cx, JSObject *proxy, Value *vp); + virtual bool getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver, + uint32_t index, Value *vp, bool *present); + + + static DeadObjectProxy singleton; +}; + extern JSObject * TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSObject *parent, unsigned flags); @@ -266,20 +356,69 @@ IsWrapper(const JSObject *obj) // stopAtOuter is true, then this returns the outer window if it was // previously wrapped. Otherwise, this returns the first object for // which JSObject::isWrapper returns false. -JS_FRIEND_API(JSObject *) UnwrapObject(JSObject *obj, bool stopAtOuter = true, - unsigned *flagsp = NULL); +JS_FRIEND_API(JSObject *) +UnwrapObject(JSObject *obj, bool stopAtOuter = true, unsigned *flagsp = NULL); // Given a JSObject, returns that object stripped of wrappers. At each stage, // the security wrapper has the opportunity to veto the unwrap. Since checked // code should never be unwrapping outer window wrappers, we always stop at // outer windows. -JS_FRIEND_API(JSObject *) UnwrapObjectChecked(JSContext *cx, JSObject *obj); +JS_FRIEND_API(JSObject *) +UnwrapObjectChecked(JSContext *cx, JSObject *obj); -bool IsCrossCompartmentWrapper(const JSObject *obj); +JS_FRIEND_API(bool) +IsCrossCompartmentWrapper(const JSObject *obj); + +JSObject * +NewDeadProxyObject(JSContext *cx, JSObject *parent); void NukeCrossCompartmentWrapper(JSObject *wrapper); +bool +RemapWrapper(JSContext *cx, JSObject *wobj, JSObject *newTarget); + +JS_FRIEND_API(bool) +RemapAllWrappersForObject(JSContext *cx, JSObject *oldTarget, + JSObject *newTarget); + +// API to recompute all cross-compartment wrappers whose source and target +// match the given filters. +// +// These filters are designed to be ephemeral stack classes, and thus don't +// do any rooting or holding of their members. +struct CompartmentFilter { + virtual bool match(JSCompartment *c) const = 0; +}; + +struct AllCompartments : public CompartmentFilter { + virtual bool match(JSCompartment *c) const { return true; } +}; + +struct ContentCompartmentsOnly : public CompartmentFilter { + virtual bool match(JSCompartment *c) const { + return !IsSystemCompartment(c); + } +}; + +struct SingleCompartment : public CompartmentFilter { + JSCompartment *ours; + SingleCompartment(JSCompartment *c) : ours(c) {} + virtual bool match(JSCompartment *c) const { return c == ours; } +}; + +struct CompartmentsWithPrincipals : public CompartmentFilter { + JSPrincipals *principals; + CompartmentsWithPrincipals(JSPrincipals *p) : principals(p) {} + virtual bool match(JSCompartment *c) const { + return JS_GetCompartmentPrincipals(c) == principals; + } +}; + +JS_FRIEND_API(bool) +RecomputeWrappers(JSContext *cx, const CompartmentFilter &sourceFilter, + const CompartmentFilter &targetFilter); + } /* namespace js */ #endif diff --git a/scripting/javascript/spidermonkey-android/include/jsxdrapi.h b/scripting/javascript/spidermonkey-android/include/jsxdrapi.h deleted file mode 100644 index 678d58ecd3..0000000000 --- a/scripting/javascript/spidermonkey-android/include/jsxdrapi.h +++ /dev/null @@ -1,215 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=78: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef jsxdrapi_h___ -#define jsxdrapi_h___ - -/* - * JS external data representation interface API. - * - * The XDR system is comprised of three major parts: - * - * - the state serialization/deserialization APIs, which allow consumers - * of the API to serialize JS runtime state (script bytecodes, atom maps, - * object graphs, etc.) for later restoration. These portions - * are implemented in various appropriate files, such as jsscript.c - * for the script portions and jsobj.c for object state. - * - the callback APIs through which the runtime requests an opaque - * representation of a native object, and through which the runtime - * constructs a live native object from an opaque representation. These - * portions are the responsibility of the native object implementor. - * - utility functions for en/decoding of primitive types, such as - * JSStrings. This portion is implemented in jsxdrapi.c. - * - * Spiritually guided by Sun's XDR, where appropriate. - */ - -#include "jspubtd.h" -#include "jsprvtd.h" - -JS_BEGIN_EXTERN_C - -/* We use little-endian byteorder for all encoded data */ - -#if defined IS_LITTLE_ENDIAN -#define JSXDR_SWAB32(x) x -#define JSXDR_SWAB16(x) x -#elif defined IS_BIG_ENDIAN -#define JSXDR_SWAB32(x) (((uint32_t)(x) >> 24) | \ - (((uint32_t)(x) >> 8) & 0xff00) | \ - (((uint32_t)(x) << 8) & 0xff0000) | \ - ((uint32_t)(x) << 24)) -#define JSXDR_SWAB16(x) (((uint16_t)(x) >> 8) | ((uint16_t)(x) << 8)) -#else -#error "unknown byte order" -#endif - -#define JSXDR_ALIGN 4 - -typedef enum JSXDRMode { - JSXDR_ENCODE, - JSXDR_DECODE -} JSXDRMode; - -typedef enum JSXDRWhence { - JSXDR_SEEK_SET, - JSXDR_SEEK_CUR, - JSXDR_SEEK_END -} JSXDRWhence; - -typedef struct JSXDROps { - JSBool (*get32)(JSXDRState *, uint32_t *); - JSBool (*set32)(JSXDRState *, uint32_t *); - JSBool (*getbytes)(JSXDRState *, char *, uint32_t); - JSBool (*setbytes)(JSXDRState *, char *, uint32_t); - void * (*raw)(JSXDRState *, uint32_t); - JSBool (*seek)(JSXDRState *, int32_t, JSXDRWhence); - uint32_t (*tell)(JSXDRState *); - void (*finalize)(JSXDRState *); -} JSXDROps; - -struct JSXDRState { - JSXDRMode mode; - JSXDROps *ops; - JSContext *cx; - void *userdata; - const char *sharedFilename; - JSPrincipals *principals; - JSPrincipals *originPrincipals; -}; - -extern JS_PUBLIC_API(void) -JS_XDRInitBase(JSXDRState *xdr, JSXDRMode mode, JSContext *cx); - -extern JS_PUBLIC_API(JSXDRState *) -JS_XDRNewMem(JSContext *cx, JSXDRMode mode); - -extern JS_PUBLIC_API(void *) -JS_XDRMemGetData(JSXDRState *xdr, uint32_t *lp); - -extern JS_PUBLIC_API(void) -JS_XDRMemSetData(JSXDRState *xdr, void *data, uint32_t len); - -extern JS_PUBLIC_API(uint32_t) -JS_XDRMemDataLeft(JSXDRState *xdr); - -extern JS_PUBLIC_API(void) -JS_XDRMemResetData(JSXDRState *xdr); - -extern JS_PUBLIC_API(void) -JS_XDRDestroy(JSXDRState *xdr); - -extern JS_PUBLIC_API(JSBool) -JS_XDRUint8(JSXDRState *xdr, uint8_t *b); - -extern JS_PUBLIC_API(JSBool) -JS_XDRUint16(JSXDRState *xdr, uint16_t *s); - -extern JS_PUBLIC_API(JSBool) -JS_XDRUint32(JSXDRState *xdr, uint32_t *lp); - -extern JS_PUBLIC_API(JSBool) -JS_XDRBytes(JSXDRState *xdr, char *bytes, uint32_t len); - -extern JS_PUBLIC_API(JSBool) -JS_XDRCString(JSXDRState *xdr, char **sp); - -extern JS_PUBLIC_API(JSBool) -JS_XDRString(JSXDRState *xdr, JSString **strp); - -extern JS_PUBLIC_API(JSBool) -JS_XDRStringOrNull(JSXDRState *xdr, JSString **strp); - -extern JS_PUBLIC_API(JSBool) -JS_XDRDouble(JSXDRState *xdr, double *dp); - -extern JS_PUBLIC_API(JSBool) -JS_XDRFunctionObject(JSXDRState *xdr, JSObject **objp); - -extern JS_PUBLIC_API(JSBool) -JS_XDRScript(JSXDRState *xdr, JSScript **scriptp); - -/* - * Magic numbers. - */ -#define JSXDR_MAGIC_SCRIPT_1 0xdead0001 -#define JSXDR_MAGIC_SCRIPT_2 0xdead0002 -#define JSXDR_MAGIC_SCRIPT_3 0xdead0003 -#define JSXDR_MAGIC_SCRIPT_4 0xdead0004 -#define JSXDR_MAGIC_SCRIPT_5 0xdead0005 -#define JSXDR_MAGIC_SCRIPT_6 0xdead0006 -#define JSXDR_MAGIC_SCRIPT_7 0xdead0007 -#define JSXDR_MAGIC_SCRIPT_8 0xdead0008 -#define JSXDR_MAGIC_SCRIPT_9 0xdead0009 -#define JSXDR_MAGIC_SCRIPT_10 0xdead000a -#define JSXDR_MAGIC_SCRIPT_11 0xdead000b -#define JSXDR_MAGIC_SCRIPT_12 0xdead000c -#define JSXDR_MAGIC_SCRIPT_CURRENT JSXDR_MAGIC_SCRIPT_12 - -/* - * Bytecode version number. Increment the subtrahend whenever JS bytecode - * changes incompatibly. - * - * This version number is XDR'd near the front of xdr bytecode and - * aborts deserialization if there is a mismatch between the current - * and saved versions. If deserialization fails, the data should be - * invalidated if possible. - */ -#define JSXDR_BYTECODE_VERSION (0xb973c0de - 109) - -JS_END_EXTERN_C - -/* - * Library-private functions. - */ -extern JSBool -js_XDRAtom(JSXDRState *xdr, JSAtom **atomp); - -/* - * Set principals that should be assigned to decoded scripts and functions. - * The principals is not held via JS_HoldPrincipals/JS_DropPrincipals unless - * they are stored in a decoded script. Thus the caller must either ensure - * that principal outlive the XDR instance or are explicitly set to NULL - * before they release by the caller. - */ -extern void -js_XDRSetPrincipals(JSXDRState *xdr, JSPrincipals *principals, JSPrincipals *originPrincipals); - -#endif /* ! jsxdrapi_h___ */ diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/Assertions.h b/scripting/javascript/spidermonkey-android/include/mozilla/Assertions.h index 1f0c2a7b5a..407fb24e98 100644 --- a/scripting/javascript/spidermonkey-android/include/mozilla/Assertions.h +++ b/scripting/javascript/spidermonkey-android/include/mozilla/Assertions.h @@ -1,42 +1,7 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=8 sw=4 et tw=99 ft=cpp: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Code. - * - * The Initial Developer of the Original Code is - * The Mozilla Foundation - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Jeff Walden - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Implementations of runtime and static assertion macros for C and C++. */ @@ -44,11 +9,27 @@ #define mozilla_Assertions_h_ #include "mozilla/Attributes.h" -#include "mozilla/Types.h" +#include #include #include -#ifndef WIN32 +#ifdef WIN32 + /* + * TerminateProcess and GetCurrentProcess are defined in , which + * further depends on . We hardcode these few definitions manually + * because those headers clutter the global namespace with a significant + * number of undesired macros and symbols. + */ +# ifdef __cplusplus + extern "C" { +# endif + __declspec(dllimport) int __stdcall + TerminateProcess(void* hProcess, unsigned int uExitCode); + __declspec(dllimport) void* __stdcall GetCurrentProcess(void); +# ifdef __cplusplus + } +# endif +#else # include #endif #ifdef ANDROID @@ -140,58 +121,73 @@ extern "C" { #endif -#if defined(WIN32) +/* + * MOZ_CRASH crashes the program, plain and simple, in a Breakpad-compatible + * way, in both debug and release builds. + * + * MOZ_CRASH is a good solution for "handling" failure cases when you're + * unwilling or unable to handle them more cleanly -- for OOM, for likely memory + * corruption, and so on. It's also a good solution if you need safe behavior + * in release builds as well as debug builds. But if the failure is one that + * should be debugged and fixed, MOZ_ASSERT is generally preferable. + */ +#if defined(_MSC_VER) /* - * We used to call DebugBreak() on Windows, but amazingly, it causes - * the MSVS 2010 debugger not to be able to recover a call stack. - */ -# define MOZ_CRASH() \ - do { \ - *((volatile int *) NULL) = 123; \ - exit(3); \ - } while (0) -#elif defined(ANDROID) - /* - * On Android, raise(SIGABRT) is handled asynchronously. Seg fault now - * so we crash immediately and capture the current call stack. We need - * to specifically use the global namespace in the C++ case. + * On MSVC use the __debugbreak compiler intrinsic, which produces an inline + * (not nested in a system function) breakpoint. This distinctively invokes + * Breakpad without requiring system library symbols on all stack-processing + * machines, as a nested breakpoint would require. We use TerminateProcess + * with the exit code aborting would generate because we don't want to invoke + * atexit handlers, destructors, library unload handlers, and so on when our + * process might be in a compromised state. We don't use abort() because + * it'd cause Windows to annoyingly pop up the process error dialog multiple + * times. See bug 345118 and bug 426163. + * + * (Technically these are Windows requirements, not MSVC requirements. But + * practically you need MSVC for debugging, and we only ship builds created + * by MSVC, so doing it this way reduces complexity.) */ # ifdef __cplusplus # define MOZ_CRASH() \ do { \ - *((volatile int *) NULL) = 123; \ + __debugbreak(); \ + *((volatile int*) NULL) = 123; \ + ::TerminateProcess(::GetCurrentProcess(), 3); \ + } while (0) +# else +# define MOZ_CRASH() \ + do { \ + __debugbreak(); \ + *((volatile int*) NULL) = 123; \ + TerminateProcess(GetCurrentProcess(), 3); \ + } while (0) +# endif +#else +# ifdef __cplusplus +# define MOZ_CRASH() \ + do { \ + *((volatile int*) NULL) = 123; \ ::abort(); \ } while (0) # else # define MOZ_CRASH() \ do { \ - *((volatile int *) NULL) = 123; \ + *((volatile int*) NULL) = 123; \ abort(); \ } while (0) # endif -#elif defined(__APPLE__) - /* - * On Mac OS X, Breakpad ignores signals. Only real Mach exceptions are - * trapped. - */ -# define MOZ_CRASH() \ - do { \ - *((volatile int *) NULL) = 123; \ - raise(SIGABRT); /* In case above statement gets nixed by the optimizer. */ \ - } while (0) -#else -# define MOZ_CRASH() \ - do { \ - raise(SIGABRT); /* To continue from here in GDB: "signal 0". */ \ - } while (0) #endif - -extern MFBT_API(void) -MOZ_Assert(const char* s, const char* file, int ln); - +/* + * Prints |s| as an assertion failure (using file and ln as the location of the + * assertion) to the standard debug-output channel. + * + * Usually you should use MOZ_ASSERT instead of this method. This method is + * primarily for internal use in this header, and only secondarily for use in + * implementing release-build assertions. + */ static MOZ_ALWAYS_INLINE void -MOZ_OutputAssertMessage(const char* s, const char *file, int ln) +MOZ_ReportAssertionFailure(const char* s, const char* file, int ln) { #ifdef ANDROID __android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert", @@ -243,7 +239,7 @@ MOZ_OutputAssertMessage(const char* s, const char *file, int ln) # define MOZ_ASSERT_HELPER1(expr) \ do { \ if (!(expr)) { \ - MOZ_OutputAssertMessage(#expr, __FILE__, __LINE__); \ + MOZ_ReportAssertionFailure(#expr, __FILE__, __LINE__); \ MOZ_CRASH(); \ } \ } while (0) @@ -251,7 +247,7 @@ MOZ_OutputAssertMessage(const char* s, const char *file, int ln) # define MOZ_ASSERT_HELPER2(expr, explain) \ do { \ if (!(expr)) { \ - MOZ_OutputAssertMessage(#expr " (" explain ")", __FILE__, __LINE__); \ + MOZ_ReportAssertionFailure(#expr " (" explain ")", __FILE__, __LINE__); \ MOZ_CRASH(); \ } \ } while (0) @@ -302,19 +298,38 @@ MOZ_OutputAssertMessage(const char* s, const char *file, int ln) # define MOZ_ASSERT_IF(cond, expr) do { } while (0) #endif -/* MOZ_NOT_REACHED_MARKER() expands (in compilers which support it) to an - * expression which states that it is undefined behavior for the compiler to - * reach this point. Most code should probably use the higher level - * MOZ_NOT_REACHED (which expands to this when appropriate). +/* + * MOZ_NOT_REACHED_MARKER() expands to an expression which states that it is + * undefined behavior for execution to reach this point. No guarantees are made + * about what will happen if this is reached at runtime. Most code should + * probably use the higher level MOZ_NOT_REACHED, which uses this when + * appropriate. */ #if defined(__clang__) # define MOZ_NOT_REACHED_MARKER() __builtin_unreachable() #elif defined(__GNUC__) + /* + * __builtin_unreachable() was implemented in gcc 4.5. If we don't have + * that, call a noreturn function; abort() will do nicely. Qualify the call + * in C++ in case there's another abort() visible in local scope. + */ # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) # define MOZ_NOT_REACHED_MARKER() __builtin_unreachable() +# else +# ifdef __cplusplus +# define MOZ_NOT_REACHED_MARKER() ::abort() +# else +# define MOZ_NOT_REACHED_MARKER() abort() +# endif # endif #elif defined(_MSC_VER) -# define MOZ_NOT_REACHED_MARKER() __assume(0) +# define MOZ_NOT_REACHED_MARKER() __assume(0) +#else +# ifdef __cplusplus +# define MOZ_NOT_REACHED_MARKER() ::abort() +# else +# define MOZ_NOT_REACHED_MARKER() abort() +# endif #endif /* @@ -334,39 +349,14 @@ MOZ_OutputAssertMessage(const char* s, const char *file, int ln) * MOZ_NOT_REACHED("boolean literal that's not true or false?"); * } */ -#if defined(MOZ_NOT_REACHED_MARKER) -# if defined(DEBUG) -# define MOZ_NOT_REACHED(reason) do { \ - MOZ_Assert(reason, __FILE__, __LINE__); \ - MOZ_NOT_REACHED_MARKER(); \ - } while (0) -# else -# define MOZ_NOT_REACHED(reason) MOZ_NOT_REACHED_MARKER() -# endif +#if defined(DEBUG) +# define MOZ_NOT_REACHED(reason) \ + do { \ + MOZ_ASSERT(false, reason); \ + MOZ_NOT_REACHED_MARKER(); \ + } while (0) #else -# if defined(__GNUC__) - /* - * On older versions of gcc we need to call a noreturn function to mark the - * code as unreachable. Since what we want is an unreachable version of - * MOZ_Assert, we use an asm label - * (http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/Asm-Labels.html) to create - * a new declaration to the same symbol. MOZ_ASSERT_NR should only be - * used via this macro, as it is a very specific hack to older versions of - * gcc. - */ -# define MOZ_GETASMPREFIX2(X) #X -# define MOZ_GETASMPREFIX(X) MOZ_GETASMPREFIX2(X) -# define MOZ_ASMPREFIX MOZ_GETASMPREFIX(__USER_LABEL_PREFIX__) - extern MOZ_NORETURN MFBT_API(void) - MOZ_ASSERT_NR(const char* s, const char* file, int ln) \ - asm (MOZ_ASMPREFIX "MOZ_Assert"); - -# define MOZ_NOT_REACHED(reason) MOZ_ASSERT_NR(reason, __FILE__, __LINE__) -# elif defined(DEBUG) -# define MOZ_NOT_REACHED(reason) MOZ_Assert(reason, __FILE__, __LINE__) -# else -# define MOZ_NOT_REACHED(reason) ((void)0) -# endif +# define MOZ_NOT_REACHED(reason) MOZ_NOT_REACHED_MARKER() #endif /* diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/Attributes.h b/scripting/javascript/spidermonkey-android/include/mozilla/Attributes.h index 4713b2c3f7..0cfcd60336 100644 --- a/scripting/javascript/spidermonkey-android/include/mozilla/Attributes.h +++ b/scripting/javascript/spidermonkey-android/include/mozilla/Attributes.h @@ -1,42 +1,7 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=99 ft=cpp: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Code. - * - * The Initial Developer of the Original Code is - * The Mozilla Foundation - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Jeff Walden (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Implementations of various class and method modifier attributes. */ @@ -180,6 +145,19 @@ # define MOZ_NORETURN /* no support */ #endif +/* + * MOZ_ASAN_BLACKLIST is a macro to tell AddressSanitizer (a compile-time + * instrumentation shipped with Clang) to not instrument the annotated function. + * Furthermore, it will prevent the compiler from inlining the function because + * inlining currently breaks the blacklisting mechanism of AddressSanitizer. + */ +#if defined(MOZ_ASAN) +# define MOZ_ASAN_BLACKLIST MOZ_NEVER_INLINE __attribute__((no_address_safety_analysis)) +# else +# define MOZ_ASAN_BLACKLIST +#endif + + #ifdef __cplusplus /* diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/BloomFilter.h b/scripting/javascript/spidermonkey-android/include/mozilla/BloomFilter.h index ec31b60a96..9effa1756c 100644 --- a/scripting/javascript/spidermonkey-android/include/mozilla/BloomFilter.h +++ b/scripting/javascript/spidermonkey-android/include/mozilla/BloomFilter.h @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -52,7 +52,8 @@ namespace mozilla { */ template -class BloomFilter { +class BloomFilter +{ /* * A counting Bloom filter with 8-bit counters. For now we assume * that having two hash functions is enough, but we may revisit that @@ -101,7 +102,7 @@ class BloomFilter { * positive rate for N == 100 and to quite bad false positive * rates for larger N. */ -public: + public: BloomFilter() { MOZ_STATIC_ASSERT(KeySize <= keyShift, "KeySize too big"); @@ -142,7 +143,7 @@ public: void remove(uint32_t hash); bool mightContain(uint32_t hash) const; -private: + private: static const size_t arraySize = (1 << KeySize); static const uint32_t keyMask = (1 << KeySize) - 1; static const uint32_t keyShift = 16; @@ -164,67 +165,67 @@ template inline void BloomFilter::clear() { - memset(counters, 0, arraySize); + memset(counters, 0, arraySize); } template inline void BloomFilter::add(uint32_t hash) { - uint8_t& slot1 = firstSlot(hash); - if (MOZ_LIKELY(!full(slot1))) - ++slot1; + uint8_t& slot1 = firstSlot(hash); + if (MOZ_LIKELY(!full(slot1))) + ++slot1; - uint8_t& slot2 = secondSlot(hash); - if (MOZ_LIKELY(!full(slot2))) - ++slot2; + uint8_t& slot2 = secondSlot(hash); + if (MOZ_LIKELY(!full(slot2))) + ++slot2; } template MOZ_ALWAYS_INLINE void BloomFilter::add(const T* t) { - uint32_t hash = t->hash(); - return add(hash); + uint32_t hash = t->hash(); + return add(hash); } template inline void BloomFilter::remove(uint32_t hash) { - // If the slots are full, we don't know whether we bumped them to be - // there when we added or not, so just leave them full. - uint8_t& slot1 = firstSlot(hash); - if (MOZ_LIKELY(!full(slot1))) - --slot1; + // If the slots are full, we don't know whether we bumped them to be + // there when we added or not, so just leave them full. + uint8_t& slot1 = firstSlot(hash); + if (MOZ_LIKELY(!full(slot1))) + --slot1; - uint8_t& slot2 = secondSlot(hash); - if (MOZ_LIKELY(!full(slot2))) - --slot2; + uint8_t& slot2 = secondSlot(hash); + if (MOZ_LIKELY(!full(slot2))) + --slot2; } template MOZ_ALWAYS_INLINE void BloomFilter::remove(const T* t) { - uint32_t hash = t->hash(); - remove(hash); + uint32_t hash = t->hash(); + remove(hash); } template MOZ_ALWAYS_INLINE bool BloomFilter::mightContain(uint32_t hash) const { - // Check that all the slots for this hash contain something - return firstSlot(hash) && secondSlot(hash); + // Check that all the slots for this hash contain something + return firstSlot(hash) && secondSlot(hash); } template MOZ_ALWAYS_INLINE bool BloomFilter::mightContain(const T* t) const { - uint32_t hash = t->hash(); - return mightContain(hash); + uint32_t hash = t->hash(); + return mightContain(hash); } } // namespace mozilla diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/CheckedInt.h b/scripting/javascript/spidermonkey-android/include/mozilla/CheckedInt.h new file mode 100644 index 0000000000..790fc6eabe --- /dev/null +++ b/scripting/javascript/spidermonkey-android/include/mozilla/CheckedInt.h @@ -0,0 +1,809 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Provides checked integers, detecting integer overflow and divide-by-0. */ + +#ifndef mozilla_CheckedInt_h_ +#define mozilla_CheckedInt_h_ + +/* + * Build options. Comment out these #defines to disable the corresponding + * optional feature. Disabling features may be useful for code using + * CheckedInt outside of Mozilla (e.g. WebKit) + */ + +// Enable usage of MOZ_STATIC_ASSERT to check for unsupported types. +// If disabled, static asserts are replaced by regular assert(). +#define MOZ_CHECKEDINT_ENABLE_MOZ_ASSERTS + +/* + * End of build options + */ + + +#ifdef MOZ_CHECKEDINT_ENABLE_MOZ_ASSERTS +# include "mozilla/Assertions.h" +#else +# ifndef MOZ_STATIC_ASSERT +# include +# define MOZ_STATIC_ASSERT(cond, reason) assert((cond) && reason) +# define MOZ_ASSERT(cond, reason) assert((cond) && reason) +# endif +#endif + +#include "mozilla/StandardInteger.h" + +#include +#include + +namespace mozilla { + +namespace detail { + +/* + * Step 1: manually record supported types + * + * What's nontrivial here is that there are different families of integer + * types: basic integer types and stdint types. It is merrily undefined which + * types from one family may be just typedefs for a type from another family. + * + * For example, on GCC 4.6, aside from the basic integer types, the only other + * type that isn't just a typedef for some of them, is int8_t. + */ + +struct UnsupportedType {}; + +template +struct IsSupportedPass2 +{ + static const bool value = false; +}; + +template +struct IsSupported +{ + static const bool value = IsSupportedPass2::value; +}; + +template<> +struct IsSupported +{ static const bool value = true; }; + +template<> +struct IsSupported +{ static const bool value = true; }; + +template<> +struct IsSupported +{ static const bool value = true; }; + +template<> +struct IsSupported +{ static const bool value = true; }; + +template<> +struct IsSupported +{ static const bool value = true; }; + +template<> +struct IsSupported +{ static const bool value = true; }; + +template<> +struct IsSupported +{ static const bool value = true; }; + +template<> +struct IsSupported +{ static const bool value = true; }; + + +template<> +struct IsSupportedPass2 +{ static const bool value = true; }; + +template<> +struct IsSupportedPass2 +{ static const bool value = true; }; + +template<> +struct IsSupportedPass2 +{ static const bool value = true; }; + +template<> +struct IsSupportedPass2 +{ static const bool value = true; }; + +template<> +struct IsSupportedPass2 +{ static const bool value = true; }; + +template<> +struct IsSupportedPass2 +{ static const bool value = true; }; + +template<> +struct IsSupportedPass2 +{ static const bool value = true; }; + +template<> +struct IsSupportedPass2 +{ static const bool value = true; }; + + +/* + * Step 2: some integer-traits kind of stuff. + */ + +template +struct StdintTypeForSizeAndSignedness +{}; + +template<> +struct StdintTypeForSizeAndSignedness<1, true> +{ typedef int8_t Type; }; + +template<> +struct StdintTypeForSizeAndSignedness<1, false> +{ typedef uint8_t Type; }; + +template<> +struct StdintTypeForSizeAndSignedness<2, true> +{ typedef int16_t Type; }; + +template<> +struct StdintTypeForSizeAndSignedness<2, false> +{ typedef uint16_t Type; }; + +template<> +struct StdintTypeForSizeAndSignedness<4, true> +{ typedef int32_t Type; }; + +template<> +struct StdintTypeForSizeAndSignedness<4, false> +{ typedef uint32_t Type; }; + +template<> +struct StdintTypeForSizeAndSignedness<8, true> +{ typedef int64_t Type; }; + +template<> +struct StdintTypeForSizeAndSignedness<8, false> +{ typedef uint64_t Type; }; + +template +struct UnsignedType +{ + typedef typename StdintTypeForSizeAndSignedness::Type Type; +}; + +template +struct IsSigned +{ + static const bool value = IntegerType(-1) <= IntegerType(0); +}; + +template +struct TwiceBiggerType +{ + typedef typename StdintTypeForSizeAndSignedness< + sizeof(IntegerType) * 2, + IsSigned::value + >::Type Type; +}; + +template +struct TwiceBiggerType +{ + typedef UnsupportedType Type; +}; + +template +struct PositionOfSignBit +{ + static const size_t value = CHAR_BIT * sizeof(IntegerType) - 1; +}; + +template +struct MinValue +{ + private: + typedef typename UnsignedType::Type UnsignedIntegerType; + static const size_t PosOfSignBit = PositionOfSignBit::value; + + public: + // Bitwise ops may return a larger type, that's why we cast explicitly. + // In C++, left bit shifts on signed values is undefined by the standard + // unless the shifted value is representable. + // Notice that signed-to-unsigned conversions are always well-defined in + // the standard as the value congruent to 2**n, as expected. By contrast, + // unsigned-to-signed is only well-defined if the value is representable. + static const IntegerType value = + IsSigned::value + ? IntegerType(UnsignedIntegerType(1) << PosOfSignBit) + : IntegerType(0); +}; + +template +struct MaxValue +{ + // Tricksy, but covered by the unit test. + // Relies heavily on the type of MinValue::value + // being IntegerType. + static const IntegerType value = ~MinValue::value; +}; + +/* + * Step 3: Implement the actual validity checks. + * + * Ideas taken from IntegerLib, code different. + */ + +template +inline bool +HasSignBit(T x) +{ + // In C++, right bit shifts on negative values is undefined by the standard. + // Notice that signed-to-unsigned conversions are always well-defined in the + // standard, as the value congruent modulo 2**n as expected. By contrast, + // unsigned-to-signed is only well-defined if the value is representable. + return bool(typename UnsignedType::Type(x) + >> PositionOfSignBit::value); +} + +// Bitwise ops may return a larger type, so it's good to use this inline +// helper guaranteeing that the result is really of type T. +template +inline T +BinaryComplement(T x) +{ + return ~x; +} + +template::value, + bool IsUSigned = IsSigned::value> +struct DoesRangeContainRange +{ +}; + +template +struct DoesRangeContainRange +{ + static const bool value = sizeof(T) >= sizeof(U); +}; + +template +struct DoesRangeContainRange +{ + static const bool value = sizeof(T) > sizeof(U); +}; + +template +struct DoesRangeContainRange +{ + static const bool value = false; +}; + +template::value, + bool IsUSigned = IsSigned::value, + bool DoesTRangeContainURange = DoesRangeContainRange::value> +struct IsInRangeImpl {}; + +template +struct IsInRangeImpl +{ + static bool run(U) + { + return true; + } +}; + +template +struct IsInRangeImpl +{ + static bool run(U x) + { + return x <= MaxValue::value && x >= MinValue::value; + } +}; + +template +struct IsInRangeImpl +{ + static bool run(U x) + { + return x <= MaxValue::value; + } +}; + +template +struct IsInRangeImpl +{ + static bool run(U x) + { + return sizeof(T) > sizeof(U) || x <= U(MaxValue::value); + } +}; + +template +struct IsInRangeImpl +{ + static bool run(U x) + { + return sizeof(T) >= sizeof(U) + ? x >= 0 + : x >= 0 && x <= U(MaxValue::value); + } +}; + +template +inline bool +IsInRange(U x) +{ + return IsInRangeImpl::run(x); +} + +template +inline bool +IsAddValid(T x, T y) +{ + // Addition is valid if the sign of x+y is equal to either that of x or that + // of y. Since the value of x+y is undefined if we have a signed type, we + // compute it using the unsigned type of the same size. + // Beware! These bitwise operations can return a larger integer type, + // if T was a small type like int8_t, so we explicitly cast to T. + + typename UnsignedType::Type ux = x; + typename UnsignedType::Type uy = y; + typename UnsignedType::Type result = ux + uy; + return IsSigned::value + ? HasSignBit(BinaryComplement(T((result ^ x) & (result ^ y)))) + : BinaryComplement(x) >= y; +} + +template +inline bool +IsSubValid(T x, T y) +{ + // Subtraction is valid if either x and y have same sign, or x-y and x have + // same sign. Since the value of x-y is undefined if we have a signed type, + // we compute it using the unsigned type of the same size. + typename UnsignedType::Type ux = x; + typename UnsignedType::Type uy = y; + typename UnsignedType::Type result = ux - uy; + + return IsSigned::value + ? HasSignBit(BinaryComplement(T((result ^ x) & (x ^ y)))) + : x >= y; +} + +template::value, + bool TwiceBiggerTypeIsSupported = + IsSupported::Type>::value> +struct IsMulValidImpl {}; + +template +struct IsMulValidImpl +{ + static bool run(T x, T y) + { + typedef typename TwiceBiggerType::Type TwiceBiggerType; + TwiceBiggerType product = TwiceBiggerType(x) * TwiceBiggerType(y); + return IsInRange(product); + } +}; + +template +struct IsMulValidImpl +{ + static bool run(T x, T y) + { + const T max = MaxValue::value; + const T min = MinValue::value; + + if (x == 0 || y == 0) + return true; + + if (x > 0) { + return y > 0 + ? x <= max / y + : y >= min / x; + } + + // If we reach this point, we know that x < 0. + return y > 0 + ? x >= min / y + : y >= max / x; + } +}; + +template +struct IsMulValidImpl +{ + static bool run(T x, T y) + { + return y == 0 || x <= MaxValue::value / y; + } +}; + +template +inline bool +IsMulValid(T x, T y) +{ + return IsMulValidImpl::run(x, y); +} + +template +inline bool +IsDivValid(T x, T y) +{ + // Keep in mind that in the signed case, min/-1 is invalid because abs(min)>max. + return y != 0 && + !(IsSigned::value && x == MinValue::value && y == T(-1)); +} + +// This is just to shut up msvc warnings about negating unsigned ints. +template::value> +struct OppositeIfSignedImpl +{ + static T run(T x) { return -x; } +}; +template +struct OppositeIfSignedImpl +{ + static T run(T x) { return x; } +}; +template +inline T +OppositeIfSigned(T x) +{ + return OppositeIfSignedImpl::run(x); +} + +} // namespace detail + + +/* + * Step 4: Now define the CheckedInt class. + */ + +/** + * @class CheckedInt + * @brief Integer wrapper class checking for integer overflow and other errors + * @param T the integer type to wrap. Can be any type among the following: + * - any basic integer type such as |int| + * - any stdint type such as |int8_t| + * + * This class implements guarded integer arithmetic. Do a computation, check + * that isValid() returns true, you then have a guarantee that no problem, such + * as integer overflow, happened during this computation, and you can call + * value() to get the plain integer value. + * + * The arithmetic operators in this class are guaranteed not to raise a signal + * (e.g. in case of a division by zero). + * + * For example, suppose that you want to implement a function that computes + * (x+y)/z, that doesn't crash if z==0, and that reports on error (divide by + * zero or integer overflow). You could code it as follows: + @code + bool computeXPlusYOverZ(int x, int y, int z, int *result) + { + CheckedInt checkedResult = (CheckedInt(x) + y) / z; + if (checkedResult.isValid()) { + *result = checkedResult.value(); + return true; + } else { + return false; + } + } + @endcode + * + * Implicit conversion from plain integers to checked integers is allowed. The + * plain integer is checked to be in range before being casted to the + * destination type. This means that the following lines all compile, and the + * resulting CheckedInts are correctly detected as valid or invalid: + * @code + // 1 is of type int, is found to be in range for uint8_t, x is valid + CheckedInt x(1); + // -1 is of type int, is found not to be in range for uint8_t, x is invalid + CheckedInt x(-1); + // -1 is of type int, is found to be in range for int8_t, x is valid + CheckedInt x(-1); + // 1000 is of type int16_t, is found not to be in range for int8_t, + // x is invalid + CheckedInt x(int16_t(1000)); + // 3123456789 is of type uint32_t, is found not to be in range for int32_t, + // x is invalid + CheckedInt x(uint32_t(3123456789)); + * @endcode + * Implicit conversion from + * checked integers to plain integers is not allowed. As shown in the + * above example, to get the value of a checked integer as a normal integer, + * call value(). + * + * Arithmetic operations between checked and plain integers is allowed; the + * result type is the type of the checked integer. + * + * Checked integers of different types cannot be used in the same arithmetic + * expression. + * + * There are convenience typedefs for all stdint types, of the following form + * (these are just 2 examples): + @code + typedef CheckedInt CheckedInt32; + typedef CheckedInt CheckedUint16; + @endcode + */ +template +class CheckedInt +{ + protected: + T mValue; + bool mIsValid; + + template + CheckedInt(U value, bool isValid) : mValue(value), mIsValid(isValid) + { + MOZ_STATIC_ASSERT(detail::IsSupported::value, + "This type is not supported by CheckedInt"); + } + + public: + /** + * Constructs a checked integer with given @a value. The checked integer is + * initialized as valid or invalid depending on whether the @a value + * is in range. + * + * This constructor is not explicit. Instead, the type of its argument is a + * separate template parameter, ensuring that no conversion is performed + * before this constructor is actually called. As explained in the above + * documentation for class CheckedInt, this constructor checks that its + * argument is valid. + */ + template + CheckedInt(U value) + : mValue(T(value)), + mIsValid(detail::IsInRange(value)) + { + MOZ_STATIC_ASSERT(detail::IsSupported::value, + "This type is not supported by CheckedInt"); + } + + /** Constructs a valid checked integer with initial value 0 */ + CheckedInt() : mValue(0), mIsValid(true) + { + MOZ_STATIC_ASSERT(detail::IsSupported::value, + "This type is not supported by CheckedInt"); + } + + /** @returns the actual value */ + T value() const + { + MOZ_ASSERT(mIsValid, "Invalid checked integer (division by zero or integer overflow)"); + return mValue; + } + + /** + * @returns true if the checked integer is valid, i.e. is not the result + * of an invalid operation or of an operation involving an invalid checked + * integer + */ + bool isValid() const + { + return mIsValid; + } + + template + friend CheckedInt operator +(const CheckedInt& lhs, + const CheckedInt& rhs); + template + CheckedInt& operator +=(U rhs); + template + friend CheckedInt operator -(const CheckedInt& lhs, + const CheckedInt &rhs); + template + CheckedInt& operator -=(U rhs); + template + friend CheckedInt operator *(const CheckedInt& lhs, + const CheckedInt &rhs); + template + CheckedInt& operator *=(U rhs); + template + friend CheckedInt operator /(const CheckedInt& lhs, + const CheckedInt &rhs); + template + CheckedInt& operator /=(U rhs); + + CheckedInt operator -() const + { + // Circumvent msvc warning about - applied to unsigned int. + // if we're unsigned, the only valid case anyway is 0 + // in which case - is a no-op. + T result = detail::OppositeIfSigned(mValue); + /* Help the compiler perform RVO (return value optimization). */ + return CheckedInt(result, + mIsValid && detail::IsSubValid(T(0), + mValue)); + } + + /** + * @returns true if the left and right hand sides are valid + * and have the same value. + * + * Note that these semantics are the reason why we don't offer + * a operator!=. Indeed, we'd want to have a!=b be equivalent to !(a==b) + * but that would mean that whenever a or b is invalid, a!=b + * is always true, which would be very confusing. + * + * For similar reasons, operators <, >, <=, >= would be very tricky to + * specify, so we just avoid offering them. + * + * Notice that these == semantics are made more reasonable by these facts: + * 1. a==b implies equality at the raw data level + * (the converse is false, as a==b is never true among invalids) + * 2. This is similar to the behavior of IEEE floats, where a==b + * means that a and b have the same value *and* neither is NaN. + */ + bool operator ==(const CheckedInt& other) const + { + return mIsValid && other.mIsValid && mValue == other.mValue; + } + + /** prefix ++ */ + CheckedInt& operator++() + { + *this += 1; + return *this; + } + + /** postfix ++ */ + CheckedInt operator++(int) + { + CheckedInt tmp = *this; + *this += 1; + return tmp; + } + + /** prefix -- */ + CheckedInt& operator--() + { + *this -= 1; + return *this; + } + + /** postfix -- */ + CheckedInt operator--(int) + { + CheckedInt tmp = *this; + *this -= 1; + return tmp; + } + + private: + /** + * The !=, <, <=, >, >= operators are disabled: + * see the comment on operator==. + */ + template + bool operator !=(U other) const MOZ_DELETE; + template + bool operator <(U other) const MOZ_DELETE; + template + bool operator <=(U other) const MOZ_DELETE; + template + bool operator >(U other) const MOZ_DELETE; + template + bool operator >=(U other) const MOZ_DELETE; +}; + +#define MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(NAME, OP) \ +template \ +inline CheckedInt operator OP(const CheckedInt &lhs, \ + const CheckedInt &rhs) \ +{ \ + if (!detail::Is##NAME##Valid(lhs.mValue, rhs.mValue)) \ + return CheckedInt(0, false); \ + \ + return CheckedInt(lhs.mValue OP rhs.mValue, \ + lhs.mIsValid && rhs.mIsValid); \ +} + +MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Add, +) +MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Sub, -) +MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Mul, *) +MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR(Div, /) + +#undef MOZ_CHECKEDINT_BASIC_BINARY_OPERATOR + +// Implement castToCheckedInt(x), making sure that +// - it allows x to be either a CheckedInt or any integer type +// that can be casted to T +// - if x is already a CheckedInt, we just return a reference to it, +// instead of copying it (optimization) + +namespace detail { + +template +struct CastToCheckedIntImpl +{ + typedef CheckedInt ReturnType; + static CheckedInt run(U u) { return u; } +}; + +template +struct CastToCheckedIntImpl > +{ + typedef const CheckedInt& ReturnType; + static const CheckedInt& run(const CheckedInt& u) { return u; } +}; + +} // namespace detail + +template +inline typename detail::CastToCheckedIntImpl::ReturnType +castToCheckedInt(U u) +{ + return detail::CastToCheckedIntImpl::run(u); +} + +#define MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(OP, COMPOUND_OP) \ +template \ +template \ +CheckedInt& CheckedInt::operator COMPOUND_OP(U rhs) \ +{ \ + *this = *this OP castToCheckedInt(rhs); \ + return *this; \ +} \ +template \ +inline CheckedInt operator OP(const CheckedInt &lhs, U rhs) \ +{ \ + return lhs OP castToCheckedInt(rhs); \ +} \ +template \ +inline CheckedInt operator OP(U lhs, const CheckedInt &rhs) \ +{ \ + return castToCheckedInt(lhs) OP rhs; \ +} + +MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(+, +=) +MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(*, *=) +MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(-, -=) +MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS(/, /=) + +#undef MOZ_CHECKEDINT_CONVENIENCE_BINARY_OPERATORS + +template +inline bool +operator ==(const CheckedInt &lhs, U rhs) +{ + return lhs == castToCheckedInt(rhs); +} + +template +inline bool +operator ==(U lhs, const CheckedInt &rhs) +{ + return castToCheckedInt(lhs) == rhs; +} + +// Convenience typedefs. +typedef CheckedInt CheckedInt8; +typedef CheckedInt CheckedUint8; +typedef CheckedInt CheckedInt16; +typedef CheckedInt CheckedUint16; +typedef CheckedInt CheckedInt32; +typedef CheckedInt CheckedUint32; +typedef CheckedInt CheckedInt64; +typedef CheckedInt CheckedUint64; + +} // namespace mozilla + +#endif /* mozilla_CheckedInt_h_ */ diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/FloatingPoint.h b/scripting/javascript/spidermonkey-android/include/mozilla/FloatingPoint.h index 029ecf23a6..cb1394e1a4 100644 --- a/scripting/javascript/spidermonkey-android/include/mozilla/FloatingPoint.h +++ b/scripting/javascript/spidermonkey-android/include/mozilla/FloatingPoint.h @@ -226,16 +226,6 @@ MOZ_DOUBLE_MIN_VALUE() return pun.d; } -/** Computes a 32-bit hash of the given double. */ -static MOZ_ALWAYS_INLINE uint32_t -MOZ_HASH_DOUBLE(double d) -{ - union MozDoublePun pun; - pun.d = d; - - return ((uint32_t)(pun.u >> 32)) ^ ((uint32_t)(pun.u)); -} - static MOZ_ALWAYS_INLINE int MOZ_DOUBLE_IS_INT32(double d, int32_t* i) { diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/GuardObjects.h b/scripting/javascript/spidermonkey-android/include/mozilla/GuardObjects.h index 68d5eb35d0..95aa37a19d 100644 --- a/scripting/javascript/spidermonkey-android/include/mozilla/GuardObjects.h +++ b/scripting/javascript/spidermonkey-android/include/mozilla/GuardObjects.h @@ -1,42 +1,7 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* vim: set ts=8 sw=4 et tw=99 ft=cpp: */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * the Mozilla Foundation. - * Portions created by the Initial Developer are Copyright (C) 2010 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * L. David Baron , Mozilla Corporation (original author) - * Ms2ger - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Implementation of macros to ensure correct use of RAII Auto* objects. */ @@ -52,6 +17,7 @@ namespace mozilla { namespace detail { + /* * The following classes are designed to cause assertions to detect * inadvertent use of guard objects as temporaries. In other words, @@ -59,11 +25,11 @@ namespace detail { * destructor (and is never otherwise referenced), the intended use * might be: * - * AutoRestore savePainting(mIsPainting); + * AutoRestore savePainting(mIsPainting); * * but is is easy to accidentally write: * - * AutoRestore(mIsPainting); + * AutoRestore(mIsPainting); * * which compiles just fine, but runs the destructor well before the * intended time. @@ -106,14 +72,14 @@ class MOZ_EXPORT_API(GuardObjectNotifier) bool* statementDone; public: - GuardObjectNotifier() : statementDone(NULL) {} + GuardObjectNotifier() : statementDone(NULL) { } ~GuardObjectNotifier() { - *statementDone = true; + *statementDone = true; } void setStatementDone(bool* statementIsDone) { - statementDone = statementIsDone; + statementDone = statementIsDone; } }; @@ -123,25 +89,24 @@ class MOZ_EXPORT_API(GuardObjectNotificationReceiver) bool statementDone; public: - GuardObjectNotificationReceiver() : statementDone(false) {} + GuardObjectNotificationReceiver() : statementDone(false) { } ~GuardObjectNotificationReceiver() { - /* - * Assert that the guard object was not used as a temporary. - * (Note that this assert might also fire if init is not called - * because the guard object's implementation is not using the - * above macros correctly.) - */ - MOZ_ASSERT(statementDone); + /* + * Assert that the guard object was not used as a temporary. (Note that + * this assert might also fire if init is not called because the guard + * object's implementation is not using the above macros correctly.) + */ + MOZ_ASSERT(statementDone); } void init(const GuardObjectNotifier& constNotifier) { - /* - * constNotifier is passed as a const reference so that we can pass a - * temporary, but we really intend it as non-const. - */ - GuardObjectNotifier& notifier = const_cast(constNotifier); - notifier.setStatementDone(&statementDone); + /* + * constNotifier is passed as a const reference so that we can pass a + * temporary, but we really intend it as non-const. + */ + GuardObjectNotifier& notifier = const_cast(constNotifier); + notifier.setStatementDone(&statementDone); } }; diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/HashFunctions.h b/scripting/javascript/spidermonkey-android/include/mozilla/HashFunctions.h index 4f8ff406e9..7a19749e55 100644 --- a/scripting/javascript/spidermonkey-android/include/mozilla/HashFunctions.h +++ b/scripting/javascript/spidermonkey-android/include/mozilla/HashFunctions.h @@ -1,11 +1,9 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: set ts=8 sw=4 et tw=99 ft=cpp: - * - * This Source Code Form is subject to the terms of the Mozilla Public +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* Utilities for hashing */ +/* Utilities for hashing. */ /* * This file exports functions for hashing data down to a 32-bit value, @@ -26,16 +24,18 @@ * * You can chain these functions together to hash complex objects. For example: * - * class ComplexObject { - * char* str; - * uint32_t uint1, uint2; - * void (*callbackFn)(); + * class ComplexObject + * { + * char* str; + * uint32_t uint1, uint2; + * void (*callbackFn)(); * - * uint32_t Hash() { - * uint32_t hash = HashString(str); - * hash = AddToHash(hash, uint1, uint2); - * return AddToHash(hash, callbackFn); - * } + * public: + * uint32_t hash() { + * uint32_t hash = HashString(str); + * hash = AddToHash(hash, uint1, uint2); + * return AddToHash(hash, callbackFn); + * } * }; * * If you want to hash an nsAString or nsACString, use the HashString functions @@ -48,6 +48,7 @@ #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" #include "mozilla/StandardInteger.h" +#include "mozilla/Types.h" #ifdef __cplusplus namespace mozilla { diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/Likely.h b/scripting/javascript/spidermonkey-android/include/mozilla/Likely.h index 6534239b16..a217e60c68 100644 --- a/scripting/javascript/spidermonkey-android/include/mozilla/Likely.h +++ b/scripting/javascript/spidermonkey-android/include/mozilla/Likely.h @@ -1,3 +1,4 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -7,8 +8,8 @@ * boolean predicate should be branch-predicted. */ -#ifndef Likely_h_ -#define Likely_h_ +#ifndef mozilla_Likely_h_ +#define mozilla_Likely_h_ #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2)) # define MOZ_LIKELY(x) (__builtin_expect((x), 1)) @@ -18,4 +19,4 @@ # define MOZ_UNLIKELY(x) (x) #endif -#endif /* Likely_h_ */ +#endif /* mozilla_Likely_h_ */ diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/LinkedList.h b/scripting/javascript/spidermonkey-android/include/mozilla/LinkedList.h index 640a6519ee..d7d3b23607 100644 --- a/scripting/javascript/spidermonkey-android/include/mozilla/LinkedList.h +++ b/scripting/javascript/spidermonkey-android/include/mozilla/LinkedList.h @@ -1,42 +1,7 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=4 sw=4 tw=80 et cin: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Code. - * - * The Initial Developer of the Original Code is - * The Mozilla Foundation - * Portions created by the Initial Developer are Copyright (C) 2012 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Justin Lebar - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* A type-safe doubly-linked list class. */ @@ -53,36 +18,30 @@ * * class Observer : public LinkedListElement * { - * void observe(char* topic) { ... } + * public: + * void observe(char* topic) { ... } * }; * * class ObserverContainer * { - * private: - * LinkedList list; + * private: + * LinkedList list; * - * public: - * - * void addObserver(Observer* observer) - * { - * // Will assert if |observer| is part of another list. - * list.insertBack(observer); - * } - * - * void removeObserver(Observer* observer) - * { - * // Will assert if |observer| is not part of some list. - * observer.remove(); - * } - * - * void notifyObservers(char* topic) - * { - * for (Observer* o = list.getFirst(); - * o != NULL; - * o = o->getNext()) { - * o->Observe(topic); + * public: + * void addObserver(Observer* observer) { + * // Will assert if |observer| is part of another list. + * list.insertBack(observer); + * } + * + * void removeObserver(Observer* observer) { + * // Will assert if |observer| is not part of some list. + * observer.remove(); + * } + * + * void notifyObservers(char* topic) { + * for (Observer* o = list.getFirst(); o != NULL; o = o->getNext()) + * o->Observe(topic); * } - * } * }; * */ @@ -137,43 +96,41 @@ class LinkedListElement * lists, and supporting this painlessly was a key design criterion. */ -private: + private: LinkedListElement* next; LinkedListElement* prev; const bool isSentinel; -public: - LinkedListElement() - : next(this) - , prev(this) - , isSentinel(false) - { - } + public: + LinkedListElement() : next(this), prev(this), isSentinel(false) { } /* * Get the next element in the list, or NULL if this is the last element in * the list. */ - T* getNext() - { - return next->asT(); + T* getNext() { + return next->asT(); + } + const T* getNext() const { + return next->asT(); } /* * Get the previous element in the list, or NULL if this is the first element * in the list. */ - T* getPrevious() - { - return prev->asT(); + T* getPrevious() { + return prev->asT(); + } + const T* getPrevious() const { + return prev->asT(); } /* * Insert elem after this element in the list. |this| must be part of a * linked list when you call setNext(); otherwise, this method will assert. */ - void setNext(T* elem) - { + void setNext(T* elem) { MOZ_ASSERT(isInList()); setNextUnsafe(elem); } @@ -183,50 +140,44 @@ public: * linked list when you call setPrevious(); otherwise, this method will * assert. */ - void setPrevious(T* elem) - { - MOZ_ASSERT(isInList()); - setPreviousUnsafe(elem); + void setPrevious(T* elem) { + MOZ_ASSERT(isInList()); + setPreviousUnsafe(elem); } /* * Remove this element from the list which contains it. If this element is * not currently part of a linked list, this method asserts. */ - void remove() - { - MOZ_ASSERT(isInList()); + void remove() { + MOZ_ASSERT(isInList()); - prev->next = next; - next->prev = prev; - next = this; - prev = this; + prev->next = next; + next->prev = prev; + next = this; + prev = this; } /* * Return true if |this| part is of a linked list, and false otherwise. */ - bool isInList() - { - MOZ_ASSERT((next == this) == (prev == this)); - return next != this; + bool isInList() const { + MOZ_ASSERT((next == this) == (prev == this)); + return next != this; } -private: - LinkedListElement& operator=(const LinkedList& other) MOZ_DELETE; - LinkedListElement(const LinkedList& other) MOZ_DELETE; - + private: friend class LinkedList; enum NodeKind { - NODE_KIND_NORMAL, - NODE_KIND_SENTINEL + NODE_KIND_NORMAL, + NODE_KIND_SENTINEL }; LinkedListElement(NodeKind nodeKind) - : next(this) - , prev(this) - , isSentinel(nodeKind == NODE_KIND_SENTINEL) + : next(this), + prev(this), + isSentinel(nodeKind == NODE_KIND_SENTINEL) { } @@ -234,125 +185,123 @@ private: * Return |this| cast to T* if we're a normal node, or return NULL if we're * a sentinel node. */ - T* asT() - { - if (isSentinel) - return NULL; + T* asT() { + if (isSentinel) + return NULL; - return static_cast(this); + return static_cast(this); + } + const T* asT() const { + if (isSentinel) + return NULL; + + return static_cast(this); } /* * Insert elem after this element, but don't check that this element is in * the list. This is called by LinkedList::insertFront(). */ - void setNextUnsafe(T* elem) - { - LinkedListElement *listElem = static_cast(elem); - MOZ_ASSERT(!listElem->isInList()); + void setNextUnsafe(T* elem) { + LinkedListElement *listElem = static_cast(elem); + MOZ_ASSERT(!listElem->isInList()); - listElem->next = this->next; - listElem->prev = this; - this->next->prev = listElem; - this->next = listElem; + listElem->next = this->next; + listElem->prev = this; + this->next->prev = listElem; + this->next = listElem; } /* * Insert elem before this element, but don't check that this element is in * the list. This is called by LinkedList::insertBack(). */ - void setPreviousUnsafe(T* elem) - { - LinkedListElement* listElem = static_cast*>(elem); - MOZ_ASSERT(!listElem->isInList()); + void setPreviousUnsafe(T* elem) { + LinkedListElement* listElem = static_cast*>(elem); + MOZ_ASSERT(!listElem->isInList()); - listElem->next = this; - listElem->prev = this->prev; - this->prev->next = listElem; - this->prev = listElem; + listElem->next = this; + listElem->prev = this->prev; + this->prev->next = listElem; + this->prev = listElem; } + + private: + LinkedListElement& operator=(const LinkedList& other) MOZ_DELETE; + LinkedListElement(const LinkedList& other) MOZ_DELETE; }; template class LinkedList { -private: + private: LinkedListElement sentinel; -public: - LinkedList& operator=(const LinkedList& other) MOZ_DELETE; - LinkedList(const LinkedList& other) MOZ_DELETE; - - LinkedList() - : sentinel(LinkedListElement::NODE_KIND_SENTINEL) - { - } + public: + LinkedList() : sentinel(LinkedListElement::NODE_KIND_SENTINEL) { } /* * Add elem to the front of the list. */ - void insertFront(T* elem) - { - /* Bypass setNext()'s this->isInList() assertion. */ - sentinel.setNextUnsafe(elem); + void insertFront(T* elem) { + /* Bypass setNext()'s this->isInList() assertion. */ + sentinel.setNextUnsafe(elem); } /* * Add elem to the back of the list. */ - void insertBack(T* elem) - { - sentinel.setPreviousUnsafe(elem); + void insertBack(T* elem) { + sentinel.setPreviousUnsafe(elem); } /* * Get the first element of the list, or NULL if the list is empty. */ - T* getFirst() - { - return sentinel.getNext(); + T* getFirst() { + return sentinel.getNext(); + } + const T* getFirst() const { + return sentinel.getNext(); } /* * Get the last element of the list, or NULL if the list is empty. */ - T* getLast() - { - return sentinel.getPrevious(); + T* getLast() { + return sentinel.getPrevious(); + } + const T* getLast() const { + return sentinel.getPrevious(); } /* * Get and remove the first element of the list. If the list is empty, * return NULL. */ - T* popFirst() - { - T* ret = sentinel.getNext(); - if (ret) - static_cast*>(ret)->remove(); - - return ret; + T* popFirst() { + T* ret = sentinel.getNext(); + if (ret) + static_cast*>(ret)->remove(); + return ret; } /* * Get and remove the last element of the list. If the list is empty, * return NULL. */ - T* popLast() - { - T* ret = sentinel.getPrevious(); - if (ret) - static_cast*>(ret)->remove(); - - return ret; + T* popLast() { + T* ret = sentinel.getPrevious(); + if (ret) + static_cast*>(ret)->remove(); + return ret; } /* * Return true if the list is empty, or false otherwise. */ - bool isEmpty() - { - return !sentinel.isInList(); + bool isEmpty() const { + return !sentinel.isInList(); } /* @@ -361,71 +310,73 @@ public: * This runs in time linear to the list's length, because we have to mark * each element as not in the list. */ - void clear() - { - while (popFirst()) - continue; + void clear() { + while (popFirst()) + continue; } /* * In a debug build, make sure that the list is sane (no cycles, consistent * next/prev pointers, only one sentinel). Has no effect in release builds. */ - void debugAssertIsSane() - { + void debugAssertIsSane() const { #ifdef DEBUG - /* - * Check for cycles in the forward singly-linked list using the - * tortoise/hare algorithm. - */ - for (LinkedListElement* slow = sentinel.next, - * fast1 = sentinel.next->next, - * fast2 = sentinel.next->next->next; - slow != sentinel && fast1 != sentinel && fast2 != sentinel; - slow = slow->next, - fast1 = fast2->next, - fast2 = fast1->next) { + const LinkedListElement* slow; + const LinkedListElement* fast1; + const LinkedListElement* fast2; - MOZ_ASSERT(slow != fast1); - MOZ_ASSERT(slow != fast2); - } + /* + * Check for cycles in the forward singly-linked list using the + * tortoise/hare algorithm. + */ + for (slow = sentinel.next, + fast1 = sentinel.next->next, + fast2 = sentinel.next->next->next; + slow != sentinel && fast1 != sentinel && fast2 != sentinel; + slow = slow->next, fast1 = fast2->next, fast2 = fast1->next) + { + MOZ_ASSERT(slow != fast1); + MOZ_ASSERT(slow != fast2); + } - /* Check for cycles in the backward singly-linked list. */ - for (LinkedListElement* slow = sentinel.prev, - * fast1 = sentinel.prev->prev, - * fast2 = sentinel.prev->prev->prev; - slow != sentinel && fast1 != sentinel && fast2 != sentinel; - slow = slow->prev, - fast1 = fast2->prev, - fast2 = fast1->prev) { + /* Check for cycles in the backward singly-linked list. */ + for (slow = sentinel.prev, + fast1 = sentinel.prev->prev, + fast2 = sentinel.prev->prev->prev; + slow != sentinel && fast1 != sentinel && fast2 != sentinel; + slow = slow->prev, fast1 = fast2->prev, fast2 = fast1->prev) + { + MOZ_ASSERT(slow != fast1); + MOZ_ASSERT(slow != fast2); + } - MOZ_ASSERT(slow != fast1); - MOZ_ASSERT(slow != fast2); - } + /* + * Check that |sentinel| is the only node in the list with + * isSentinel == true. + */ + for (const LinkedListElement* elem = sentinel.next; + elem != sentinel; + elem = elem->next) + { + MOZ_ASSERT(!elem->isSentinel); + } - /* - * Check that |sentinel| is the only node in the list with - * isSentinel == true. - */ - for (LinkedListElement* elem = sentinel.next; - elem != sentinel; - elem = elem->next) { + /* Check that the next/prev pointers match up. */ + const LinkedListElement* prev = sentinel; + const LinkedListElement* cur = sentinel.next; + do { + MOZ_ASSERT(cur->prev == prev); + MOZ_ASSERT(prev->next == cur); - MOZ_ASSERT(!elem->isSentinel); - } - - /* Check that the next/prev pointers match up. */ - LinkedListElement* prev = sentinel; - LinkedListElement* cur = sentinel.next; - do { - MOZ_ASSERT(cur->prev == prev); - MOZ_ASSERT(prev->next == cur); - - prev = cur; - cur = cur->next; - } while (cur != sentinel); + prev = cur; + cur = cur->next; + } while (cur != sentinel); #endif /* ifdef DEBUG */ } + + private: + LinkedList& operator=(const LinkedList& other) MOZ_DELETE; + LinkedList(const LinkedList& other) MOZ_DELETE; }; } /* namespace mozilla */ diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/RangedPtr.h b/scripting/javascript/spidermonkey-android/include/mozilla/RangedPtr.h index 74ad1c75e4..7c8d58147d 100644 --- a/scripting/javascript/spidermonkey-android/include/mozilla/RangedPtr.h +++ b/scripting/javascript/spidermonkey-android/include/mozilla/RangedPtr.h @@ -1,42 +1,7 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=99 ft=cpp: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Code. - * - * The Initial Developer of the Original Code is - * The Mozilla Foundation - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Jeff Walden (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Implements a smart pointer asserted to remain within a range specified at @@ -71,7 +36,7 @@ namespace mozilla { * explicitly convert to T*. Keep in mind that the raw pointer of course won't * implement bounds checking in debug builds. */ -template +template class RangedPtr { T* ptr; @@ -82,16 +47,16 @@ class RangedPtr #endif void checkSanity() { - MOZ_ASSERT(rangeStart <= ptr); - MOZ_ASSERT(ptr <= rangeEnd); + MOZ_ASSERT(rangeStart <= ptr); + MOZ_ASSERT(ptr <= rangeEnd); } /* Creates a new pointer for |ptr|, restricted to this pointer's range. */ RangedPtr create(T *ptr) const { #ifdef DEBUG - return RangedPtr(ptr, rangeStart, rangeEnd); + return RangedPtr(ptr, rangeStart, rangeEnd); #else - return RangedPtr(ptr, NULL, size_t(0)); + return RangedPtr(ptr, NULL, size_t(0)); #endif } @@ -102,8 +67,8 @@ class RangedPtr , rangeStart(start), rangeEnd(end) #endif { - MOZ_ASSERT(rangeStart <= rangeEnd); - checkSanity(); + MOZ_ASSERT(rangeStart <= rangeEnd); + checkSanity(); } RangedPtr(T* p, T* start, size_t length) : ptr(p) @@ -111,9 +76,9 @@ class RangedPtr , rangeStart(start), rangeEnd(start + length) #endif { - MOZ_ASSERT(length <= size_t(-1) / sizeof(T)); - MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart)); - checkSanity(); + MOZ_ASSERT(length <= size_t(-1) / sizeof(T)); + MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart)); + checkSanity(); } /* Equivalent to RangedPtr(p, p, length). */ @@ -123,9 +88,9 @@ class RangedPtr , rangeStart(p), rangeEnd(p + length) #endif { - MOZ_ASSERT(length <= size_t(-1) / sizeof(T)); - MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart)); - checkSanity(); + MOZ_ASSERT(length <= size_t(-1) / sizeof(T)); + MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart)); + checkSanity(); } /* Equivalent to RangedPtr(arr, arr, N). */ @@ -140,7 +105,7 @@ class RangedPtr } T* get() const { - return ptr; + return ptr; } /* @@ -154,23 +119,23 @@ class RangedPtr * p1 = RangedPtr(arr2, 3); // asserts */ RangedPtr& operator=(const RangedPtr& other) { - MOZ_ASSERT(rangeStart == other.rangeStart); - MOZ_ASSERT(rangeEnd == other.rangeEnd); - ptr = other.ptr; - checkSanity(); - return *this; + MOZ_ASSERT(rangeStart == other.rangeStart); + MOZ_ASSERT(rangeEnd == other.rangeEnd); + ptr = other.ptr; + checkSanity(); + return *this; } RangedPtr operator+(size_t inc) { - MOZ_ASSERT(inc <= size_t(-1) / sizeof(T)); - MOZ_ASSERT(ptr + inc > ptr); - return create(ptr + inc); + MOZ_ASSERT(inc <= size_t(-1) / sizeof(T)); + MOZ_ASSERT(ptr + inc > ptr); + return create(ptr + inc); } RangedPtr operator-(size_t dec) { - MOZ_ASSERT(dec <= size_t(-1) / sizeof(T)); - MOZ_ASSERT(ptr - dec < ptr); - return create(ptr - dec); + MOZ_ASSERT(dec <= size_t(-1) / sizeof(T)); + MOZ_ASSERT(ptr - dec < ptr); + return create(ptr - dec); } /* @@ -179,97 +144,97 @@ class RangedPtr */ template RangedPtr& operator=(U* p) { - *this = create(p); - return *this; + *this = create(p); + return *this; } template RangedPtr& operator=(const RangedPtr& p) { - MOZ_ASSERT(rangeStart <= p.ptr); - MOZ_ASSERT(p.ptr <= rangeEnd); - ptr = p.ptr; - checkSanity(); - return *this; + MOZ_ASSERT(rangeStart <= p.ptr); + MOZ_ASSERT(p.ptr <= rangeEnd); + ptr = p.ptr; + checkSanity(); + return *this; } RangedPtr& operator++() { - return (*this += 1); + return (*this += 1); } RangedPtr operator++(int) { - RangedPtr rcp = *this; - ++*this; - return rcp; + RangedPtr rcp = *this; + ++*this; + return rcp; } RangedPtr& operator--() { - return (*this -= 1); + return (*this -= 1); } RangedPtr operator--(int) { - RangedPtr rcp = *this; - --*this; - return rcp; + RangedPtr rcp = *this; + --*this; + return rcp; } RangedPtr& operator+=(size_t inc) { - this->operator=(*this + inc); - return *this; + *this = *this + inc; + return *this; } RangedPtr& operator-=(size_t dec) { - this->operator=(*this - dec); - return *this; + *this = *this - dec; + return *this; } T& operator[](int index) const { - MOZ_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T)); - return *create(ptr + index); + MOZ_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T)); + return *create(ptr + index); } T& operator*() const { - return *ptr; + return *ptr; } template bool operator==(const RangedPtr& other) const { - return ptr == other.ptr; + return ptr == other.ptr; } template bool operator!=(const RangedPtr& other) const { - return !(*this == other); + return !(*this == other); } template bool operator==(const U* u) const { - return ptr == u; + return ptr == u; } template bool operator!=(const U* u) const { - return !(*this == u); + return !(*this == u); } template bool operator<(const RangedPtr& other) const { - return ptr < other.ptr; + return ptr < other.ptr; } template bool operator<=(const RangedPtr& other) const { - return ptr <= other.ptr; + return ptr <= other.ptr; } template bool operator>(const RangedPtr& other) const { - return ptr > other.ptr; + return ptr > other.ptr; } template bool operator>=(const RangedPtr& other) const { - return ptr >= other.ptr; + return ptr >= other.ptr; } size_t operator-(const RangedPtr& other) const { - MOZ_ASSERT(ptr >= other.ptr); - return PointerRangeSize(other.ptr, ptr); + MOZ_ASSERT(ptr >= other.ptr); + return PointerRangeSize(other.ptr, ptr); } private: diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/RefPtr.h b/scripting/javascript/spidermonkey-android/include/mozilla/RefPtr.h index 8c3ff94f10..15ace62ef8 100644 --- a/scripting/javascript/spidermonkey-android/include/mozilla/RefPtr.h +++ b/scripting/javascript/spidermonkey-android/include/mozilla/RefPtr.h @@ -1,42 +1,7 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=99 ft=cpp: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Code. - * - * The Initial Developer of the Original Code is - * The Mozilla Foundation - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Chris Jones - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Helpers for defining and using refcounted objects. */ @@ -80,24 +45,24 @@ class RefCounted { friend class RefPtr; -public: + public: RefCounted() : refCnt(0) { } ~RefCounted() { MOZ_ASSERT(refCnt == -0xdead); } // Compatibility with nsRefPtr. void AddRef() { - MOZ_ASSERT(refCnt >= 0); - ++refCnt; + MOZ_ASSERT(refCnt >= 0); + ++refCnt; } void Release() { - MOZ_ASSERT(refCnt > 0); - if (0 == --refCnt) { + MOZ_ASSERT(refCnt > 0); + if (0 == --refCnt) { #ifdef DEBUG - refCnt = -0xdead; + refCnt = -0xdead; #endif - delete static_cast(this); - } + delete static_cast(this); + } } // Compatibility with wtf::RefPtr. @@ -105,11 +70,11 @@ public: void deref() { Release(); } int refCount() const { return refCnt; } bool hasOneRef() const { - MOZ_ASSERT(refCnt > 0); - return refCnt == 1; + MOZ_ASSERT(refCnt > 0); + return refCnt == 1; } -private: + private: int refCnt; }; @@ -130,9 +95,9 @@ class RefPtr friend class TemporaryRef; friend class OutParamRef; - struct dontRef {}; + struct DontRef {}; -public: + public: RefPtr() : ptr(0) { } RefPtr(const RefPtr& o) : ptr(ref(o.ptr)) {} RefPtr(const TemporaryRef& o) : ptr(o.drop()) {} @@ -144,28 +109,28 @@ public: ~RefPtr() { unref(ptr); } RefPtr& operator=(const RefPtr& o) { - assign(ref(o.ptr)); - return *this; + assign(ref(o.ptr)); + return *this; } RefPtr& operator=(const TemporaryRef& o) { - assign(o.drop()); - return *this; + assign(o.drop()); + return *this; } RefPtr& operator=(T* t) { - assign(ref(t)); - return *this; + assign(ref(t)); + return *this; } template RefPtr& operator=(const RefPtr& o) { - assign(ref(o.get())); - return *this; + assign(ref(o.get())); + return *this; } TemporaryRef forget() { - T* tmp = ptr; - ptr = 0; - return TemporaryRef(tmp, dontRef()); + T* tmp = ptr; + ptr = 0; + return TemporaryRef(tmp, DontRef()); } T* get() const { return ptr; } @@ -175,25 +140,23 @@ public: template operator TemporaryRef() { return TemporaryRef(ptr); } -private: + private: void assign(T* t) { - unref(ptr); - ptr = t; + unref(ptr); + ptr = t; } T* ptr; static MOZ_ALWAYS_INLINE T* ref(T* t) { - if (t) { - t->AddRef(); - } - return t; + if (t) + t->AddRef(); + return t; } static MOZ_ALWAYS_INLINE void unref(T* t) { - if (t) { - t->Release(); - } + if (t) + t->Release(); } }; @@ -209,9 +172,9 @@ class TemporaryRef // To allow it to construct TemporaryRef from a bare T* friend class RefPtr; - typedef typename RefPtr::dontRef dontRef; + typedef typename RefPtr::DontRef DontRef; -public: + public: TemporaryRef(T* t) : ptr(RefPtr::ref(t)) {} TemporaryRef(const TemporaryRef& o) : ptr(o.drop()) {} @@ -221,18 +184,18 @@ public: ~TemporaryRef() { RefPtr::unref(ptr); } T* drop() const { - T* tmp = ptr; - ptr = 0; - return tmp; + T* tmp = ptr; + ptr = 0; + return tmp; } -private: - TemporaryRef(T* t, const dontRef&) : ptr(t) {} + private: + TemporaryRef(T* t, const DontRef&) : ptr(t) {} mutable T* ptr; - TemporaryRef(); - TemporaryRef& operator=(const TemporaryRef&); + TemporaryRef() MOZ_DELETE; + void operator=(const TemporaryRef&) MOZ_DELETE; }; /** @@ -254,15 +217,15 @@ class OutParamRef { friend OutParamRef byRef(RefPtr&); -public: + public: ~OutParamRef() { - RefPtr::unref(refPtr.ptr); - refPtr.ptr = tmp; + RefPtr::unref(refPtr.ptr); + refPtr.ptr = tmp; } operator T**() { return &tmp; } -private: + private: OutParamRef(RefPtr& p) : refPtr(p), tmp(p.get()) {} RefPtr& refPtr; @@ -279,7 +242,7 @@ template OutParamRef byRef(RefPtr& ptr) { - return OutParamRef(ptr); + return OutParamRef(ptr); } } // namespace mozilla @@ -297,15 +260,15 @@ using namespace mozilla; struct Foo : public RefCounted { - Foo() : dead(false) { } - ~Foo() { - MOZ_ASSERT(!dead); - dead = true; - numDestroyed++; - } + Foo() : dead(false) { } + ~Foo() { + MOZ_ASSERT(!dead); + dead = true; + numDestroyed++; + } - bool dead; - static int numDestroyed; + bool dead; + static int numDestroyed; }; int Foo::numDestroyed; @@ -314,34 +277,34 @@ struct Bar : public Foo { }; TemporaryRef NewFoo() { - return RefPtr(new Foo()); + return RefPtr(new Foo()); } TemporaryRef NewBar() { - return new Bar(); + return new Bar(); } void GetNewFoo(Foo** f) { - *f = new Bar(); - // Kids, don't try this at home - (*f)->AddRef(); + *f = new Bar(); + // Kids, don't try this at home + (*f)->AddRef(); } void GetPassedFoo(Foo** f) { - // Kids, don't try this at home - (*f)->AddRef(); + // Kids, don't try this at home + (*f)->AddRef(); } void GetNewFoo(RefPtr* f) { - *f = new Bar(); + *f = new Bar(); } void @@ -351,93 +314,93 @@ GetPassedFoo(RefPtr* f) TemporaryRef GetNullFoo() { - return 0; + return 0; } int main(int argc, char** argv) { - // This should blow up + // This should blow up // Foo* f = new Foo(); delete f; - MOZ_ASSERT(0 == Foo::numDestroyed); - { - RefPtr f = new Foo(); - MOZ_ASSERT(f->refCount() == 1); - } + MOZ_ASSERT(0 == Foo::numDestroyed); + { + RefPtr f = new Foo(); + MOZ_ASSERT(f->refCount() == 1); + } + MOZ_ASSERT(1 == Foo::numDestroyed); + + { + RefPtr f1 = NewFoo(); + RefPtr f2(NewFoo()); MOZ_ASSERT(1 == Foo::numDestroyed); + } + MOZ_ASSERT(3 == Foo::numDestroyed); - { - RefPtr f1 = NewFoo(); - RefPtr f2(NewFoo()); - MOZ_ASSERT(1 == Foo::numDestroyed); - } + { + RefPtr b = NewBar(); MOZ_ASSERT(3 == Foo::numDestroyed); + } + MOZ_ASSERT(4 == Foo::numDestroyed); + { + RefPtr f1; { - RefPtr b = NewBar(); - MOZ_ASSERT(3 == Foo::numDestroyed); + f1 = new Foo(); + RefPtr f2(f1); + RefPtr f3 = f2; + MOZ_ASSERT(4 == Foo::numDestroyed); } MOZ_ASSERT(4 == Foo::numDestroyed); + } + MOZ_ASSERT(5 == Foo::numDestroyed); - { - RefPtr f1; - { - f1 = new Foo(); - RefPtr f2(f1); - RefPtr f3 = f2; - MOZ_ASSERT(4 == Foo::numDestroyed); - } - MOZ_ASSERT(4 == Foo::numDestroyed); - } - MOZ_ASSERT(5 == Foo::numDestroyed); + { + RefPtr f = new Foo(); + f.forget(); + MOZ_ASSERT(6 == Foo::numDestroyed); + } - { - RefPtr f = new Foo(); - f.forget(); - MOZ_ASSERT(6 == Foo::numDestroyed); - } + { + RefPtr f = new Foo(); + GetNewFoo(byRef(f)); + MOZ_ASSERT(7 == Foo::numDestroyed); + } + MOZ_ASSERT(8 == Foo::numDestroyed); - { - RefPtr f = new Foo(); - GetNewFoo(byRef(f)); - MOZ_ASSERT(7 == Foo::numDestroyed); - } + { + RefPtr f = new Foo(); + GetPassedFoo(byRef(f)); MOZ_ASSERT(8 == Foo::numDestroyed); + } + MOZ_ASSERT(9 == Foo::numDestroyed); - { - RefPtr f = new Foo(); - GetPassedFoo(byRef(f)); - MOZ_ASSERT(8 == Foo::numDestroyed); - } - MOZ_ASSERT(9 == Foo::numDestroyed); + { + RefPtr f = new Foo(); + GetNewFoo(&f); + MOZ_ASSERT(10 == Foo::numDestroyed); + } + MOZ_ASSERT(11 == Foo::numDestroyed); - { - RefPtr f = new Foo(); - GetNewFoo(&f); - MOZ_ASSERT(10 == Foo::numDestroyed); - } + { + RefPtr f = new Foo(); + GetPassedFoo(&f); MOZ_ASSERT(11 == Foo::numDestroyed); + } + MOZ_ASSERT(12 == Foo::numDestroyed); - { - RefPtr f = new Foo(); - GetPassedFoo(&f); - MOZ_ASSERT(11 == Foo::numDestroyed); - } - MOZ_ASSERT(12 == Foo::numDestroyed); + { + RefPtr f1 = new Bar(); + } + MOZ_ASSERT(13 == Foo::numDestroyed); - { - RefPtr f1 = new Bar(); - } + { + RefPtr f = GetNullFoo(); MOZ_ASSERT(13 == Foo::numDestroyed); + } + MOZ_ASSERT(13 == Foo::numDestroyed); - { - RefPtr f = GetNullFoo(); - MOZ_ASSERT(13 == Foo::numDestroyed); - } - MOZ_ASSERT(13 == Foo::numDestroyed); - - return 0; + return 0; } #endif diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/Scoped.h b/scripting/javascript/spidermonkey-android/include/mozilla/Scoped.h index a39a077c46..b811a47d5e 100644 --- a/scripting/javascript/spidermonkey-android/include/mozilla/Scoped.h +++ b/scripting/javascript/spidermonkey-android/include/mozilla/Scoped.h @@ -35,12 +35,12 @@ * Note that the RAII classes defined in this header do _not_ perform any form * of reference-counting or garbage-collection. These classes have exactly two * behaviors: + * * - if |forget()| has not been called, the resource is always deallocated at * the end of the scope; * - if |forget()| has been called, any control on the resource is unbound * and the resource is not deallocated by the class. * - * * Extension: * * In addition, this header provides class |Scoped| and macro |SCOPED_TEMPLATE| @@ -52,6 +52,8 @@ #include "mozilla/Attributes.h" #include "mozilla/GuardObjects.h" +namespace mozilla { + /* * Scoped is a helper to create RAII wrappers * Type argument |Traits| is expected to have the following structure: @@ -66,87 +68,87 @@ * const static void release(type); * } */ -template +template class Scoped { -public: - typedef typename Traits::type Resource; + public: + typedef typename Traits::type Resource; - explicit Scoped(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) - : value(Traits::empty()) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - explicit Scoped(const Resource& value - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) - : value(value) - { - MOZ_GUARD_OBJECT_NOTIFIER_INIT; - } - ~Scoped() { - Traits::release(value); - } + explicit Scoped(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) + : value(Traits::empty()) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + explicit Scoped(const Resource& value + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : value(value) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + ~Scoped() { + Traits::release(value); + } - // Constant getter - operator const Resource&() const { return value; } - const Resource& operator->() const { return value; } - const Resource& get() const { return value; } - // Non-constant getter. - Resource& rwget() { return value; } + // Constant getter + operator const Resource&() const { return value; } + const Resource& operator->() const { return value; } + const Resource& get() const { return value; } + // Non-constant getter. + Resource& rwget() { return value; } - /* - * Forget the resource. - * - * Once |forget| has been called, the |Scoped| is neutralized, i.e. it will - * have no effect at destruction (unless it is reset to another resource by - * |operator=|). - * - * @return The original resource. - */ - Resource forget() { - Resource tmp = value; - value = Traits::empty(); - return tmp; - } + /* + * Forget the resource. + * + * Once |forget| has been called, the |Scoped| is neutralized, i.e. it will + * have no effect at destruction (unless it is reset to another resource by + * |operator=|). + * + * @return The original resource. + */ + Resource forget() { + Resource tmp = value; + value = Traits::empty(); + return tmp; + } - /* - * Perform immediate clean-up of this |Scoped|. - * - * If this |Scoped| is currently empty, this method has no effect. - */ - void dispose() { - Traits::release(value); - value = Traits::empty(); - } + /* + * Perform immediate clean-up of this |Scoped|. + * + * If this |Scoped| is currently empty, this method has no effect. + */ + void dispose() { + Traits::release(value); + value = Traits::empty(); + } - bool operator==(const Resource& other) const { - return value == other; - } + bool operator==(const Resource& other) const { + return value == other; + } - /* - * Replace the resource with another resource. - * - * Calling |operator=| has the side-effect of triggering clean-up. If you do - * not want to trigger clean-up, you should first invoke |forget|. - * - * @return this - */ - Scoped& operator=(const Resource& other) { - return reset(other); - } - Scoped& reset(const Resource& other) { - Traits::release(value); - value = other; - return *this; - } + /* + * Replace the resource with another resource. + * + * Calling |operator=| has the side-effect of triggering clean-up. If you do + * not want to trigger clean-up, you should first invoke |forget|. + * + * @return this + */ + Scoped& operator=(const Resource& other) { + return reset(other); + } + Scoped& reset(const Resource& other) { + Traits::release(value); + value = other; + return *this; + } -private: - explicit Scoped(const Scoped& value) MOZ_DELETE; - Scoped& operator=(const Scoped& value) MOZ_DELETE; + private: + explicit Scoped(const Scoped& value) MOZ_DELETE; + Scoped& operator=(const Scoped& value) MOZ_DELETE; -private: - Resource value; - MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER + private: + Resource value; + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER }; /* @@ -158,25 +160,25 @@ private: * for more details. */ #define SCOPED_TEMPLATE(name, Traits) \ -template \ -struct name : public Scoped > \ +template \ +struct name : public mozilla::Scoped > \ { \ - typedef Scoped > Super; \ - typedef typename Super::Resource Resource; \ - name& operator=(Resource ptr) { \ - Super::operator=(ptr); \ - return *this; \ - } \ - explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) \ - : Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT) \ - {} \ - explicit name(Resource ptr \ - MOZ_GUARD_OBJECT_NOTIFIER_PARAM) \ - : Super(ptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) \ - {} \ -private: \ - explicit name(name& source) MOZ_DELETE; \ - name& operator=(name& source) MOZ_DELETE; \ + typedef mozilla::Scoped > Super; \ + typedef typename Super::Resource Resource; \ + name& operator=(Resource ptr) { \ + Super::operator=(ptr); \ + return *this; \ + } \ + explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) \ + : Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT) \ + {} \ + explicit name(Resource ptr \ + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) \ + : Super(ptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) \ + {} \ + private: \ + explicit name(name& source) MOZ_DELETE; \ + name& operator=(name& source) MOZ_DELETE; \ }; /* @@ -186,12 +188,12 @@ private: \ * ScopedFreePtr foo = malloc(sizeof(S)); * ScopedFreePtr bar = strdup(str); */ -template +template struct ScopedFreePtrTraits { - typedef T* type; - static T* empty() { return NULL; } - static void release(T* ptr) { free(ptr); } + typedef T* type; + static T* empty() { return NULL; } + static void release(T* ptr) { free(ptr); } }; SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits) @@ -201,9 +203,10 @@ SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits) * struct S { ... }; * ScopedDeletePtr foo = new S(); */ -template -struct ScopedDeletePtrTraits : public ScopedFreePtrTraits { - static void release(T* ptr) { delete ptr; } +template +struct ScopedDeletePtrTraits : public ScopedFreePtrTraits +{ + static void release(T* ptr) { delete ptr; } }; SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits) @@ -213,12 +216,13 @@ SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits) * struct S { ... }; * ScopedDeleteArray foo = new S[42]; */ -template +template struct ScopedDeleteArrayTraits : public ScopedFreePtrTraits { - static void release(T* ptr) { delete [] ptr; } + static void release(T* ptr) { delete [] ptr; } }; SCOPED_TEMPLATE(ScopedDeleteArray, ScopedDeleteArrayTraits) +} /* namespace mozilla */ #endif // mozilla_Scoped_h_ diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/StandardInteger.h b/scripting/javascript/spidermonkey-android/include/mozilla/StandardInteger.h index 344750a794..8e4c8578f1 100644 --- a/scripting/javascript/spidermonkey-android/include/mozilla/StandardInteger.h +++ b/scripting/javascript/spidermonkey-android/include/mozilla/StandardInteger.h @@ -1,42 +1,7 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=99 ft=cpp: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Code. - * - * The Initial Developer of the Original Code is - * The Mozilla Foundation - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Jeff Walden (original author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Implements the C99 interface for C and C++ code. */ diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/ThreadLocal.h b/scripting/javascript/spidermonkey-android/include/mozilla/ThreadLocal.h new file mode 100644 index 0000000000..712f1f12d4 --- /dev/null +++ b/scripting/javascript/spidermonkey-android/include/mozilla/ThreadLocal.h @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Cross-platform lightweight thread local data wrappers. */ + +#ifndef mozilla_TLS_h_ +#define mozilla_TLS_h_ + +#if defined(XP_WIN) +// This file will get included in any file that wants to add a profiler mark. +// In order to not bring together we could include windef.h and +// winbase.h which are sufficient to get the prototypes for the Tls* functions. +// # include +// # include +// Unfortunately, even including these headers causes us to add a bunch of ugly +// stuff to our namespace e.g #define CreateEvent CreateEventW +extern "C" { +__declspec(dllimport) void * __stdcall TlsGetValue(unsigned long); +__declspec(dllimport) int __stdcall TlsSetValue(unsigned long, void *); +__declspec(dllimport) unsigned long __stdcall TlsAlloc(); +} +#else +# include +# include +#endif + +#include "mozilla/Assertions.h" +#include "mozilla/Attributes.h" + +namespace mozilla { + +// sig_safe_t denotes an atomic type which can be read or stored in a single +// instruction. This means that data of this type is safe to be manipulated +// from a signal handler, or other similar asynchronous execution contexts. +#if defined(XP_WIN) +typedef unsigned long sig_safe_t; +#else +typedef sig_atomic_t sig_safe_t; +#endif + +/* + * Thread Local Storage helpers. + * + * Usage: + * + * Only static-storage-duration (e.g. global variables, or static class members) + * objects of this class should be instantiated. This class relies on + * zero-initialization, which is implicit for static-storage-duration objects. + * It doesn't have a custom default constructor, to avoid static initializers. + * + * API usage: + * + * // Create a TLS item + * mozilla::ThreadLocal tlsKey; + * if (!tlsKey.init()) { + * // deal with the error + * } + * + * // Set the TLS value + * tlsKey.set(123); + * + * // Get the TLS value + * int value = tlsKey.get(); + */ +template +class ThreadLocal +{ +#if defined(XP_WIN) + typedef unsigned long key_t; +#else + typedef pthread_key_t key_t; +#endif + + union Helper { + void* ptr; + T value; + }; + + public: + MOZ_WARN_UNUSED_RESULT inline bool init(); + + inline T get() const; + + inline bool set(const T value); + + bool initialized() const { + return inited; + } + + private: + key_t key; + bool inited; +}; + +template +inline bool +ThreadLocal::init() +{ + MOZ_STATIC_ASSERT(sizeof(T) <= sizeof(void *), + "mozilla::ThreadLocal can't be used for types larger than " + "a pointer"); + MOZ_ASSERT(!initialized()); +#ifdef XP_WIN + key = TlsAlloc(); + inited = key != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES +#else + inited = !pthread_key_create(&key, NULL); +#endif + return inited; +} + +template +inline T +ThreadLocal::get() const +{ + MOZ_ASSERT(initialized()); + Helper h; +#ifdef XP_WIN + h.ptr = TlsGetValue(key); +#else + h.ptr = pthread_getspecific(key); +#endif + return h.value; +} + +template +inline bool +ThreadLocal::set(const T value) +{ + MOZ_ASSERT(initialized()); + Helper h; + h.value = value; +#ifdef XP_WIN + return TlsSetValue(key, h.ptr); +#else + return !pthread_setspecific(key, h.ptr); +#endif +} + +} // namespace mozilla + +#endif // mozilla_TLS_h_ diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/TypeTraits.h b/scripting/javascript/spidermonkey-android/include/mozilla/TypeTraits.h new file mode 100644 index 0000000000..8f04e7a4ac --- /dev/null +++ b/scripting/javascript/spidermonkey-android/include/mozilla/TypeTraits.h @@ -0,0 +1,122 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Template-based metaprogramming and type-testing facilities. */ + +#ifndef mozilla_TypeTraits_h_ +#define mozilla_TypeTraits_h_ + +namespace mozilla { + +/* + * IsBaseOf allows to know whether a given class is derived from another. + * + * Consider the following class definitions: + * + * class A {}; + * class B : public A {}; + * class C {}; + * + * mozilla::IsBaseOf::value is true; + * mozilla::IsBaseOf::value is false; + */ +template +class IsBaseOf +{ + private: + static char test(Base* b); + static int test(...); + + public: + static const bool value = + sizeof(test(static_cast(0))) == sizeof(char); +}; + +/* + * IsConvertible determines whether a value of type From will implicitly convert + * to a value of type To. For example: + * + * struct A {}; + * struct B : public A {}; + * struct C {}; + * + * mozilla::IsConvertible::value is true; + * mozilla::IsConvertible::value is true; + * mozilla::IsConvertible::value is true; + * mozilla::IsConvertible::value is true; + * mozilla::IsConvertible::value is false; + * mozilla::IsConvertible::value is false; + * mozilla::IsConvertible::value is false; + * mozilla::IsConvertible::value is false. + * + * For obscure reasons, you can't use IsConvertible when the types being tested + * are related through private inheritance, and you'll get a compile error if + * you try. Just don't do it! + */ +template +struct IsConvertible +{ + private: + static From create(); + + template + static char test(To to); + + template + static int test(...); + + public: + static const bool value = + sizeof(test(create())) == sizeof(char); +}; + +/* + * Conditional selects a class between two, depending on a given boolean value. + * + * mozilla::Conditional::Type is A; + * mozilla::Conditional::Type is B; + */ +template +struct Conditional +{ + typedef A Type; +}; + +template +struct Conditional +{ + typedef B Type; +}; + +/* + * EnableIf is a struct containing a typedef of T if and only if B is true. + * + * mozilla::EnableIf::Type is int; + * mozilla::EnableIf::Type is a compile-time error. + * + * Use this template to implement SFINAE-style (Substitution Failure Is not An + * Error) requirements. For example, you might use it to impose a restriction + * on a template parameter: + * + * template + * class PodVector // vector optimized to store POD (memcpy-able) types + * { + * EnableIf, T>::Type* vector; + * size_t length; + * ... + * }; + */ +template +struct EnableIf +{}; + +template +struct EnableIf +{ + typedef T Type; +}; + +} /* namespace mozilla */ + +#endif /* mozilla_TypeTraits_h_ */ diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/Types.h b/scripting/javascript/spidermonkey-android/include/mozilla/Types.h index 6899719463..f803586ec1 100644 --- a/scripting/javascript/spidermonkey-android/include/mozilla/Types.h +++ b/scripting/javascript/spidermonkey-android/include/mozilla/Types.h @@ -1,41 +1,7 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=99 ft=cpp: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Code. - * - * The Initial Developer of the Original Code is - * The Mozilla Foundation - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* mfbt foundational types and macros. */ diff --git a/scripting/javascript/spidermonkey-android/include/mozilla/Util.h b/scripting/javascript/spidermonkey-android/include/mozilla/Util.h index edbe10d01b..735c067940 100644 --- a/scripting/javascript/spidermonkey-android/include/mozilla/Util.h +++ b/scripting/javascript/spidermonkey-android/include/mozilla/Util.h @@ -1,41 +1,7 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sw=4 et tw=99 ft=cpp: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Code. - * - * The Initial Developer of the Original Code is - * The Mozilla Foundation - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * Miscellaneous uncategorized functionality. Please add new functionality to @@ -54,54 +20,53 @@ namespace mozilla { /** - * DebugOnly contains a value of type T, but only in debug builds. In - * release builds, it does not contain a value. This helper is - * intended to be used along with ASSERT()-style macros, allowing one - * to write + * DebugOnly contains a value of type T, but only in debug builds. In release + * builds, it does not contain a value. This helper is intended to be used with + * MOZ_ASSERT()-style macros, allowing one to write: * - * DebugOnly check = Func(); - * ASSERT(check); + * DebugOnly check = func(); + * MOZ_ASSERT(check); * - * more concisely than declaring |check| conditional on #ifdef DEBUG, - * but also without allocating storage space for |check| in release - * builds. + * more concisely than declaring |check| conditional on #ifdef DEBUG, but also + * without allocating storage space for |check| in release builds. * - * DebugOnly instances can only be coerced to T in debug builds; in - * release builds, they don't have a value so type coercion is not - * well defined. + * DebugOnly instances can only be coerced to T in debug builds. In release + * builds they don't have a value, so type coercion is not well defined. */ -template +template struct DebugOnly { #ifdef DEBUG T value; - DebugOnly() {} - DebugOnly(const T& other) : value(other) {} - DebugOnly(const DebugOnly& other) : value(other.value) {} + DebugOnly() { } + DebugOnly(const T& other) : value(other) { } + DebugOnly(const DebugOnly& other) : value(other.value) { } DebugOnly& operator=(const T& rhs) { - value = rhs; - return *this; + value = rhs; + return *this; } void operator++(int) { - value++; + value++; } void operator--(int) { - value--; + value--; } + T *operator&() { return &value; } + operator T&() { return value; } operator const T&() const { return value; } T& operator->() { return value; } #else - DebugOnly() {} - DebugOnly(const T&) {} - DebugOnly(const DebugOnly&) {} + DebugOnly() { } + DebugOnly(const T&) { } + DebugOnly(const DebugOnly&) { } DebugOnly& operator=(const T&) { return *this; } - void operator++(int) {} - void operator--(int) {} + void operator++(int) { } + void operator--(int) { } #endif /* @@ -117,17 +82,16 @@ struct DebugOnly * bytes of alignment a given type needs. */ template -struct AlignmentFinder +class AlignmentFinder { -private: - struct Aligner - { - char c; - T t; - }; + struct Aligner + { + char c; + T t; + }; -public: - static const int alignment = sizeof(Aligner) - sizeof(T); + public: + static const size_t alignment = sizeof(Aligner) - sizeof(T); }; #define MOZ_ALIGNOF(T) mozilla::AlignmentFinder::alignment @@ -154,7 +118,8 @@ public: #endif /* - * AlignedElem is a structure whose alignment is guaranteed to be at least N bytes. + * AlignedElem is a structure whose alignment is guaranteed to be at least N + * bytes. * * We support 1, 2, 4, 8, and 16-bit alignment. */ @@ -169,31 +134,31 @@ struct AlignedElem; template<> struct AlignedElem<1> { - MOZ_ALIGNED_DECL(uint8_t elem, 1); + MOZ_ALIGNED_DECL(uint8_t elem, 1); }; template<> struct AlignedElem<2> { - MOZ_ALIGNED_DECL(uint8_t elem, 2); + MOZ_ALIGNED_DECL(uint8_t elem, 2); }; template<> struct AlignedElem<4> { - MOZ_ALIGNED_DECL(uint8_t elem, 4); + MOZ_ALIGNED_DECL(uint8_t elem, 4); }; template<> struct AlignedElem<8> { - MOZ_ALIGNED_DECL(uint8_t elem, 8); + MOZ_ALIGNED_DECL(uint8_t elem, 8); }; template<> struct AlignedElem<16> { - MOZ_ALIGNED_DECL(uint8_t elem, 16); + MOZ_ALIGNED_DECL(uint8_t elem, 16); }; /* @@ -206,28 +171,28 @@ struct AlignedElem<16> * false negatives when we cast from the char buffer to whatever type we've * constructed using the bytes. */ -template +template struct AlignedStorage { union U { - char bytes[nbytes]; - uint64_t _; + char bytes[nbytes]; + uint64_t _; } u; - const void *addr() const { return u.bytes; } - void *addr() { return u.bytes; } + const void* addr() const { return u.bytes; } + void* addr() { return u.bytes; } }; -template +template struct AlignedStorage2 { union U { - char bytes[sizeof(T)]; - uint64_t _; + char bytes[sizeof(T)]; + uint64_t _; } u; - const T *addr() const { return (const T *)u.bytes; } - T *addr() { return (T *)(void *)u.bytes; } + const T* addr() const { return reinterpret_cast(u.bytes); } + T* addr() { return static_cast(static_cast(u.bytes)); } }; /* @@ -241,16 +206,13 @@ struct AlignedStorage2 * N.B. GCC seems to miss some optimizations with Maybe and may generate extra * branches/loads/stores. Use with caution on hot paths. */ -template +template class Maybe { AlignedStorage2 storage; bool constructed; - T &asT() { return *storage.addr(); } - - explicit Maybe(const Maybe &other); - const Maybe &operator=(const Maybe &other); + T& asT() { return *storage.addr(); } public: Maybe() { constructed = false; } @@ -259,63 +221,67 @@ class Maybe bool empty() const { return !constructed; } void construct() { - MOZ_ASSERT(!constructed); - new(storage.addr()) T(); - constructed = true; + MOZ_ASSERT(!constructed); + new (storage.addr()) T(); + constructed = true; } - template - void construct(const T1 &t1) { - MOZ_ASSERT(!constructed); - new(storage.addr()) T(t1); - constructed = true; + template + void construct(const T1& t1) { + MOZ_ASSERT(!constructed); + new (storage.addr()) T(t1); + constructed = true; } - template - void construct(const T1 &t1, const T2 &t2) { - MOZ_ASSERT(!constructed); - new(storage.addr()) T(t1, t2); - constructed = true; + template + void construct(const T1& t1, const T2& t2) { + MOZ_ASSERT(!constructed); + new (storage.addr()) T(t1, t2); + constructed = true; } - template - void construct(const T1 &t1, const T2 &t2, const T3 &t3) { - MOZ_ASSERT(!constructed); - new(storage.addr()) T(t1, t2, t3); - constructed = true; + template + void construct(const T1& t1, const T2& t2, const T3& t3) { + MOZ_ASSERT(!constructed); + new (storage.addr()) T(t1, t2, t3); + constructed = true; } - template - void construct(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) { - MOZ_ASSERT(!constructed); - new(storage.addr()) T(t1, t2, t3, t4); - constructed = true; + template + void construct(const T1& t1, const T2& t2, const T3& t3, const T4& t4) { + MOZ_ASSERT(!constructed); + new (storage.addr()) T(t1, t2, t3, t4); + constructed = true; } - T *addr() { - MOZ_ASSERT(constructed); - return &asT(); + T* addr() { + MOZ_ASSERT(constructed); + return &asT(); } - T &ref() { - MOZ_ASSERT(constructed); - return asT(); + T& ref() { + MOZ_ASSERT(constructed); + return asT(); } - const T &ref() const { - MOZ_ASSERT(constructed); - return const_cast(this)->asT(); + const T& ref() const { + MOZ_ASSERT(constructed); + return const_cast(this)->asT(); } void destroy() { - ref().~T(); - constructed = false; + ref().~T(); + constructed = false; } void destroyIfConstructed() { - if (!empty()) - destroy(); + if (!empty()) + destroy(); } + + private: + Maybe(const Maybe& other) MOZ_DELETE; + const Maybe& operator=(const Maybe& other) MOZ_DELETE; }; /* @@ -324,12 +290,12 @@ class Maybe * set, the unsigned subtraction followed by right shift will produce -1, or * size_t(-1), instead of the real difference. */ -template +template MOZ_ALWAYS_INLINE size_t PointerRangeSize(T* begin, T* end) { - MOZ_ASSERT(end >= begin); - return (size_t(end) - size_t(begin)) / sizeof(T); + MOZ_ASSERT(end >= begin); + return (size_t(end) - size_t(begin)) / sizeof(T); } /* @@ -342,7 +308,7 @@ template size_t ArrayLength(T (&arr)[N]) { - return N; + return N; } /* @@ -354,7 +320,7 @@ template T* ArrayEnd(T (&arr)[N]) { - return arr + ArrayLength(arr); + return arr + ArrayLength(arr); } } /* namespace mozilla */ diff --git a/scripting/javascript/spidermonkey-android/lib/libjs_static.a.REMOVED.git-id b/scripting/javascript/spidermonkey-android/lib/libjs_static.a.REMOVED.git-id index cc066ffc9b..6f6b44ff18 100644 --- a/scripting/javascript/spidermonkey-android/lib/libjs_static.a.REMOVED.git-id +++ b/scripting/javascript/spidermonkey-android/lib/libjs_static.a.REMOVED.git-id @@ -1 +1 @@ -b55240db62f4497ae539c524d8a5ed2efb2a6b48 \ No newline at end of file +4b6a92efb0e694d8aee845c9c7fcd1c2e63adab6 \ No newline at end of file