diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index 1206acaddd3..86cc2b5c38f 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -531,6 +531,17 @@ AutoGCRooter::trace(JSTracer *trc) return; } + case OBJOBJHASHMAP: { + AutoObjectObjectHashMap::HashMapImpl &map = static_cast(this)->map; + for (AutoObjectObjectHashMap::Enum e(map); !e.empty(); e.popFront()) { + RawObject key = e.front().key; + MarkObjectRoot(trc, (RawObject *) &e.front().key, "AutoObjectObjectHashMap key"); + JS_ASSERT(key == e.front().key); + MarkObjectRoot(trc, &e.front().value, "AutoObjectObjectHashMap value"); + } + return; + } + case PROPDESC: { PropDesc::AutoRooter *rooter = static_cast(this); MarkValueRoot(trc, &rooter->pd->pd_, "PropDesc::AutoRooter pd"); diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 552acfda05c..0ed16a1b1b6 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -31,6 +31,7 @@ #include "jsalloc.h" #include "js/Vector.h" +#include "js/HashTable.h" /************************************************************************/ @@ -1041,7 +1042,7 @@ class JS_PUBLIC_API(AutoGCRooter) { *stackTop = down; } - /* Implemented in jsgc.cpp. */ + /* Implemented in gc/RootMarking.cpp. */ inline void trace(JSTracer *trc); static void traceAll(JSTracer *trc); static void traceAllWrappers(JSTracer *trc); @@ -1087,7 +1088,8 @@ class JS_PUBLIC_API(AutoGCRooter) { IONMASM = -28, /* js::ion::MacroAssembler */ IONALLOC = -29, /* js::ion::AutoTempAllocatorRooter */ WRAPVECTOR = -30, /* js::AutoWrapperVector */ - WRAPPER = -31 /* js::AutoWrapperRooter */ + WRAPPER = -31, /* js::AutoWrapperRooter */ + OBJOBJHASHMAP=-32 /* js::AutoObjectObjectHashMap */ }; private: @@ -1328,6 +1330,129 @@ class AutoVectorRooter : protected AutoGCRooter JS_DECL_USE_GUARD_OBJECT_NOTIFIER }; +template +class AutoHashMapRooter : protected AutoGCRooter +{ + private: + typedef js::HashMap HashMapImpl; + + public: + explicit AutoHashMapRooter(JSContext *cx, ptrdiff_t tag + JS_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoGCRooter(cx, tag), map(cx) + { + JS_GUARD_OBJECT_NOTIFIER_INIT; + } + + typedef Key KeyType; + typedef Value ValueType; + typedef typename HashMapImpl::Lookup Lookup; + typedef typename HashMapImpl::Ptr Ptr; + typedef typename HashMapImpl::AddPtr AddPtr; + + bool init(uint32_t len = 16) { + return map.init(len); + } + bool initialized() const { + return map.initialized(); + } + Ptr lookup(const Lookup &l) const { + return map.lookup(l); + } + void remove(Ptr p) { + map.remove(p); + } + AddPtr lookupForAdd(const Lookup &l) const { + return map.lookupForAdd(l); + } + + template + bool add(AddPtr &p, const KeyInput &k, const ValueInput &v) { + return map.add(k, v); + } + + bool add(AddPtr &p, const Key &k) { + return map.add(p, k); + } + + template + bool relookupOrAdd(AddPtr &p, const KeyInput &k, const ValueInput &v) { + return map.relookupOrAdd(p, k, v); + } + + typedef typename HashMapImpl::Range Range; + Range all() const { + return map.all(); + } + + typedef typename HashMapImpl::Enum Enum; + + void clear() { + map.clear(); + } + + void finish() { + map.finish(); + } + + bool empty() const { + return map.empty(); + } + + uint32_t count() const { + return map.count(); + } + + size_t capacity() const { + return map.capacity(); + } + + size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const { + return map.sizeOfExcludingThis(mallocSizeOf); + } + size_t sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const { + return map.sizeOfIncludingThis(mallocSizeOf); + } + + unsigned generation() const { + return map.generation(); + } + + /************************************************** Shorthand operations */ + + bool has(const Lookup &l) const { + return map.has(l); + } + + template + bool put(const KeyInput &k, const ValueInput &v) { + return map.put(k, v); + } + + template + bool putNew(const KeyInput &k, const ValueInput &v) { + return map.putNew(k, v); + } + + Ptr lookupWithDefault(const Key &k, const Value &defaultValue) { + return map.lookupWithDefault(k, defaultValue); + } + + void remove(const Lookup &l) { + map.remove(l); + } + + friend void AutoGCRooter::trace(JSTracer *trc); + + private: + AutoHashMapRooter(const AutoHashMapRooter &hmr) MOZ_DELETE; + AutoHashMapRooter &operator=(const AutoHashMapRooter &hmr) MOZ_DELETE; + + HashMapImpl map; + + JS_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + class AutoValueVector : public AutoVectorRooter { public: diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 591ecb3dd31..511c2e9cc7a 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -2097,12 +2097,12 @@ SetValueRangeToNull(Value *vec, size_t len) SetValueRangeToNull(vec, vec + len); } -class AutoObjectVector : public AutoVectorRooter +class AutoObjectVector : public AutoVectorRooter { public: explicit AutoObjectVector(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter(cx, OBJVECTOR) + : AutoVectorRooter(cx, OBJVECTOR) { JS_GUARD_OBJECT_NOTIFIER_INIT; } @@ -2110,12 +2110,12 @@ class AutoObjectVector : public AutoVectorRooter JS_DECL_USE_GUARD_OBJECT_NOTIFIER }; -class AutoStringVector : public AutoVectorRooter +class AutoStringVector : public AutoVectorRooter { public: explicit AutoStringVector(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter(cx, STRINGVECTOR) + : AutoVectorRooter(cx, STRINGVECTOR) { JS_GUARD_OBJECT_NOTIFIER_INIT; } @@ -2123,12 +2123,12 @@ class AutoStringVector : public AutoVectorRooter JS_DECL_USE_GUARD_OBJECT_NOTIFIER }; -class AutoShapeVector : public AutoVectorRooter +class AutoShapeVector : public AutoVectorRooter { public: explicit AutoShapeVector(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM) - : AutoVectorRooter(cx, SHAPEVECTOR) + : AutoVectorRooter(cx, SHAPEVECTOR) { JS_GUARD_OBJECT_NOTIFIER_INIT; } @@ -2138,24 +2138,37 @@ class AutoShapeVector : public AutoVectorRooter class AutoValueArray : public AutoGCRooter { - js::Value *start_; + RawValue *start_; unsigned length_; SkipRoot skip; public: - AutoValueArray(JSContext *cx, js::Value *start, unsigned length + AutoValueArray(JSContext *cx, RawValue *start, unsigned length JS_GUARD_OBJECT_NOTIFIER_PARAM) : AutoGCRooter(cx, VALARRAY), start_(start), length_(length), skip(cx, start, length) { JS_GUARD_OBJECT_NOTIFIER_INIT; } - Value *start() { return start_; } + RawValue *start() { return start_; } unsigned length() const { return length_; } JS_DECL_USE_GUARD_OBJECT_NOTIFIER }; +class AutoObjectObjectHashMap : public AutoHashMapRooter +{ + public: + explicit AutoObjectObjectHashMap(JSContext *cx + JS_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoHashMapRooter(cx, OBJOBJHASHMAP) + { + JS_GUARD_OBJECT_NOTIFIER_INIT; + } + + JS_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + /* * Allocation policy that uses JSRuntime::malloc_ and friends, so that * memory pressure is properly accounted for. This is suitable for