From 14bc095b599c7afc5e403b0c48331b899de39719 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Wed, 30 Dec 2015 08:52:12 -0800 Subject: [PATCH] Bug 1235598 - Part 1: Add better SpiderMonkey API support for tracing in C++; r=sfink --HG-- extra : rebase_source : 777e1dd17331f38b482fc12ef1e2d96ec61fb02d --- js/public/TracingAPI.h | 49 ++++++++++++++++------------------------ js/src/ctypes/CTypes.cpp | 12 +++++----- js/src/ctypes/CTypes.h | 2 +- js/src/gc/Marking.cpp | 17 +++++++++++++- js/src/gc/Tracer.cpp | 36 ----------------------------- js/src/jsfriendapi.cpp | 2 +- js/src/jsgc.h | 20 +++++++++------- 7 files changed, 55 insertions(+), 83 deletions(-) diff --git a/js/public/TracingAPI.h b/js/public/TracingAPI.h index 08ced6818517..0806d43961e1 100644 --- a/js/public/TracingAPI.h +++ b/js/public/TracingAPI.h @@ -281,40 +281,29 @@ JSTracer::asCallbackTracer() return static_cast(this); } -// 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::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 { + +// 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 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. 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 d9489f0bad28..9a6b391256b4 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_CallObjectTracer(trc, &fninfo->mABI, "abi"); - JS_CallObjectTracer(trc, &fninfo->mReturnType, "returnType"); + JS::TraceEdge(trc, &fninfo->mABI, "abi"); + JS::TraceEdge(trc, &fninfo->mReturnType, "returnType"); for (size_t i = 0; i < fninfo->mArgTypes.length(); ++i) - JS_CallObjectTracer(trc, &fninfo->mArgTypes[i], "argType"); + JS::TraceEdge(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_CallObjectTracer(trc, &cinfo->typeObj, "typeObj"); - JS_CallObjectTracer(trc, &cinfo->jsfnObj, "jsfnObj"); + JS::TraceEdge(trc, &cinfo->typeObj, "typeObj"); + JS::TraceEdge(trc, &cinfo->jsfnObj, "jsfnObj"); if (cinfo->thisObj) - JS_CallObjectTracer(trc, &cinfo->thisObj, "thisObj"); + JS::TraceEdge(trc, &cinfo->thisObj, "thisObj"); } void diff --git a/js/src/ctypes/CTypes.h b/js/src/ctypes/CTypes.h index 728baf9c6c8e..9577b3698ce9 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_CallObjectTracer(trc, &mType, "fieldType"); + JS::TraceEdge(trc, &mType, "fieldType"); } }; diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 2627b12cc9ae..6bff25c5c356 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -405,6 +405,15 @@ 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) @@ -483,7 +492,6 @@ 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*); \ @@ -495,6 +503,13 @@ 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 da90d4c356d2..565b15c1e06e 100644 --- a/js/src/gc/Tracer.cpp +++ b/js/src/gc/Tracer.cpp @@ -135,42 +135,6 @@ 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 a808545eb566..588e9cff1bae 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_CallObjectTracer(trc, &value, name); + JS::TraceEdge(trc, &value, name); } JS_FRIEND_API(JSObject*) diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 56f0999a8735..1536a17e8972 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -51,8 +51,20 @@ 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*) \ @@ -65,8 +77,6 @@ enum State { D(ArrayBufferViewObject*) \ D(DebugScopeObject*) \ D(GlobalObject*) \ - D(JSObject*) \ - D(JSFunction*) \ D(ModuleObject*) \ D(ModuleEnvironmentObject*) \ D(ModuleNamespaceObject*) \ @@ -78,18 +88,12 @@ 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. */