diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 08e3b2cd0f6..0dd9041a169 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -334,7 +334,9 @@ class ProtoAndIfaceCache void Trace(JSTracer* aTracer) { for (size_t i = 0; i < ArrayLength(*this); ++i) { - JS::TraceNullableEdge(aTracer, &(*this)[i], "protoAndIfaceCache[i]"); + if ((*this)[i]) { + JS_CallObjectTracer(aTracer, &(*this)[i], "protoAndIfaceCache[i]"); + } } } @@ -393,7 +395,9 @@ class ProtoAndIfaceCache Page* p = mPages[i]; if (p) { for (size_t j = 0; j < ArrayLength(*p); ++j) { - JS::TraceNullableEdge(trc, &(*p)[j], "protoAndIfaceCache[i]"); + if ((*p)[j]) { + JS_CallObjectTracer(trc, &(*p)[j], "protoAndIfaceCache[i]"); + } } } } diff --git a/dom/plugins/base/nsJSNPRuntime.cpp b/dom/plugins/base/nsJSNPRuntime.cpp index febfa3e1b08..26614b317fe 100644 --- a/dom/plugins/base/nsJSNPRuntime.cpp +++ b/dom/plugins/base/nsJSNPRuntime.cpp @@ -288,7 +288,9 @@ TraceJSObjWrappers(JSTracer *trc, void *data) nsJSObjWrapperKey key = e.front().key(); JS_CallUnbarrieredObjectTracer(trc, &key.mJSObj, "sJSObjWrappers key object"); nsJSObjWrapper *wrapper = e.front().value(); - JS::TraceNullableEdge(trc, &wrapper->mJSObj, "sJSObjWrappers wrapper object"); + if (wrapper->mJSObj) { + JS_CallObjectTracer(trc, &wrapper->mJSObj, "sJSObjWrappers wrapper object"); + } if (key != e.front().key()) { e.rekeyFront(key); } @@ -2258,16 +2260,21 @@ NPObjectMember_Trace(JSTracer *trc, JSObject *obj) if (!memberPrivate) return; - // Our NPIdentifier is not always interned, so we must trace it. - JS::TraceEdge(trc, &memberPrivate->methodName, "NPObjectMemberPrivate.methodName"); + // Our NPIdentifier is not always interned, so we must root it explicitly. + JS_CallIdTracer(trc, &memberPrivate->methodName, "NPObjectMemberPrivate.methodName"); - JS::TraceEdge(trc, &memberPrivate->fieldValue, "NPObject Member => fieldValue"); + if (!memberPrivate->fieldValue.isPrimitive()) { + JS_CallValueTracer(trc, &memberPrivate->fieldValue, + "NPObject Member => fieldValue"); + } // There's no strong reference from our private data to the // NPObject, so make sure to mark the NPObject wrapper to keep the // NPObject alive as long as this NPObjectMember is alive. - JS::TraceNullableEdge(trc, &memberPrivate->npobjWrapper, + if (memberPrivate->npobjWrapper) { + JS_CallObjectTracer(trc, &memberPrivate->npobjWrapper, "NPObject Member => npobjWrapper"); + } } static bool diff --git a/dom/workers/XMLHttpRequest.cpp b/dom/workers/XMLHttpRequest.cpp index 81ca75e5599..7a157de3956 100644 --- a/dom/workers/XMLHttpRequest.cpp +++ b/dom/workers/XMLHttpRequest.cpp @@ -559,8 +559,8 @@ public: private: virtual void trace(JSTracer* aTrc) { - JS::TraceEdge(aTrc, &mStateData->mResponse, - "XMLHttpRequest::StateData::mResponse"); + JS_CallValueTracer(aTrc, &mStateData->mResponse, + "XMLHttpRequest::StateData::mResponse"); } }; diff --git a/dom/xul/nsXULElement.h b/dom/xul/nsXULElement.h index 67665561d19..9a4dd8ac79b 100644 --- a/dom/xul/nsXULElement.h +++ b/dom/xul/nsXULElement.h @@ -249,7 +249,9 @@ public: void TraceScriptObject(JSTracer* aTrc) { - JS::TraceNullableEdge(aTrc, &mScriptObject, "active window XUL prototype script"); + if (mScriptObject) { + JS_CallScriptTracer(aTrc, &mScriptObject, "active window XUL prototype script"); + } } void Trace(const TraceCallbacks& aCallbacks, void* aClosure) diff --git a/dom/xul/nsXULPrototypeCache.cpp b/dom/xul/nsXULPrototypeCache.cpp index 9691ef5760a..b4867d51bfb 100644 --- a/dom/xul/nsXULPrototypeCache.cpp +++ b/dom/xul/nsXULPrototypeCache.cpp @@ -630,7 +630,7 @@ static PLDHashOperator MarkScriptsInGC(nsIURI* aKey, JS::Heap& aScript, void* aClosure) { JSTracer* trc = static_cast(aClosure); - JS::TraceEdge(trc, &aScript, "nsXULPrototypeCache script"); + JS_CallScriptTracer(trc, &aScript, "nsXULPrototypeCache script"); return PL_DHASH_NEXT; } diff --git a/js/ipc/JavaScriptShared.cpp b/js/ipc/JavaScriptShared.cpp index df3383145b8..18131a2f561 100644 --- a/js/ipc/JavaScriptShared.cpp +++ b/js/ipc/JavaScriptShared.cpp @@ -35,8 +35,10 @@ IdToObjectMap::init() void IdToObjectMap::trace(JSTracer* trc) { - for (Table::Range r(table_.all()); !r.empty(); r.popFront()) - JS::TraceEdge(trc, &r.front().value(), "ipc-object"); + for (Table::Range r(table_.all()); !r.empty(); r.popFront()) { + DebugOnly prior = r.front().value().get(); + JS_CallObjectTracer(trc, &r.front().value(), "ipc-object"); + } } void diff --git a/js/public/TracingAPI.h b/js/public/TracingAPI.h index 0806d43961e..08ced681851 100644 --- a/js/public/TracingAPI.h +++ b/js/public/TracingAPI.h @@ -281,29 +281,40 @@ JSTracer::asCallbackTracer() return static_cast(this); } -namespace JS { - -// The JS::TraceEdge 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 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::TraceEdge 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::TraceEdge will be updated to the thing'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. +// 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::Heap* valuep, const char* name); + +extern JS_PUBLIC_API(void) +JS_CallIdTracer(JSTracer* trc, JS::Heap* idp, const char* name); + +extern JS_PUBLIC_API(void) +JS_CallObjectTracer(JSTracer* trc, JS::Heap* objp, const char* name); + +extern JS_PUBLIC_API(void) +JS_CallStringTracer(JSTracer* trc, JS::Heap* strp, const char* name); + +extern JS_PUBLIC_API(void) +JS_CallScriptTracer(JSTracer* trc, JS::Heap* scriptp, const char* name); + +extern JS_PUBLIC_API(void) +JS_CallFunctionTracer(JSTracer* trc, JS::Heap* funp, const char* name); + +namespace JS { template extern JS_PUBLIC_API(void) TraceEdge(JSTracer* trc, JS::Heap* edgep, const char* name); - -// As with JS::TraceEdge, but checks if *edgep is a nullptr before proceeding. -// Note that edgep itself must always be non-null. -template -extern JS_PUBLIC_API(void) -TraceNullableEdge(JSTracer* trc, JS::Heap* edgep, const char* name); - } // namespace JS // The following JS_CallUnbarriered*Tracer functions should only be called where diff --git a/js/src/ctypes/CTypes.cpp b/js/src/ctypes/CTypes.cpp index 9a6b391256b..d9489f0bad2 100644 --- a/js/src/ctypes/CTypes.cpp +++ b/js/src/ctypes/CTypes.cpp @@ -4106,10 +4106,10 @@ CType::Trace(JSTracer* trc, JSObject* obj) MOZ_ASSERT(fninfo); // Identify our objects to the tracer. - JS::TraceEdge(trc, &fninfo->mABI, "abi"); - JS::TraceEdge(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::TraceEdge(trc, &fninfo->mArgTypes[i], "argType"); + JS_CallObjectTracer(trc, &fninfo->mArgTypes[i], "argType"); break; } @@ -6904,10 +6904,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::TraceEdge(trc, &cinfo->typeObj, "typeObj"); - JS::TraceEdge(trc, &cinfo->jsfnObj, "jsfnObj"); + JS_CallObjectTracer(trc, &cinfo->typeObj, "typeObj"); + JS_CallObjectTracer(trc, &cinfo->jsfnObj, "jsfnObj"); if (cinfo->thisObj) - JS::TraceEdge(trc, &cinfo->thisObj, "thisObj"); + JS_CallObjectTracer(trc, &cinfo->thisObj, "thisObj"); } void diff --git a/js/src/ctypes/CTypes.h b/js/src/ctypes/CTypes.h index ef78fe7f7b5..728baf9c6c8 100644 --- a/js/src/ctypes/CTypes.h +++ b/js/src/ctypes/CTypes.h @@ -231,7 +231,7 @@ struct FieldInfo size_t mOffset; // offset of the field in the struct, in bytes void trace(JSTracer* trc) { - JS::TraceEdge(trc, &mType, "fieldType"); + JS_CallObjectTracer(trc, &mType, "fieldType"); } }; diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 6bff25c5c35..2627b12cc9a 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -405,15 +405,6 @@ JS::TraceEdge(JSTracer* trc, JS::Heap* thingp, const char* name) DispatchToTracer(trc, ConvertToBase(thingp->unsafeGet()), name); } -template -JS_PUBLIC_API(void) -JS::TraceNullableEdge(JSTracer* trc, JS::Heap* thingp, const char* name) -{ - MOZ_ASSERT(thingp); - if (InternalGCMethods::isMarkable(thingp->get())) - DispatchToTracer(trc, ConvertToBase(thingp->unsafeGet()), name); -} - template void js::TraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, const char* name) @@ -492,6 +483,7 @@ js::TraceRootRange(JSTracer* trc, size_t len, T* vec, const char* name) // Instantiate a copy of the Tracing templates for each derived type. #define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(type) \ template void js::TraceEdge(JSTracer*, WriteBarrieredBase*, const char*); \ + template JS_PUBLIC_API(void) JS::TraceEdge(JSTracer*, JS::Heap*, const char*); \ template void js::TraceManuallyBarrieredEdge(JSTracer*, type*, const char*); \ template void js::TraceWeakEdge(JSTracer*, WeakRef*, const char*); \ template void js::TraceRoot(JSTracer*, type*, const char*); \ @@ -503,13 +495,6 @@ js::TraceRootRange(JSTracer* trc, size_t len, T* vec, const char* name) FOR_EACH_GC_POINTER_TYPE(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS) #undef INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS -#define INSTANTIATE_PUBLIC_TRACE_FUNCTIONS(type) \ - template JS_PUBLIC_API(void) JS::TraceEdge(JSTracer*, JS::Heap*, const char*); \ - template JS_PUBLIC_API(void) JS::TraceNullableEdge(JSTracer*, JS::Heap*, \ - const char*); -FOR_EACH_PUBLIC_GC_POINTER_TYPE(INSTANTIATE_PUBLIC_TRACE_FUNCTIONS) -#undef INSTANTIATE_PUBLIC_TRACE_FUNCTIONS - template void js::TraceManuallyBarrieredCrossCompartmentEdge(JSTracer* trc, JSObject* src, T* dst, diff --git a/js/src/gc/Tracer.cpp b/js/src/gc/Tracer.cpp index 565b15c1e06..da90d4c356d 100644 --- a/js/src/gc/Tracer.cpp +++ b/js/src/gc/Tracer.cpp @@ -135,6 +135,42 @@ JS_CallUnbarrieredScriptTracer(JSTracer* trc, JSScript** scriptp, const char* na TraceManuallyBarrieredEdge(trc, scriptp, name); } +JS_PUBLIC_API(void) +JS_CallValueTracer(JSTracer* trc, JS::Heap* valuep, const char* name) +{ + TraceManuallyBarrieredEdge(trc, valuep->unsafeGet(), name); +} + +JS_PUBLIC_API(void) +JS_CallIdTracer(JSTracer* trc, JS::Heap* idp, const char* name) +{ + TraceManuallyBarrieredEdge(trc, idp->unsafeGet(), name); +} + +JS_PUBLIC_API(void) +JS_CallObjectTracer(JSTracer* trc, JS::Heap* objp, const char* name) +{ + TraceManuallyBarrieredEdge(trc, objp->unsafeGet(), name); +} + +JS_PUBLIC_API(void) +JS_CallStringTracer(JSTracer* trc, JS::Heap* strp, const char* name) +{ + TraceManuallyBarrieredEdge(trc, strp->unsafeGet(), name); +} + +JS_PUBLIC_API(void) +JS_CallScriptTracer(JSTracer* trc, JS::Heap* scriptp, const char* name) +{ + TraceManuallyBarrieredEdge(trc, scriptp->unsafeGet(), name); +} + +JS_PUBLIC_API(void) +JS_CallFunctionTracer(JSTracer* trc, JS::Heap* funp, const char* name) +{ + TraceManuallyBarrieredEdge(trc, funp->unsafeGet(), name); +} + JS_PUBLIC_API(void) JS_CallTenuredObjectTracer(JSTracer* trc, JS::TenuredHeap* objp, const char* name) { diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 588e9cff1ba..a808545eb56 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -1072,7 +1072,7 @@ JS::ObjectPtr::updateWeakPointerAfterGC() void JS::ObjectPtr::trace(JSTracer* trc, const char* name) { - JS::TraceEdge(trc, &value, name); + JS_CallObjectTracer(trc, &value, name); } JS_FRIEND_API(JSObject*) diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 1536a17e897..56f0999a873 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -51,20 +51,8 @@ enum State { COMPACT }; -// Expand the given macro D for each publicly exposed GC reference type. -#define FOR_EACH_PUBLIC_GC_POINTER_TYPE(D) \ - D(JS::Symbol*) \ - D(JSAtom*) \ - D(JSFunction*) \ - D(JSObject*) \ - D(JSScript*) \ - D(JSString*) \ - D(JS::Value) \ - D(jsid) - // Expand the given macro D for each valid GC reference type. #define FOR_EACH_GC_POINTER_TYPE(D) \ - FOR_EACH_PUBLIC_GC_POINTER_TYPE(D) \ D(AccessorShape*) \ D(BaseShape*) \ D(UnownedBaseShape*) \ @@ -77,6 +65,8 @@ enum State { D(ArrayBufferViewObject*) \ D(DebugScopeObject*) \ D(GlobalObject*) \ + D(JSObject*) \ + D(JSFunction*) \ D(ModuleObject*) \ D(ModuleEnvironmentObject*) \ D(ModuleNamespaceObject*) \ @@ -88,12 +78,18 @@ enum State { D(SharedArrayBufferObject*) \ D(ImportEntryObject*) \ D(ExportEntryObject*) \ + D(JSScript*) \ D(LazyScript*) \ D(Shape*) \ + D(JSAtom*) \ + D(JSString*) \ D(JSFlatString*) \ D(JSLinearString*) \ D(PropertyName*) \ + D(JS::Symbol*) \ D(js::ObjectGroup*) \ + D(Value) \ + D(jsid) \ D(TaggedProto) /* Map from C++ type to alloc kind. JSObject does not have a 1:1 mapping, so must use Arena::thingSize. */ diff --git a/js/xpconnect/src/XPCVariant.cpp b/js/xpconnect/src/XPCVariant.cpp index 32b605ed9b8..4eb8eee7e2e 100644 --- a/js/xpconnect/src/XPCVariant.cpp +++ b/js/xpconnect/src/XPCVariant.cpp @@ -66,7 +66,7 @@ XPCTraceableVariant::~XPCTraceableVariant() void XPCTraceableVariant::TraceJS(JSTracer* trc) { MOZ_ASSERT(mJSVal.isMarkable()); - JS::TraceEdge(trc, &mJSVal, "XPCTraceableVariant::mJSVal"); + JS_CallValueTracer(trc, &mJSVal, "XPCTraceableVariant::mJSVal"); } NS_IMPL_CYCLE_COLLECTION_CLASS(XPCVariant) diff --git a/js/xpconnect/src/XPCWrappedJS.cpp b/js/xpconnect/src/XPCWrappedJS.cpp index 0bd0eb2b2e2..ea7390d941d 100644 --- a/js/xpconnect/src/XPCWrappedJS.cpp +++ b/js/xpconnect/src/XPCWrappedJS.cpp @@ -291,7 +291,7 @@ void nsXPCWrappedJS::TraceJS(JSTracer* trc) { MOZ_ASSERT(mRefCnt >= 2 && IsValid(), "must be strongly referenced"); - JS::TraceEdge(trc, &mJSObj, "nsXPCWrappedJS::mJSObj"); + JS_CallObjectTracer(trc, &mJSObj, "nsXPCWrappedJS::mJSObj"); } NS_IMETHODIMP diff --git a/js/xpconnect/src/XPCWrappedNative.cpp b/js/xpconnect/src/XPCWrappedNative.cpp index bd310e4ff7e..f22eaa66a42 100644 --- a/js/xpconnect/src/XPCWrappedNative.cpp +++ b/js/xpconnect/src/XPCWrappedNative.cpp @@ -2360,5 +2360,5 @@ XPCJSObjectHolder::~XPCJSObjectHolder() void XPCJSObjectHolder::TraceJS(JSTracer* trc) { - JS::TraceEdge(trc, &mJSObj, "XPCJSObjectHolder::mJSObj"); + JS_CallObjectTracer(trc, &mJSObj, "XPCJSObjectHolder::mJSObj"); } diff --git a/js/xpconnect/src/XPCWrappedNativeScope.cpp b/js/xpconnect/src/XPCWrappedNativeScope.cpp index a433010bfc9..7084087a5f0 100644 --- a/js/xpconnect/src/XPCWrappedNativeScope.cpp +++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp @@ -467,7 +467,7 @@ XPCWrappedNativeScope::~XPCWrappedNativeScope() void XPCWrappedNativeScope::TraceWrappedNativesInAllScopes(JSTracer* trc, XPCJSRuntime* rt) { - // Do JS::TraceEdge for all wrapped natives with external references, as + // Do JS_CallTracer for all wrapped natives with external references, as // well as any DOM expando objects. for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext) { for (auto i = cur->mWrappedNativeMap->Iter(); !i.Done(); i.Next()) { @@ -479,7 +479,7 @@ XPCWrappedNativeScope::TraceWrappedNativesInAllScopes(JSTracer* trc, XPCJSRuntim if (cur->mDOMExpandoSet) { for (DOMExpandoSet::Enum e(*cur->mDOMExpandoSet); !e.empty(); e.popFront()) - JS::TraceEdge(trc, &e.mutableFront(), "DOM expando object"); + JS_CallObjectTracer(trc, &e.mutableFront(), "DOM expando object"); } } } diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index 4c8f6fa5a12..d7da4ff126e 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -781,17 +781,17 @@ struct JsGcTracer : public TraceCallbacks virtual void Trace(JS::Heap* aPtr, const char* aName, void* aClosure) const override { - JS::TraceEdge(static_cast(aClosure), aPtr, aName); + JS_CallValueTracer(static_cast(aClosure), aPtr, aName); } virtual void Trace(JS::Heap* aPtr, const char* aName, void* aClosure) const override { - JS::TraceEdge(static_cast(aClosure), aPtr, aName); + JS_CallIdTracer(static_cast(aClosure), aPtr, aName); } virtual void Trace(JS::Heap* aPtr, const char* aName, void* aClosure) const override { - JS::TraceEdge(static_cast(aClosure), aPtr, aName); + JS_CallObjectTracer(static_cast(aClosure), aPtr, aName); } virtual void Trace(JSObject** aPtr, const char* aName, void* aClosure) const override @@ -806,17 +806,17 @@ struct JsGcTracer : public TraceCallbacks virtual void Trace(JS::Heap* aPtr, const char* aName, void* aClosure) const override { - JS::TraceEdge(static_cast(aClosure), aPtr, aName); + JS_CallStringTracer(static_cast(aClosure), aPtr, aName); } virtual void Trace(JS::Heap* aPtr, const char* aName, void* aClosure) const override { - JS::TraceEdge(static_cast(aClosure), aPtr, aName); + JS_CallScriptTracer(static_cast(aClosure), aPtr, aName); } virtual void Trace(JS::Heap* aPtr, const char* aName, void* aClosure) const override { - JS::TraceEdge(static_cast(aClosure), aPtr, aName); + JS_CallFunctionTracer(static_cast(aClosure), aPtr, aName); } }; diff --git a/xpcom/glue/tests/gtest/TestGCPostBarriers.cpp b/xpcom/glue/tests/gtest/TestGCPostBarriers.cpp index 8423b4c5d82..70feef96313 100644 --- a/xpcom/glue/tests/gtest/TestGCPostBarriers.cpp +++ b/xpcom/glue/tests/gtest/TestGCPostBarriers.cpp @@ -28,7 +28,7 @@ TraceArray(JSTracer* trc, void* data) { ArrayT* array = static_cast(data); for (unsigned i = 0; i < array->Length(); ++i) - JS::TraceEdge(trc, &array->ElementAt(i), "array-element"); + JS_CallObjectTracer(trc, &array->ElementAt(i), "array-element"); } /*