From b6490325aff7d2f619842c3fad66b10493282dcd Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Thu, 28 Mar 2013 13:37:22 -0700 Subject: [PATCH] Bug 777548 - Make non-cc-participant tracing indirect; r=smaug,billm,jst --- content/base/src/nsCCUncollectableMarker.cpp | 4 +- content/base/src/nsContentUtils.cpp | 3 +- content/xul/content/src/nsXULElement.cpp | 5 +- content/xul/content/src/nsXULElement.h | 7 +++ .../xul/document/src/nsXULPrototypeCache.cpp | 2 +- dom/base/nsGlobalWindow.cpp | 8 ++++ dom/base/nsGlobalWindow.h | 1 + dom/base/nsWrapperCache.h | 3 ++ dom/base/nsWrapperCacheInlines.h | 7 +++ dom/bindings/BindingUtils.h | 5 +- dom/plugins/base/nsJSNPRuntime.cpp | 7 +-- dom/workers/DOMBindingBase.cpp | 5 +- dom/workers/DOMBindingBase.h | 7 +++ dom/workers/EventListenerManager.cpp | 2 +- dom/workers/WorkerPrivate.cpp | 4 +- dom/workers/WorkerScope.cpp | 2 +- dom/workers/XMLHttpRequest.cpp | 4 +- dom/workers/XMLHttpRequestUpload.cpp | 2 +- js/public/GCAPI.h | 4 ++ js/src/builtin/TestingFunctions.cpp | 2 +- js/src/ctypes/CTypes.cpp | 18 +++---- js/src/jsapi.cpp | 42 +++++++++-------- js/src/jsapi.h | 47 ++++++++++++++++--- js/xpconnect/src/XPCJSRuntime.cpp | 2 +- js/xpconnect/src/XPCVariant.cpp | 6 +-- js/xpconnect/src/XPCWrappedJS.cpp | 2 +- js/xpconnect/src/XPCWrappedNative.cpp | 2 +- js/xpconnect/src/XPCWrappedNativeScope.cpp | 4 +- js/xpconnect/src/xpcprivate.h | 21 +++++---- 29 files changed, 149 insertions(+), 79 deletions(-) diff --git a/content/base/src/nsCCUncollectableMarker.cpp b/content/base/src/nsCCUncollectableMarker.cpp index c01d83443a2e..7414d7a5ee7f 100644 --- a/content/base/src/nsCCUncollectableMarker.cpp +++ b/content/base/src/nsCCUncollectableMarker.cpp @@ -419,9 +419,7 @@ TraceActiveWindowGlobal(const uint64_t& aId, nsGlobalWindow*& aWindow, void* aCl { if (aWindow->GetDocShell() && aWindow->IsOuterWindow()) { TraceClosure* closure = static_cast(aClosure); - if (JSObject* global = aWindow->FastGetGlobalJSObject()) { - JS_CallObjectTracer(closure->mTrc, global, "active window global"); - } + aWindow->TraceGlobalJSObject(closure->mTrc); #ifdef MOZ_XUL nsIDocument* doc = aWindow->GetExtantDoc(); if (doc && doc->IsXUL()) { diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 65419feb873f..4c0379d9ea2d 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -1647,7 +1647,8 @@ nsContentUtils::TraceSafeJSContext(JSTracer* aTrc) return; } if (JSObject* global = JS_GetGlobalObject(cx)) { - JS_CallObjectTracer(aTrc, global, "safe context"); + JS_CallObjectTracer(aTrc, &global, "safe context"); + MOZ_ASSERT(global == JS_GetGlobalObject(cx)); } } diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index 4bf49f321fb7..8cdea75cd93c 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -2340,10 +2340,7 @@ nsXULPrototypeElement::TraceAllScripts(JSTracer* aTrc) if (child->mType == nsXULPrototypeNode::eType_Element) { static_cast(child)->TraceAllScripts(aTrc); } else if (child->mType == nsXULPrototypeNode::eType_Script) { - JSScript* script = static_cast(child)->GetScriptObject(); - if (script) { - JS_CallScriptTracer(aTrc, script, "active window XUL prototype script"); - } + static_cast(child)->TraceScriptObject(aTrc); } } } diff --git a/content/xul/content/src/nsXULElement.h b/content/xul/content/src/nsXULElement.h index edaacd0f44a0..9fc895de55e8 100644 --- a/content/xul/content/src/nsXULElement.h +++ b/content/xul/content/src/nsXULElement.h @@ -241,6 +241,13 @@ public: return mScriptObject; } + void TraceScriptObject(JSTracer* aTrc) + { + if (mScriptObject) { + JS_CallScriptTracer(aTrc, &mScriptObject, "active window XUL prototype script"); + } + } + nsCOMPtr mSrcURI; uint32_t mLineNo; bool mSrcLoading; diff --git a/content/xul/document/src/nsXULPrototypeCache.cpp b/content/xul/document/src/nsXULPrototypeCache.cpp index 499b491ee231..92ae12c24f3c 100644 --- a/content/xul/document/src/nsXULPrototypeCache.cpp +++ b/content/xul/document/src/nsXULPrototypeCache.cpp @@ -660,7 +660,7 @@ static PLDHashOperator MarkScriptsInGC(nsIURI* aKey, CacheScriptEntry& aScriptEntry, void* aClosure) { JSTracer* trc = static_cast(aClosure); - JS_CallScriptTracer(trc, aScriptEntry.mScriptObject, + JS_CallScriptTracer(trc, &aScriptEntry.mScriptObject, "nsXULPrototypeCache script"); return PL_DHASH_NEXT; } diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index d5f2e1d4e7ba..5831b9f49352 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -1823,6 +1823,14 @@ nsGlobalWindow::GetGlobalJSObject() return FastGetGlobalJSObject(); } +void +nsGlobalWindow::TraceGlobalJSObject(JSTracer* aTrc) +{ + if (mJSObject) { + JS_CallObjectTracer(aTrc, &mJSObject, "active window global"); + } +} + bool nsGlobalWindow::WouldReuseInnerWindow(nsIDocument *aNewDocument) { diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 65b84d9311a1..067abd2aecd2 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -303,6 +303,7 @@ public: { return mJSObject; } + void TraceGlobalJSObject(JSTracer* aTrc); virtual nsresult EnsureScriptEnvironment(); diff --git a/dom/base/nsWrapperCache.h b/dom/base/nsWrapperCache.h index 0cbedca79a12..64fcb9f82e81 100644 --- a/dom/base/nsWrapperCache.h +++ b/dom/base/nsWrapperCache.h @@ -10,6 +10,7 @@ #include "mozilla/Assertions.h" #include "js/RootingAPI.h" +struct JSTracer; class JSObject; struct JSContext; class XPCWrappedNativeScope; @@ -189,6 +190,8 @@ private: (mWrapperPtrBits & WRAPPER_IS_DOM_BINDING); } + void TraceJSObjectFromBits(JSTracer *aTrc, const char *aName); + /** * If this bit is set then we're preserving the wrapper, which in effect ties * the lifetime of the JS object stored in the cache to the lifetime of the diff --git a/dom/base/nsWrapperCacheInlines.h b/dom/base/nsWrapperCacheInlines.h index c56b724de9ac..b2280ead7f98 100644 --- a/dom/base/nsWrapperCacheInlines.h +++ b/dom/base/nsWrapperCacheInlines.h @@ -8,6 +8,7 @@ #include "nsWrapperCache.h" #include "xpcpublic.h" +#include "jsapi.h" // We want to encode 3 bits into mWrapperPtrBits, so anything we store in it // needs to be aligned on 8 byte boundaries. @@ -56,4 +57,10 @@ nsWrapperCache::IsBlackAndDoesNotNeedTracing(nsISupports* aThis) return false; } +inline void +nsWrapperCache::TraceJSObjectFromBits(JSTracer* aTrc, const char* aName) +{ + JS_CallMaskedObjectTracer(aTrc, &mWrapperPtrBits, kWrapperBitMask, aName); +} + #endif /* nsWrapperCache_h___ */ diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index bf17550f6f74..869da38e728b 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -256,9 +256,8 @@ TraceProtoAndIfaceCache(JSTracer* trc, JSObject* obj) return; JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(obj); for (size_t i = 0; i < kProtoAndIfaceCacheCount; ++i) { - JSObject* proto = protoAndIfaceArray[i]; - if (proto) { - JS_CallObjectTracer(trc, proto, "protoAndIfaceArray[i]"); + if (protoAndIfaceArray[i]) { + JS_CallObjectTracer(trc, &protoAndIfaceArray[i], "protoAndIfaceArray[i]"); } } } diff --git a/dom/plugins/base/nsJSNPRuntime.cpp b/dom/plugins/base/nsJSNPRuntime.cpp index f598e57a96cf..f0c7d4766623 100644 --- a/dom/plugins/base/nsJSNPRuntime.cpp +++ b/dom/plugins/base/nsJSNPRuntime.cpp @@ -2172,10 +2172,11 @@ NPObjectMember_Trace(JSTracer *trc, JSObject *obj) // Our NPIdentifier is not always interned, so we must root it explicitly. jsid id = NPIdentifierToJSId(memberPrivate->methodName); - JS_CallIdTracer(trc, id, "NPObjectMemberPrivate.methodName"); + JS_CallIdTracer(trc, &id, "NPObjectMemberPrivate.methodName"); + memberPrivate->methodName = JSIdToNPIdentifier(id); if (!JSVAL_IS_PRIMITIVE(memberPrivate->fieldValue)) { - JS_CallValueTracer(trc, memberPrivate->fieldValue, + JS_CallValueTracer(trc, &memberPrivate->fieldValue, "NPObject Member => fieldValue"); } @@ -2183,7 +2184,7 @@ NPObjectMember_Trace(JSTracer *trc, JSObject *obj) // NPObject, so make sure to mark the NPObject wrapper to keep the // NPObject alive as long as this NPObjectMember is alive. if (memberPrivate->npobjWrapper) { - JS_CallObjectTracer(trc, memberPrivate->npobjWrapper, + JS_CallObjectTracer(trc, &memberPrivate->npobjWrapper, "NPObject Member => npobjWrapper"); } } diff --git a/dom/workers/DOMBindingBase.cpp b/dom/workers/DOMBindingBase.cpp index 17285a55d17c..cfe7872f22b1 100644 --- a/dom/workers/DOMBindingBase.cpp +++ b/dom/workers/DOMBindingBase.cpp @@ -39,10 +39,7 @@ NS_INTERFACE_MAP_END void DOMBindingBase::_trace(JSTracer* aTrc) { - JSObject* obj = GetJSObject(); - if (obj) { - JS_CallObjectTracer(aTrc, obj, "cached wrapper"); - } + TraceJSObject(aTrc, "cached wrapper"); } void diff --git a/dom/workers/DOMBindingBase.h b/dom/workers/DOMBindingBase.h index 256d5b6724af..96edede365d0 100644 --- a/dom/workers/DOMBindingBase.h +++ b/dom/workers/DOMBindingBase.h @@ -46,6 +46,13 @@ public: JSContext* GetJSContext() const; + void + TraceJSObject(JSTracer* aTrc, const char* aName) + { + if (GetJSObject()) + TraceJSObjectFromBits(aTrc, aName); + } + #ifdef DEBUG JSObject* GetJSObject() const; diff --git a/dom/workers/EventListenerManager.cpp b/dom/workers/EventListenerManager.cpp index c9aa166c82d7..144b24af7089 100644 --- a/dom/workers/EventListenerManager.cpp +++ b/dom/workers/EventListenerManager.cpp @@ -185,7 +185,7 @@ EventListenerManager::TraceInternal(JSTracer* aTrc) const listenerElem; listenerElem = listenerElem->getNext()) { JS_CallObjectTracer(aTrc, - listenerElem->mListener, + &const_cast(listenerElem)->mListener, "EventListenerManager listener object"); } } diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 64f57b331b56..9f6a290a1984 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -3258,10 +3258,10 @@ WorkerPrivate::TraceInternal(JSTracer* aTrc) for (uint32_t index = 0; index < mTimeouts.Length(); index++) { TimeoutInfo* info = mTimeouts[index]; - JS_CallValueTracer(aTrc, info->mTimeoutVal, + JS_CallValueTracer(aTrc, &info->mTimeoutVal, "WorkerPrivate timeout value"); for (uint32_t index2 = 0; index2 < info->mExtraArgVals.Length(); index2++) { - JS_CallValueTracer(aTrc, info->mExtraArgVals[index2], + JS_CallValueTracer(aTrc, &info->mExtraArgVals[index2], "WorkerPrivate timeout extra argument value"); } } diff --git a/dom/workers/WorkerScope.cpp b/dom/workers/WorkerScope.cpp index eb9dd050c939..7affa98e1895 100644 --- a/dom/workers/WorkerScope.cpp +++ b/dom/workers/WorkerScope.cpp @@ -128,7 +128,7 @@ protected: _trace(JSTracer* aTrc) MOZ_OVERRIDE { for (int32_t i = 0; i < SLOT_COUNT; i++) { - JS_CallValueTracer(aTrc, mSlots[i], "WorkerGlobalScope instance slot"); + JS_CallValueTracer(aTrc, &mSlots[i], "WorkerGlobalScope instance slot"); } mWorker->TraceInternal(aTrc); EventTarget::_trace(aTrc); diff --git a/dom/workers/XMLHttpRequest.cpp b/dom/workers/XMLHttpRequest.cpp index 201b283a374e..91d9a2bbe1ce 100644 --- a/dom/workers/XMLHttpRequest.cpp +++ b/dom/workers/XMLHttpRequest.cpp @@ -1421,9 +1421,9 @@ void XMLHttpRequest::_trace(JSTracer* aTrc) { if (mUpload) { - JS_CallObjectTracer(aTrc, mUpload->GetJSObject(), "mUpload"); + mUpload->TraceJSObject(aTrc, "mUpload"); } - JS_CallValueTracer(aTrc, mStateData.mResponse, "mResponse"); + JS_CallValueTracer(aTrc, &mStateData.mResponse, "mResponse"); XMLHttpRequestEventTarget::_trace(aTrc); } diff --git a/dom/workers/XMLHttpRequestUpload.cpp b/dom/workers/XMLHttpRequestUpload.cpp index eb475da497b4..289a112e91a2 100644 --- a/dom/workers/XMLHttpRequestUpload.cpp +++ b/dom/workers/XMLHttpRequestUpload.cpp @@ -23,7 +23,7 @@ void XMLHttpRequestUpload::_trace(JSTracer* aTrc) { if (mXHR) { - JS_CallObjectTracer(aTrc, mXHR->GetJSObject(), "mXHR"); + mXHR->TraceJSObject(aTrc, "mXHR"); } XMLHttpRequestEventTarget::_trace(aTrc); } diff --git a/js/public/GCAPI.h b/js/public/GCAPI.h index a69b567f65e2..1b0036116c3e 100644 --- a/js/public/GCAPI.h +++ b/js/public/GCAPI.h @@ -239,6 +239,10 @@ class ObjectPtr return *this; } + void trace(JSTracer *trc, const char *name) { + JS_CallObjectTracer(trc, &value, name); + } + JSObject &operator*() const { return *value; } JSObject *operator->() const { return value; } operator JSObject *() const { return value; } diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index d469f9e090e4..ba2f0a2abd41 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -715,7 +715,7 @@ CountHeap(JSContext *cx, unsigned argc, jsval *vp) if (startValue.isUndefined()) { JS_TraceRuntime(&countTracer.base); } else { - JS_CallValueTracer(&countTracer.base, startValue, "root"); + JS_CallValueTracer(&countTracer.base, startValue.address(), "root"); } counter = 0; diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp index 8ced194b1a69..fb20a1f1ab28 100644 --- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -3326,8 +3326,10 @@ CType::Trace(JSTracer* trc, JSObject* obj) FieldInfoHash* fields = static_cast(JSVAL_TO_PRIVATE(slot)); for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) { - JS_CallStringTracer(trc, r.front().key, "fieldName"); - JS_CallObjectTracer(trc, r.front().value.mType, "fieldType"); + JSString *key = r.front().key; + JS_CallStringTracer(trc, &key, "fieldName"); + JS_ASSERT(key == r.front().key); + JS_CallObjectTracer(trc, &r.front().value.mType, "fieldType"); } break; @@ -3342,10 +3344,10 @@ CType::Trace(JSTracer* trc, JSObject* obj) JS_ASSERT(fninfo); // Identify our objects to the tracer. - JS_CallObjectTracer(trc, fninfo->mABI, "abi"); - JS_CallObjectTracer(trc, fninfo->mReturnType, "returnType"); + JS_CallObjectTracer(trc, &fninfo->mABI, "abi"); + JS_CallObjectTracer(trc, &fninfo->mReturnType, "returnType"); for (size_t i = 0; i < fninfo->mArgTypes.length(); ++i) - JS_CallObjectTracer(trc, fninfo->mArgTypes[i], "argType"); + JS_CallObjectTracer(trc, &fninfo->mArgTypes[i], "argType"); break; } @@ -6078,10 +6080,10 @@ CClosure::Trace(JSTracer* trc, JSObject* obj) // Identify our objects to the tracer. (There's no need to identify // 'closureObj', since that's us.) - JS_CallObjectTracer(trc, cinfo->typeObj, "typeObj"); - JS_CallObjectTracer(trc, cinfo->jsfnObj, "jsfnObj"); + JS_CallObjectTracer(trc, &cinfo->typeObj, "typeObj"); + JS_CallObjectTracer(trc, &cinfo->jsfnObj, "jsfnObj"); if (cinfo->thisObj) - JS_CallObjectTracer(trc, cinfo->thisObj, "thisObj"); + JS_CallObjectTracer(trc, &cinfo->thisObj, "thisObj"); } void diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index b83324882f11..2782cd4cc94d 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -2477,43 +2477,47 @@ JS_SetExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data) } JS_PUBLIC_API(void) -JS_CallValueTracer(JSTracer *trc, Value valueArg, const char *name) +JS_CallValueTracer(JSTracer *trc, Value *valuep, const char *name) { - Value value = valueArg; - MarkValueUnbarriered(trc, &value, name); - JS_ASSERT(value == valueArg); + MarkValueUnbarriered(trc, valuep, name); } JS_PUBLIC_API(void) -JS_CallIdTracer(JSTracer *trc, jsid idArg, const char *name) +JS_CallIdTracer(JSTracer *trc, jsid *idp, const char *name) { - jsid id = idArg; - MarkIdUnbarriered(trc, &id, name); - JS_ASSERT(id == idArg); + MarkIdUnbarriered(trc, idp, name); } JS_PUBLIC_API(void) -JS_CallObjectTracer(JSTracer *trc, JSObject *objArg, const char *name) +JS_CallObjectTracer(JSTracer *trc, JSObject **objp, const char *name) { - JSObject *obj = objArg; + MarkObjectUnbarriered(trc, objp, name); +} + +JS_PUBLIC_API(void) +JS_CallMaskedObjectTracer(JSTracer *trc, uintptr_t *objp, uintptr_t flagMask, const char *name) +{ + uintptr_t flags = *objp & flagMask; + JSObject *obj = reinterpret_cast(*objp & ~flagMask); + if (!obj) + return; + + JS_SET_TRACING_LOCATION(trc, (void*)objp); MarkObjectUnbarriered(trc, &obj, name); - JS_ASSERT(obj == objArg); + + *objp = uintptr_t(obj) | flags; } JS_PUBLIC_API(void) -JS_CallStringTracer(JSTracer *trc, JSString *strArg, const char *name) +JS_CallStringTracer(JSTracer *trc, JSString **strp, const char *name) { - JSString *str = strArg; - MarkStringUnbarriered(trc, &str, name); - JS_ASSERT(str == strArg); + MarkStringUnbarriered(trc, strp, name); } JS_PUBLIC_API(void) -JS_CallScriptTracer(JSTracer *trc, JSScript *scriptArg, const char *name) +JS_CallScriptTracer(JSTracer *trc, JSScript **scriptp, const char *name) { - JSScript *script = scriptArg; - MarkScriptUnbarriered(trc, &script, name); - JS_ASSERT(script == scriptArg); + MarkScriptUnbarriered(trc, scriptp, name); } JS_PUBLIC_API(void) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index d655e7255956..eb656e43865c 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -907,8 +907,8 @@ typedef JSBool /* * Function type for trace operation of the class called to enumerate all * traceable things reachable from obj's private data structure. For each such - * thing, a trace implementation must call one of the |JS_CallTracer| - * variants on the thing. + * thing, a trace implementation must call one of the JS_Call*Tracer variants + * on the thing. * * JSTraceOp implementation can assume that no other threads mutates object * state. It must not change state of the object or corresponding native @@ -2511,24 +2511,57 @@ struct JSTracer { # define JS_SET_TRACING_NAME(trc, name) \ JS_SET_TRACING_DETAILS(trc, NULL, name, (size_t)-1) +/* + * The JS_Call*Tracer family of functions traces the given GC thing reference. + * This performs the tracing action configured on the given JSTracer: + * typically calling the JSTracer::callback or marking the thing as live. + * + * The argument to JS_Call*Tracer is an in-out param: when the function + * returns, the garbage collector might have moved the GC thing. In this case, + * the reference passed to JS_Call*Tracer will be updated to the object's new + * location. Callers of this method are responsible for updating any state + * that is dependent on the object's address. For example, if the object's + * address is used as a key in a hashtable, then the object must be removed + * and re-inserted with the correct hash. + */ extern JS_PUBLIC_API(void) -JS_CallValueTracer(JSTracer *trc, JS::Value value, const char *name); +JS_CallValueTracer(JSTracer *trc, JS::Value *valuep, const char *name); extern JS_PUBLIC_API(void) -JS_CallIdTracer(JSTracer *trc, jsid id, const char *name); +JS_CallIdTracer(JSTracer *trc, jsid *idp, const char *name); extern JS_PUBLIC_API(void) -JS_CallObjectTracer(JSTracer *trc, JSObject *obj, const char *name); +JS_CallObjectTracer(JSTracer *trc, JSObject **objp, const char *name); extern JS_PUBLIC_API(void) -JS_CallStringTracer(JSTracer *trc, JSString *str, const char *name); +JS_CallStringTracer(JSTracer *trc, JSString **strp, const char *name); extern JS_PUBLIC_API(void) -JS_CallScriptTracer(JSTracer *trc, JSScript *script, const char *name); +JS_CallScriptTracer(JSTracer *trc, JSScript **scriptp, const char *name); extern JS_PUBLIC_API(void) JS_CallGenericTracer(JSTracer *trc, void *gcthing, const char *name); +template +inline void +JS_CallHashSetObjectTracer(JSTracer *trc, HashSetEnum &e, JSObject *const &key, const char *name) +{ + JSObject *updated = key; + JS_SET_TRACING_LOCATION(trc, reinterpret_cast(&const_cast(key))); + JS_CallObjectTracer(trc, &updated, name); + if (updated != key) + e.rekeyFront(key, updated); +} + +/* + * The JS_CallMaskedObjectTracer variant traces a JSObject* that is stored + * with flags embedded in the low bits of the word. The flagMask parameter + * expects |*objp & flagMask| to yield the flags with the pointer value + * stripped and |*objp & ~flagMask| to yield a valid GC pointer. + */ +extern JS_PUBLIC_API(void) +JS_CallMaskedObjectTracer(JSTracer *trc, uintptr_t *objp, uintptr_t flagMask, const char *name); + /* * API for JSTraceCallback implementations. */ diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index f8d9b84245ee..822053c5796b 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -430,7 +430,7 @@ void XPCJSRuntime::TraceXPConnectRoots(JSTracer *trc) while (JSContext *acx = JS_ContextIterator(GetJSRuntime(), &iter)) { MOZ_ASSERT(js::HasUnrootedGlobal(acx)); if (JSObject *global = JS_GetGlobalObject(acx)) - JS_CallObjectTracer(trc, global, "XPC global object"); + JS_CallObjectTracer(trc, &global, "XPC global object"); } XPCAutoLock lock(mMapLock); diff --git a/js/xpconnect/src/XPCVariant.cpp b/js/xpconnect/src/XPCVariant.cpp index 6a03bffadf5c..a746669e77cc 100644 --- a/js/xpconnect/src/XPCVariant.cpp +++ b/js/xpconnect/src/XPCVariant.cpp @@ -65,11 +65,9 @@ XPCTraceableVariant::~XPCTraceableVariant() void XPCTraceableVariant::TraceJS(JSTracer* trc) { - jsval val = GetJSValPreserveColor(); - - MOZ_ASSERT(JSVAL_IS_TRACEABLE(val)); + MOZ_ASSERT(JSVAL_IS_TRACEABLE(mJSVal)); JS_SET_TRACING_DETAILS(trc, GetTraceName, this, 0); - JS_CallValueTracer(trc, val, "XPCTraceableVariant::mJSVal"); + JS_CallValueTracer(trc, &mJSVal, "XPCTraceableVariant::mJSVal"); } // static diff --git a/js/xpconnect/src/XPCWrappedJS.cpp b/js/xpconnect/src/XPCWrappedJS.cpp index 4af7e104cb20..637cfb6fe4d4 100644 --- a/js/xpconnect/src/XPCWrappedJS.cpp +++ b/js/xpconnect/src/XPCWrappedJS.cpp @@ -214,7 +214,7 @@ nsXPCWrappedJS::TraceJS(JSTracer* trc) { NS_ASSERTION(mRefCnt >= 2 && IsValid(), "must be strongly referenced"); JS_SET_TRACING_DETAILS(trc, GetTraceName, this, 0); - JS_CallObjectTracer(trc, GetJSObjectPreserveColor(), "nsXPCWrappedJS::mJSObj"); + JS_CallObjectTracer(trc, &mJSObj, "nsXPCWrappedJS::mJSObj"); } // static diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index a43b33e94e97..beef9d9f22ab 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -3581,7 +3581,7 @@ void XPCJSObjectHolder::TraceJS(JSTracer *trc) { JS_SET_TRACING_DETAILS(trc, GetTraceName, this, 0); - JS_CallObjectTracer(trc, mJSObj, "XPCJSObjectHolder::mJSObj"); + JS_CallObjectTracer(trc, &mJSObj, "XPCJSObjectHolder::mJSObj"); } // static diff --git a/js/xpconnect/src/XPCWrappedNativeScope.cpp b/js/xpconnect/src/XPCWrappedNativeScope.cpp index ba4f05a0c8b9..5b827f53b127 100644 --- a/js/xpconnect/src/XPCWrappedNativeScope.cpp +++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp @@ -402,8 +402,8 @@ XPCWrappedNativeScope::TraceWrappedNativesInAllScopes(JSTracer* trc, XPCJSRuntim for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) { cur->mWrappedNativeMap->Enumerate(WrappedNativeJSGCThingTracer, trc); if (cur->mDOMExpandoSet) { - for (DOMExpandoSet::Range r = cur->mDOMExpandoSet->all(); !r.empty(); r.popFront()) - JS_CallObjectTracer(trc, r.front(), "DOM expando object"); + for (DOMExpandoSet::Enum e(*cur->mDOMExpandoSet); !e.empty(); e.popFront()) + JS_CallHashSetObjectTracer(trc, e, e.front(), "DOM expando object"); } } } diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h index 228d52807b51..127d7b5be4d4 100644 --- a/js/xpconnect/src/xpcprivate.h +++ b/js/xpconnect/src/xpcprivate.h @@ -1617,11 +1617,10 @@ public: TraceWrappedNativesInAllScopes(JSTracer* trc, XPCJSRuntime* rt); void TraceSelf(JSTracer *trc) { - JSObject *obj = GetGlobalJSObjectPreserveColor(); - MOZ_ASSERT(obj); - JS_CallObjectTracer(trc, obj, "XPCWrappedNativeScope::mGlobalJSObject"); + MOZ_ASSERT(mGlobalJSObject); + mGlobalJSObject.trace(trc, "XPCWrappedNativeScope::mGlobalJSObject"); if (mXBLScope) - JS_CallObjectTracer(trc, mXBLScope, "XPCWrappedNativeScope::mXBLScope"); + mXBLScope.trace(trc, "XPCWrappedNativeScope::mXBLScope"); } static void @@ -2428,7 +2427,7 @@ public: void TraceSelf(JSTracer *trc) { if (mJSProtoObject) - JS_CallObjectTracer(trc, mJSProtoObject, "XPCWrappedNativeProto::mJSProtoObject"); + mJSProtoObject.trace(trc, "XPCWrappedNativeProto::mJSProtoObject"); } void TraceInside(JSTracer *trc) { @@ -2826,9 +2825,7 @@ public: GetProto()->TraceSelf(trc); else GetScope()->TraceSelf(trc); - JSObject* wrapper = GetWrapperPreserveColor(); - if (wrapper) - JS_CallObjectTracer(trc, wrapper, "XPCWrappedNative::mWrapper"); + TraceWrapper(trc); if (mFlatJSObject && mFlatJSObject != INVALID_OBJECT && JS_IsGlobalObject(mFlatJSObject)) { @@ -2847,7 +2844,7 @@ public: // normally somebody else is doing that. Be careful not to trace the // bogus INVALID_OBJECT value we can have during init, though. if (mFlatJSObject && mFlatJSObject != INVALID_OBJECT) { - JS_CallObjectTracer(trc, mFlatJSObject, + JS_CallObjectTracer(trc, &mFlatJSObject, "XPCWrappedNative::mFlatJSObject"); } } @@ -2902,6 +2899,12 @@ public: mWrapperWord = newval; } + void TraceWrapper(JSTracer *trc) + { + JS_CallMaskedObjectTracer(trc, reinterpret_cast(&mWrapperWord), + (uintptr_t)FLAG_MASK, "XPCWrappedNative::mWrapper"); + } + // Returns the relevant same-compartment security if applicable, or // mFlatJSObject otherwise. //