From b89abe6790bff17a3605ddec87924cab011dcbfb Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Wed, 7 Sep 2022 09:49:58 +0000 Subject: [PATCH] Bug 1785804 - Part 2: Remove tracing name context and pass name through the trace methods r=sfink One point of difference between the DoMarking fast path and other tracers is handling the edge name. Passing this through to the concrete tracer and handling it there removes this differemce. Eventually we should be able to inline some of these these calls at which point it should get optimsed away for tracers that ignore it. Depends on D156559 Differential Revision: https://phabricator.services.mozilla.com/D156560 --- dom/bindings/BindingUtils.h | 2 +- js/public/TracingAPI.h | 43 ++++----------- js/src/builtin/TestingFunctions.cpp | 2 +- js/src/gc/ClearEdgesTracer.h | 2 +- js/src/gc/Compacting.cpp | 2 +- js/src/gc/GC.cpp | 6 +-- js/src/gc/GCInternals.h | 4 +- js/src/gc/GCRuntime.h | 4 +- js/src/gc/Marking.cpp | 23 ++++---- js/src/gc/RootMarking.cpp | 2 +- js/src/gc/Tenuring.cpp | 53 ++++++++++++------- js/src/gc/Tenuring.h | 2 +- js/src/gc/Tracer.cpp | 7 +-- js/src/gc/Tracer.h | 7 +-- js/src/gc/Verifier.cpp | 37 +++++++------ js/src/jsapi-tests/testGCMarking.cpp | 2 +- .../jsapi-tests/testPrivateGCThingValue.cpp | 2 +- js/src/util/DumpFunctions.cpp | 6 +-- js/src/vm/SelfHosting.cpp | 2 +- js/src/vm/UbiNode.cpp | 6 +-- xpcom/base/CycleCollectedJSRuntime.cpp | 13 ++--- 21 files changed, 108 insertions(+), 119 deletions(-) diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 2e89651611cc..4f4ed2c32abb 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -636,7 +636,7 @@ struct VerifyTraceProtoAndIfaceCacheCalledTracer : public JS::CallbackTracer { : JS::CallbackTracer(cx, JS::TracerKind::VerifyTraceProtoAndIface), ok(false) {} - void onChild(JS::GCCellPtr) override { + void onChild(JS::GCCellPtr, const char* name) override { // We don't do anything here, we only want to verify that // TraceProtoAndIfaceCache was called. } diff --git a/js/public/TracingAPI.h b/js/public/TracingAPI.h index a7177e727985..9c56c2bfe6c3 100644 --- a/js/public/TracingAPI.h +++ b/js/public/TracingAPI.h @@ -101,7 +101,6 @@ struct TraceOptions { : weakEdgeAction(weakEdgeActionArg) {} }; -class AutoTracingName; class AutoTracingIndex; // Optional context information that can be used to construct human readable @@ -124,13 +123,6 @@ class TracingContext { // complexity), by associating a functor with the tracer so that, when // requested, the user can generate totally custom edge descriptions. - // Returns the current edge's name. It is only valid to call this when - // inside the trace callback, however, the edge name will always be set. - const char* name() const { - MOZ_ASSERT(name_); - return name_; - } - // Returns the current edge's index, if marked as part of an array of edges. // This must be called only inside the trace callback. When not tracing an // array, the value will be InvalidIndex. @@ -142,7 +134,7 @@ class TracingContext { // heap. On the other hand, the description provided by this method may be // substantially more accurate and useful than those provided by only the // name and index. - void getEdgeName(char* buffer, size_t bufferSize); + void getEdgeName(const char* name, char* buffer, size_t bufferSize); // The trace implementation may associate a callback with one or more edges // using AutoTracingDetails. This functor is called by getEdgeName and @@ -155,9 +147,6 @@ class TracingContext { }; private: - friend class AutoTracingName; - const char* name_ = nullptr; - friend class AutoTracingIndex; size_t index_ = InvalidIndex; @@ -228,7 +217,7 @@ class GenericTracer : public JSTracer { // which is freqently useful if, for example, we only want to process one type // of edge. #define DEFINE_ON_EDGE_METHOD(name, type, _1, _2) \ - virtual type* on##name##Edge(type* thing) = 0; + virtual type* on##name##Edge(type* thing, const char* name) = 0; JS_FOR_EACH_TRACEKIND(DEFINE_ON_EDGE_METHOD) #undef DEFINE_ON_EDGE_METHOD }; @@ -245,8 +234,10 @@ class GenericTracerImpl : public GenericTracer { private: T* derived() { return static_cast(this); } -#define DEFINE_ON_EDGE_METHOD(name, type, _1, _2) \ - type* on##name##Edge(type* thing) final { return derived()->onEdge(thing); } +#define DEFINE_ON_EDGE_METHOD(name, type, _1, _2) \ + type* on##name##Edge(type* thing, const char* name) final { \ + return derived()->onEdge(thing, name); \ + } JS_FOR_EACH_TRACEKIND(DEFINE_ON_EDGE_METHOD) #undef DEFINE_ON_EDGE_METHOD }; @@ -268,33 +259,17 @@ class JS_PUBLIC_API CallbackTracer // Override this method to receive notification when a node in the GC // heap graph is visited. - virtual void onChild(JS::GCCellPtr thing) = 0; + virtual void onChild(JS::GCCellPtr thing, const char* name) = 0; private: template - T* onEdge(T* thing) { - onChild(JS::GCCellPtr(thing)); + T* onEdge(T* thing, const char* name) { + onChild(JS::GCCellPtr(thing), name); return thing; } friend class js::GenericTracerImpl; }; -// Set the name portion of the tracer's context for the current edge. -class MOZ_RAII AutoTracingName { - JSTracer* trc_; - - public: - AutoTracingName(JSTracer* trc, const char* name) : trc_(trc) { - MOZ_ASSERT(name); - MOZ_ASSERT(!trc_->context().name_); - trc_->context().name_ = name; - } - ~AutoTracingName() { - MOZ_ASSERT(trc_->context().name_); - trc_->context().name_ = nullptr; - } -}; - // Set the index portion of the tracer's context for the current range. class MOZ_RAII AutoTracingIndex { JSTracer* trc_; diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 017b6d562634..db60daa408e7 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -2651,7 +2651,7 @@ class HasChildTracer final : public JS::CallbackTracer { RootedValue child_; bool found_; - void onChild(JS::GCCellPtr thing) override { + void onChild(JS::GCCellPtr thing, const char* name) override { if (thing.asCell() == child_.toGCThing()) { found_ = true; } diff --git a/js/src/gc/ClearEdgesTracer.h b/js/src/gc/ClearEdgesTracer.h index aebedf14732c..a5e4f8afd7c8 100644 --- a/js/src/gc/ClearEdgesTracer.h +++ b/js/src/gc/ClearEdgesTracer.h @@ -17,7 +17,7 @@ struct ClearEdgesTracer final : public GenericTracerImpl { private: template - T* onEdge(T* thing); + T* onEdge(T* thing, const char* name); friend class GenericTracerImpl; }; diff --git a/js/src/gc/Compacting.cpp b/js/src/gc/Compacting.cpp index e08266505dcb..f580d34d4185 100644 --- a/js/src/gc/Compacting.cpp +++ b/js/src/gc/Compacting.cpp @@ -441,7 +441,7 @@ MovingTracer::MovingTracer(JSRuntime* rt) JS::WeakMapTraceAction::TraceKeysAndValues) {} template -inline T* MovingTracer::onEdge(T* thing) { +inline T* MovingTracer::onEdge(T* thing, const char* name) { if (thing->runtimeFromAnyThread() == runtime() && IsForwarded(thing)) { thing = Forwarded(thing); } diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp index 4cec18251e31..4d19cd50d3bd 100644 --- a/js/src/gc/GC.cpp +++ b/js/src/gc/GC.cpp @@ -2178,7 +2178,7 @@ bool GCRuntime::shouldPreserveJITCode(Realm* realm, #ifdef DEBUG class CompartmentCheckTracer final : public JS::CallbackTracer { - void onChild(JS::GCCellPtr thing) override; + void onChild(JS::GCCellPtr thing, const char* name) override; bool edgeIsInCrossCompartmentMap(JS::GCCellPtr dst); public: @@ -2217,7 +2217,7 @@ static bool InCrossCompartmentMap(JSRuntime* rt, JSObject* src, return false; } -void CompartmentCheckTracer::onChild(JS::GCCellPtr thing) { +void CompartmentCheckTracer::onChild(JS::GCCellPtr thing, const char* name) { Compartment* comp = MapGCThingTyped(thing, [](auto t) { return t->maybeCompartment(); }); if (comp && compartment) { @@ -4735,7 +4735,7 @@ js::gc::ClearEdgesTracer::ClearEdgesTracer(JSRuntime* rt) JS::WeakMapTraceAction::TraceKeysAndValues) {} template -T* js::gc::ClearEdgesTracer::onEdge(T* thing) { +T* js::gc::ClearEdgesTracer::onEdge(T* thing, const char* name) { // We don't handle removing pointers to nursery edges from the store buffer // with this tracer. Check that this doesn't happen. MOZ_ASSERT(!IsInsideNursery(thing)); diff --git a/js/src/gc/GCInternals.h b/js/src/gc/GCInternals.h index d6c95f29034e..411c6564fbfc 100644 --- a/js/src/gc/GCInternals.h +++ b/js/src/gc/GCInternals.h @@ -306,7 +306,7 @@ struct MovingTracer final : public GenericTracerImpl { private: template - T* onEdge(T* thingp); + T* onEdge(T* thingp, const char* name); friend class GenericTracerImpl; }; @@ -316,7 +316,7 @@ struct MinorSweepingTracer final private: template - T* onEdge(T* thingp); + T* onEdge(T* thingp, const char* name); friend class GenericTracerImpl; }; diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index d9137ac8f60c..e2432897b9dc 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -263,7 +263,7 @@ class BarrierTracer final : public GenericTracerImpl { private: template - T* onEdge(T* thing); + T* onEdge(T* thing, const char* name); friend class GenericTracerImpl; void handleBufferFull(JS::GCCellPtr cell); @@ -276,7 +276,7 @@ struct SweepingTracer final : public GenericTracerImpl { private: template - T* onEdge(T* thingp); + T* onEdge(T* thingp, const char* name); friend class GenericTracerImpl; }; diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 6434c3bd11ff..9cd51a22ddc9 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -646,10 +646,9 @@ void js::TraceGCCellPtrRoot(JSTracer* trc, JS::GCCellPtr* thingp, template inline bool DoCallback(GenericTracer* trc, T** thingp, const char* name) { CheckTracedThing(trc, *thingp); - JS::AutoTracingName ctx(trc, name); T* thing = *thingp; - T* post = DispatchToOnEdge(trc, thing); + T* post = DispatchToOnEdge(trc, thing, name); if (post != thing) { *thingp = post; } @@ -659,14 +658,12 @@ inline bool DoCallback(GenericTracer* trc, T** thingp, const char* name) { template inline bool DoCallback(GenericTracer* trc, T* thingp, const char* name) { - JS::AutoTracingName ctx(trc, name); - // Return true by default. For some types the lambda below won't be called. bool ret = true; - auto thing = MapGCThingTyped(*thingp, [trc, &ret](auto thing) { + auto thing = MapGCThingTyped(*thingp, [&](auto thing) { CheckTracedThing(trc, thing); - auto* post = DispatchToOnEdge(trc, thing); + auto* post = DispatchToOnEdge(trc, thing, name); if (!post) { ret = false; return TaggedPtr::empty(); @@ -2440,7 +2437,7 @@ SweepingTracer::SweepingTracer(JSRuntime* rt) JS::WeakMapTraceAction::TraceKeysAndValues) {} template -inline T* SweepingTracer::onEdge(T* thing) { +inline T* SweepingTracer::onEdge(T* thing, const char* name) { CheckIsMarkedThing(thing); if (!thing->isTenured()) { @@ -2560,7 +2557,7 @@ struct AssertNonGrayTracer final : public JS::CallbackTracer { // context without making this more generic. explicit AssertNonGrayTracer(JSRuntime* rt) : JS::CallbackTracer(rt, JS::TracerKind::UnmarkGray) {} - void onChild(JS::GCCellPtr thing) override { + void onChild(JS::GCCellPtr thing, const char* name) override { MOZ_ASSERT(!thing.asCell()->isMarkedGray()); } }; @@ -2589,10 +2586,10 @@ class UnmarkGrayTracer final : public JS::CallbackTracer { // Stack of cells to traverse. Vector& stack; - void onChild(JS::GCCellPtr thing) override; + void onChild(JS::GCCellPtr thing, const char* name) override; }; -void UnmarkGrayTracer::onChild(JS::GCCellPtr thing) { +void UnmarkGrayTracer::onChild(JS::GCCellPtr thing, const char* name) { Cell* cell = thing.asCell(); // Cells in the nursery cannot be gray, and nor can certain kinds of tenured @@ -2645,7 +2642,7 @@ void UnmarkGrayTracer::onChild(JS::GCCellPtr thing) { void UnmarkGrayTracer::unmark(JS::GCCellPtr cell) { MOZ_ASSERT(stack.empty()); - onChild(cell); + onChild(cell, "unmarking root"); while (!stack.empty() && !oom) { TraceChildren(this, stack.popCopy()); @@ -2705,7 +2702,7 @@ static bool CellHasChildren(JS::GCCellPtr cell) { struct Tracer : public JS::CallbackTracer { bool hasChildren = false; explicit Tracer(JSRuntime* runtime) : JS::CallbackTracer(runtime) {} - void onChild(JS::GCCellPtr thing) { hasChildren = true; } + void onChild(JS::GCCellPtr thing, const char* name) { hasChildren = true; } }; Tracer trc(cell.asCell()->runtimeFromMainThread()); @@ -2749,7 +2746,7 @@ BarrierTracer::BarrierTracer(JSRuntime* rt) marker(rt->gc.marker) {} template -T* BarrierTracer::onEdge(T* thing) { +T* BarrierTracer::onEdge(T* thing, const char* name) { PreWriteBarrier(thing); return thing; } diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index 01305f6e3cc3..ca4be6fdf383 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -400,7 +400,7 @@ IncrementalProgress GCRuntime::traceEmbeddingGrayRoots(JSTracer* trc, #ifdef DEBUG class AssertNoRootsTracer final : public JS::CallbackTracer { - void onChild(JS::GCCellPtr thing) override { + void onChild(JS::GCCellPtr thing, const char* name) override { MOZ_CRASH("There should not be any roots during runtime shutdown"); } diff --git a/js/src/gc/Tenuring.cpp b/js/src/gc/Tenuring.cpp index b425ace03ba5..2438e07bae3b 100644 --- a/js/src/gc/Tenuring.cpp +++ b/js/src/gc/Tenuring.cpp @@ -59,7 +59,7 @@ static inline void UpdateAllocSiteOnTenure(Cell* cell) { site->incTenuredCount(); } -JSObject* TenuringTracer::onObjectEdge(JSObject* obj) { +JSObject* TenuringTracer::onObjectEdge(JSObject* obj, const char* name) { if (!IsInsideNursery(obj)) { return obj; } @@ -80,7 +80,7 @@ JSObject* TenuringTracer::onObjectEdge(JSObject* obj) { return moveToTenuredSlow(obj); } -JSString* TenuringTracer::onStringEdge(JSString* str) { +JSString* TenuringTracer::onStringEdge(JSString* str, const char* name) { if (!IsInsideNursery(str)) { return str; } @@ -95,7 +95,7 @@ JSString* TenuringTracer::onStringEdge(JSString* str) { return moveToTenured(str); } -JS::BigInt* TenuringTracer::onBigIntEdge(JS::BigInt* bi) { +JS::BigInt* TenuringTracer::onBigIntEdge(JS::BigInt* bi, const char* name) { if (!IsInsideNursery(bi)) { return bi; } @@ -110,23 +110,38 @@ JS::BigInt* TenuringTracer::onBigIntEdge(JS::BigInt* bi) { return moveToTenured(bi); } -JS::Symbol* TenuringTracer::onSymbolEdge(JS::Symbol* sym) { return sym; } -js::BaseScript* TenuringTracer::onScriptEdge(BaseScript* script) { +JS::Symbol* TenuringTracer::onSymbolEdge(JS::Symbol* sym, const char* name) { + return sym; +} +js::BaseScript* TenuringTracer::onScriptEdge(BaseScript* script, + const char* name) { return script; } -js::Shape* TenuringTracer::onShapeEdge(Shape* shape) { return shape; } -js::RegExpShared* TenuringTracer::onRegExpSharedEdge(RegExpShared* shared) { +js::Shape* TenuringTracer::onShapeEdge(Shape* shape, const char* name) { + return shape; +} +js::RegExpShared* TenuringTracer::onRegExpSharedEdge(RegExpShared* shared, + const char* name) { return shared; } -js::BaseShape* TenuringTracer::onBaseShapeEdge(BaseShape* base) { return base; } -js::GetterSetter* TenuringTracer::onGetterSetterEdge(GetterSetter* gs) { +js::BaseShape* TenuringTracer::onBaseShapeEdge(BaseShape* base, + const char* name) { + return base; +} +js::GetterSetter* TenuringTracer::onGetterSetterEdge(GetterSetter* gs, + const char* name) { return gs; } -js::PropMap* TenuringTracer::onPropMapEdge(PropMap* map) { return map; } -js::jit::JitCode* TenuringTracer::onJitCodeEdge(jit::JitCode* code) { +js::PropMap* TenuringTracer::onPropMapEdge(PropMap* map, const char* name) { + return map; +} +js::jit::JitCode* TenuringTracer::onJitCodeEdge(jit::JitCode* code, + const char* name) { return code; } -js::Scope* TenuringTracer::onScopeEdge(Scope* scope) { return scope; } +js::Scope* TenuringTracer::onScopeEdge(Scope* scope, const char* name) { + return scope; +} void TenuringTracer::traverse(JS::Value* thingp) { MOZ_ASSERT(!nursery().isInside(thingp)); @@ -138,18 +153,18 @@ void TenuringTracer::traverse(JS::Value* thingp) { // tighter code than using MapGCThingTyped. Value post; if (value.isObject()) { - post = JS::ObjectValue(*onObjectEdge(&value.toObject())); + post = JS::ObjectValue(*onObjectEdge(&value.toObject(), "value")); } #ifdef ENABLE_RECORD_TUPLE else if (value.isExtendedPrimitive()) { - post = - JS::ExtendedPrimitiveValue(*onObjectEdge(&value.toExtendedPrimitive())); + post = JS::ExtendedPrimitiveValue( + *onObjectEdge(&value.toExtendedPrimitive(), "value")); } #endif else if (value.isString()) { - post = JS::StringValue(onStringEdge(value.toString())); + post = JS::StringValue(onStringEdge(value.toString(), "value")); } else if (value.isBigInt()) { - post = JS::BigIntValue(onBigIntEdge(value.toBigInt())); + post = JS::BigIntValue(onBigIntEdge(value.toBigInt(), "value")); } else { MOZ_ASSERT_IF(value.isGCThing(), !IsInsideNursery(value.toGCThing())); return; @@ -397,7 +412,7 @@ void js::gc::StoreBuffer::CellPtrEdge::trace(TenuringTracer& mover) const { edge, JS::TraceKind::String)); } - *edge = DispatchToOnEdge(&mover, thing); + *edge = DispatchToOnEdge(&mover, thing, "CellPtrEdge"); } void js::gc::StoreBuffer::ValueEdge::trace(TenuringTracer& mover) const { @@ -986,7 +1001,7 @@ MinorSweepingTracer::MinorSweepingTracer(JSRuntime* rt) } template -inline T* MinorSweepingTracer::onEdge(T* thing) { +inline T* MinorSweepingTracer::onEdge(T* thing, const char* name) { if (thing->isTenured()) { return thing; } diff --git a/js/src/gc/Tenuring.h b/js/src/gc/Tenuring.h index bf236be0749d..b0c8780df047 100644 --- a/js/src/gc/Tenuring.h +++ b/js/src/gc/Tenuring.h @@ -36,7 +36,7 @@ class TenuringTracer final : public GenericTracer { gc::StringRelocationOverlay* stringHead = nullptr; #define DEFINE_ON_EDGE_METHOD(name, type, _1, _2) \ - type* on##name##Edge(type* thing) override; + type* on##name##Edge(type* thing, const char* name) override; JS_FOR_EACH_TRACEKIND(DEFINE_ON_EDGE_METHOD) #undef DEFINE_ON_EDGE_METHOD diff --git a/js/src/gc/Tracer.cpp b/js/src/gc/Tracer.cpp index a8087eaa84ad..c4ab83745cc1 100644 --- a/js/src/gc/Tracer.cpp +++ b/js/src/gc/Tracer.cpp @@ -39,17 +39,18 @@ template void RuntimeScopeData::trace(JSTracer* trc); template void RuntimeScopeData::trace( JSTracer* trc); -void JS::TracingContext::getEdgeName(char* buffer, size_t bufferSize) { +void JS::TracingContext::getEdgeName(const char* name, char* buffer, + size_t bufferSize) { MOZ_ASSERT(bufferSize > 0); if (functor_) { (*functor_)(this, buffer, bufferSize); return; } if (index_ != InvalidIndex) { - snprintf(buffer, bufferSize, "%s[%zu]", name_, index_); + snprintf(buffer, bufferSize, "%s[%zu]", name, index_); return; } - snprintf(buffer, bufferSize, "%s", name_); + snprintf(buffer, bufferSize, "%s", name); } /*** Public Tracing API *****************************************************/ diff --git a/js/src/gc/Tracer.h b/js/src/gc/Tracer.h index c9c4eb0c533d..80ddfa78c52c 100644 --- a/js/src/gc/Tracer.h +++ b/js/src/gc/Tracer.h @@ -355,9 +355,10 @@ void GetTraceThingInfo(char* buf, size_t bufsize, void* thing, // Overloaded function to call the correct GenericTracer method based on the // argument type. -#define DEFINE_DISPATCH_FUNCTION(name, type, _1, _2) \ - inline type* DispatchToOnEdge(GenericTracer* trc, type* thing) { \ - return trc->on##name##Edge(thing); \ +#define DEFINE_DISPATCH_FUNCTION(name, type, _1, _2) \ + inline type* DispatchToOnEdge(GenericTracer* trc, type* thing, \ + const char* name) { \ + return trc->on##name##Edge(thing, name); \ } JS_FOR_EACH_TRACEKIND(DEFINE_DISPATCH_FUNCTION) #undef DEFINE_DISPATCH_FUNCTION diff --git a/js/src/gc/Verifier.cpp b/js/src/gc/Verifier.cpp index ddbc6dce4447..24b90ebc1fd4 100644 --- a/js/src/gc/Verifier.cpp +++ b/js/src/gc/Verifier.cpp @@ -86,7 +86,7 @@ typedef HashMap, SystemAllocPolicy> class js::VerifyPreTracer final : public JS::CallbackTracer { JS::AutoDisableGenerationalGC noggc; - void onChild(JS::GCCellPtr thing) override; + void onChild(JS::GCCellPtr thing, const char* name) override; public: /* The gcNumber when the verification began. */ @@ -123,7 +123,7 @@ class js::VerifyPreTracer final : public JS::CallbackTracer { * This function builds up the heap snapshot by adding edges to the current * node. */ -void VerifyPreTracer::onChild(JS::GCCellPtr thing) { +void VerifyPreTracer::onChild(JS::GCCellPtr thing, const char* name) { MOZ_ASSERT(!IsInsideNursery(thing.asCell())); // Skip things in other runtimes. @@ -141,7 +141,7 @@ void VerifyPreTracer::onChild(JS::GCCellPtr thing) { uint32_t i = node->count; node->edges[i].thing = thing; - node->edges[i].label = context().name(); + node->edges[i].label = name; node->count++; } @@ -280,7 +280,7 @@ struct CheckEdgeTracer final : public JS::CallbackTracer { VerifyNode* node; explicit CheckEdgeTracer(JSRuntime* rt) : JS::CallbackTracer(rt), node(nullptr) {} - void onChild(JS::GCCellPtr thing) override; + void onChild(JS::GCCellPtr thing, const char* name) override; }; static const uint32_t MAX_VERIFIER_EDGES = 1000; @@ -292,7 +292,7 @@ static const uint32_t MAX_VERIFIER_EDGES = 1000; * non-nullptr edges (i.e., the ones from the original snapshot that must have * been modified) must point to marked objects. */ -void CheckEdgeTracer::onChild(JS::GCCellPtr thing) { +void CheckEdgeTracer::onChild(JS::GCCellPtr thing, const char* name) { // Skip things in other runtimes. if (thing.asCell()->asTenured().runtimeFromAnyThread() != runtime()) { return; @@ -781,11 +781,11 @@ class HeapCheckTracerBase : public JS::CallbackTracer { public: explicit HeapCheckTracerBase(JSRuntime* rt, JS::TraceOptions options); bool traceHeap(AutoTraceSession& session); - virtual void checkCell(Cell* cell) = 0; + virtual void checkCell(Cell* cell, const char* name) = 0; protected: void dumpCellInfo(Cell* cell); - void dumpCellPath(); + void dumpCellPath(const char* name); Cell* parentCell() { return parentIndex == -1 ? nullptr : stack[parentIndex].thing.asCell(); @@ -794,7 +794,7 @@ class HeapCheckTracerBase : public JS::CallbackTracer { size_t failures; private: - void onChild(JS::GCCellPtr thing) override; + void onChild(JS::GCCellPtr thing, const char* name) override; struct WorkItem { WorkItem(JS::GCCellPtr thing, const char* name, int parentIndex) @@ -824,9 +824,9 @@ HeapCheckTracerBase::HeapCheckTracerBase(JSRuntime* rt, oom(false), parentIndex(-1) {} -void HeapCheckTracerBase::onChild(JS::GCCellPtr thing) { +void HeapCheckTracerBase::onChild(JS::GCCellPtr thing, const char* name) { Cell* cell = thing.asCell(); - checkCell(cell); + checkCell(cell, name); if (visited.lookup(cell)) { return; @@ -842,7 +842,7 @@ void HeapCheckTracerBase::onChild(JS::GCCellPtr thing) { return; } - WorkItem item(thing, context().name(), parentIndex); + WorkItem item(thing, name, parentIndex); if (!stack.append(item)) { oom = true; } @@ -884,8 +884,7 @@ void HeapCheckTracerBase::dumpCellInfo(Cell* cell) { } } -void HeapCheckTracerBase::dumpCellPath() { - const char* name = context().name(); +void HeapCheckTracerBase::dumpCellPath(const char* name) { for (int index = parentIndex; index != -1; index = stack[index].parentIndex) { const WorkItem& parent = stack[index]; Cell* cell = parent.thing.asCell(); @@ -905,7 +904,7 @@ class CheckHeapTracer final : public HeapCheckTracerBase { void check(AutoTraceSession& session); private: - void checkCell(Cell* cell) override; + void checkCell(Cell* cell, const char* name) override; GCType gcType; }; @@ -917,14 +916,14 @@ inline static bool IsValidGCThingPointer(Cell* cell) { return (uintptr_t(cell) & CellAlignMask) == 0; } -void CheckHeapTracer::checkCell(Cell* cell) { +void CheckHeapTracer::checkCell(Cell* cell, const char* name) { // Moving if (!IsValidGCThingPointer(cell) || ((gcType == GCType::Moving) && !IsGCThingValidAfterMovingGC(cell)) || ((gcType == GCType::NonMoving) && cell->isForwarded())) { failures++; fprintf(stderr, "Bad pointer %p\n", cell); - dumpCellPath(); + dumpCellPath(name); } } @@ -959,7 +958,7 @@ class CheckGrayMarkingTracer final : public HeapCheckTracerBase { bool check(AutoTraceSession& session); private: - void checkCell(Cell* cell) override; + void checkCell(Cell* cell, const char* name) override; }; CheckGrayMarkingTracer::CheckGrayMarkingTracer(JSRuntime* rt) @@ -968,7 +967,7 @@ CheckGrayMarkingTracer::CheckGrayMarkingTracer(JSRuntime* rt) // Weak gray->black edges are allowed. } -void CheckGrayMarkingTracer::checkCell(Cell* cell) { +void CheckGrayMarkingTracer::checkCell(Cell* cell, const char* name) { Cell* parent = parentCell(); if (!parent) { return; @@ -980,7 +979,7 @@ void CheckGrayMarkingTracer::checkCell(Cell* cell) { fprintf(stderr, "Found black to gray edge to "); dumpCellInfo(cell); fprintf(stderr, "\n"); - dumpCellPath(); + dumpCellPath(name); # ifdef DEBUG if (parent->is()) { diff --git a/js/src/jsapi-tests/testGCMarking.cpp b/js/src/jsapi-tests/testGCMarking.cpp index f86bca1dfd0a..dc2f1e0f4d63 100644 --- a/js/src/jsapi-tests/testGCMarking.cpp +++ b/js/src/jsapi-tests/testGCMarking.cpp @@ -75,7 +75,7 @@ static bool ConstructCCW(JSContext* cx, const JSClass* globalClasp, } class CCWTestTracer final : public JS::CallbackTracer { - void onChild(JS::GCCellPtr thing) override { + void onChild(JS::GCCellPtr thing, const char* name) override { numberOfThingsTraced++; printf("*thingp = %p\n", thing.asCell()); diff --git a/js/src/jsapi-tests/testPrivateGCThingValue.cpp b/js/src/jsapi-tests/testPrivateGCThingValue.cpp index a479294676ee..a4560b68d29e 100644 --- a/js/src/jsapi-tests/testPrivateGCThingValue.cpp +++ b/js/src/jsapi-tests/testPrivateGCThingValue.cpp @@ -16,7 +16,7 @@ #include "util/Text.h" class TestTracer final : public JS::CallbackTracer { - void onChild(JS::GCCellPtr thing) override { + void onChild(JS::GCCellPtr thing, const char* name) override { if (thing.asCell() == expectedCell && thing.kind() == expectedKind) { found = true; } diff --git a/js/src/util/DumpFunctions.cpp b/js/src/util/DumpFunctions.cpp index 7657931bb7a5..d8ab0df4d049 100644 --- a/js/src/util/DumpFunctions.cpp +++ b/js/src/util/DumpFunctions.cpp @@ -537,7 +537,7 @@ struct DumpHeapTracer final : public JS::CallbackTracer, public WeakMapTracer { key.asCell(), kdelegate, value.asCell()); } - void onChild(JS::GCCellPtr thing) override; + void onChild(JS::GCCellPtr thing, const char* name) override; }; static char MarkDescriptor(js::gc::Cell* thing) { @@ -603,13 +603,13 @@ static void DumpHeapVisitCell(JSRuntime* rt, void* data, JS::GCCellPtr cellptr, JS::TraceChildren(dtrc, cellptr); } -void DumpHeapTracer::onChild(JS::GCCellPtr thing) { +void DumpHeapTracer::onChild(JS::GCCellPtr thing, const char* name) { if (js::gc::IsInsideNursery(thing.asCell())) { return; } char buffer[1024]; - context().getEdgeName(buffer, sizeof(buffer)); + context().getEdgeName(name, buffer, sizeof(buffer)); fprintf(output, "%s%p %c %s\n", prefix, thing.asCell(), MarkDescriptor(thing.asCell()), buffer); } diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index f70eedb73a15..cdc1dc2931a0 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -2229,7 +2229,7 @@ class CheckTenuredTracer : public JS::CallbackTracer { JS::TraceChildren(this, stack.popCopy()); } } - void onChild(JS::GCCellPtr thing) override { + void onChild(JS::GCCellPtr thing, const char* name) override { gc::Cell* cell = thing.asCell(); MOZ_RELEASE_ASSERT(cell->isTenured(), "Expected tenured cell"); if (!visited.has(cell)) { diff --git a/js/src/vm/UbiNode.cpp b/js/src/vm/UbiNode.cpp index bd6c732e8b40..4bc76c1d64a1 100644 --- a/js/src/vm/UbiNode.cpp +++ b/js/src/vm/UbiNode.cpp @@ -196,7 +196,7 @@ class EdgeVectorTracer final : public JS::CallbackTracer { // True if we should populate the edge's names. bool wantNames; - void onChild(JS::GCCellPtr thing) override { + void onChild(JS::GCCellPtr thing, const char* name) override { if (!okay) { return; } @@ -214,8 +214,8 @@ class EdgeVectorTracer final : public JS::CallbackTracer { if (wantNames) { // Ask the tracer to compute an edge name for us. char buffer[1024]; - context().getEdgeName(buffer, sizeof(buffer)); - const char* name = buffer; + context().getEdgeName(name, buffer, sizeof(buffer)); + name = buffer; // Convert the name to char16_t characters. name16 = js_pod_malloc(strlen(name) + 1); diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index e58d20e2db07..495fa310fab0 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -161,7 +161,7 @@ struct NoteWeakMapChildrenTracer : public JS::CallbackTracer { mMap(nullptr), mKey(nullptr), mKeyDelegate(nullptr) {} - void onChild(JS::GCCellPtr aThing) override; + void onChild(JS::GCCellPtr aThing, const char* name) override; nsCycleCollectionNoteRootCallback& mCb; bool mTracedAny; JSObject* mMap; @@ -169,7 +169,8 @@ struct NoteWeakMapChildrenTracer : public JS::CallbackTracer { JSObject* mKeyDelegate; }; -void NoteWeakMapChildrenTracer::onChild(JS::GCCellPtr aThing) { +void NoteWeakMapChildrenTracer::onChild(JS::GCCellPtr aThing, + const char* name) { if (aThing.is()) { return; } @@ -399,11 +400,11 @@ struct TraversalTracer : public JS::CallbackTracer { JS::TraceOptions(JS::WeakMapTraceAction::Skip, JS::WeakEdgeTraceAction::Trace)), mCb(aCb) {} - void onChild(JS::GCCellPtr aThing) override; + void onChild(JS::GCCellPtr aThing, const char* name) override; nsCycleCollectionTraversalCallback& mCb; }; -void TraversalTracer::onChild(JS::GCCellPtr aThing) { +void TraversalTracer::onChild(JS::GCCellPtr aThing, const char* name) { // Checking strings and symbols for being gray is rather slow, and we don't // need either of them for the cycle collector. if (aThing.is() || aThing.is()) { @@ -425,7 +426,7 @@ void TraversalTracer::onChild(JS::GCCellPtr aThing) { if (JS::IsCCTraceKind(aThing.kind())) { if (MOZ_UNLIKELY(mCb.WantDebugInfo())) { char buffer[200]; - context().getEdgeName(buffer, sizeof(buffer)); + context().getEdgeName(name, buffer, sizeof(buffer)); mCb.NoteNextEdgeName(buffer); } mCb.NoteJSChild(aThing); @@ -746,7 +747,7 @@ class JSLeakTracer : public JS::CallbackTracer { JS::WeakMapTraceAction::TraceKeysAndValues) {} private: - void onChild(JS::GCCellPtr thing) override { + void onChild(JS::GCCellPtr thing, const char* name) override { const char* kindName = JS::GCTraceKindToAscii(thing.kind()); size_t size = JS::GCTraceKindSize(thing.kind()); MOZ_LOG_CTOR(thing.asCell(), kindName, size);