Bug 1668825 - Change GenericTracer API so that it doesn't include details of heap storage r=sfink

The final patch in this series. This changes the GenericTracer APIs to take a
thing pointer and return a possibly updated versions, rather than taking a
double pointer to the thing. This means that we can change the details of how
pointers are stored in the heap without chaning this interface.

Differential Revision: https://phabricator.services.mozilla.com/D93336
This commit is contained in:
Jon Coppeard 2020-10-14 09:17:27 +00:00
Родитель 2eb7622b4a
Коммит 16aaee1d65
7 изменённых файлов: 253 добавлений и 217 удалений

Просмотреть файл

@ -238,25 +238,28 @@ class GenericTracer : public JSTracer {
MOZ_ASSERT(isGenericTracer());
}
// Override these methods to receive notification when an edge is visited
// with the type contained in the callback.
// These methods are called when the tracer encounters an edge. Clients should
// override them to receive notifications when an edge of each type is
// visited.
//
// The caller updates the edge with the return value (if different).
//
// In C++, overriding a method hides all methods in the base class with that
// name, not just methods with that signature. Thus, the typed edge methods
// have to have distinct names to allow us to override them individually,
// which is freqently useful if, for example, we only want to process one type
// of edge.
virtual bool onObjectEdge(JSObject** objp) = 0;
virtual bool onStringEdge(JSString** strp) = 0;
virtual bool onSymbolEdge(JS::Symbol** symp) = 0;
virtual bool onBigIntEdge(JS::BigInt** bip) = 0;
virtual bool onScriptEdge(js::BaseScript** scriptp) = 0;
virtual bool onShapeEdge(js::Shape** shapep) = 0;
virtual bool onRegExpSharedEdge(js::RegExpShared** sharedp) = 0;
virtual bool onObjectGroupEdge(js::ObjectGroup** groupp) = 0;
virtual bool onBaseShapeEdge(js::BaseShape** basep) = 0;
virtual bool onJitCodeEdge(js::jit::JitCode** codep) = 0;
virtual bool onScopeEdge(js::Scope** scopep) = 0;
virtual JSObject* onObjectEdge(JSObject* obj) = 0;
virtual JSString* onStringEdge(JSString* str) = 0;
virtual JS::Symbol* onSymbolEdge(JS::Symbol* sym) = 0;
virtual JS::BigInt* onBigIntEdge(JS::BigInt* bi) = 0;
virtual js::BaseScript* onScriptEdge(js::BaseScript* script) = 0;
virtual js::Shape* onShapeEdge(js::Shape* shape) = 0;
virtual js::RegExpShared* onRegExpSharedEdge(js::RegExpShared* shared) = 0;
virtual js::ObjectGroup* onObjectGroupEdge(js::ObjectGroup* group) = 0;
virtual js::BaseShape* onBaseShapeEdge(js::BaseShape* base) = 0;
virtual js::jit::JitCode* onJitCodeEdge(js::jit::JitCode* code) = 0;
virtual js::Scope* onScopeEdge(js::Scope* scope) = 0;
};
} // namespace js
@ -282,49 +285,49 @@ class JS_PUBLIC_API CallbackTracer : public js::GenericTracer {
private:
// This class implements the GenericTracer interface to dispatches to onChild.
virtual bool onObjectEdge(JSObject** objp) {
onChild(JS::GCCellPtr(*objp));
return true;
virtual JSObject* onObjectEdge(JSObject* obj) {
onChild(JS::GCCellPtr(obj));
return obj;
}
virtual bool onStringEdge(JSString** strp) {
onChild(JS::GCCellPtr(*strp));
return true;
virtual JSString* onStringEdge(JSString* str) {
onChild(JS::GCCellPtr(str));
return str;
}
virtual bool onSymbolEdge(JS::Symbol** symp) {
onChild(JS::GCCellPtr(*symp));
return true;
virtual JS::Symbol* onSymbolEdge(JS::Symbol* sym) {
onChild(JS::GCCellPtr(sym));
return sym;
}
virtual bool onBigIntEdge(JS::BigInt** bip) {
onChild(JS::GCCellPtr(*bip));
return true;
virtual JS::BigInt* onBigIntEdge(JS::BigInt* bi) {
onChild(JS::GCCellPtr(bi));
return bi;
}
virtual bool onScriptEdge(js::BaseScript** scriptp) {
onChild(JS::GCCellPtr(*scriptp));
return true;
virtual js::BaseScript* onScriptEdge(js::BaseScript* script) {
onChild(JS::GCCellPtr(script));
return script;
}
virtual bool onShapeEdge(js::Shape** shapep) {
onChild(JS::GCCellPtr(*shapep, JS::TraceKind::Shape));
return true;
virtual js::Shape* onShapeEdge(js::Shape* shape) {
onChild(JS::GCCellPtr(shape, JS::TraceKind::Shape));
return shape;
}
virtual bool onObjectGroupEdge(js::ObjectGroup** groupp) {
onChild(JS::GCCellPtr(*groupp, JS::TraceKind::ObjectGroup));
return true;
virtual js::ObjectGroup* onObjectGroupEdge(js::ObjectGroup* group) {
onChild(JS::GCCellPtr(group, JS::TraceKind::ObjectGroup));
return group;
}
virtual bool onBaseShapeEdge(js::BaseShape** basep) {
onChild(JS::GCCellPtr(*basep, JS::TraceKind::BaseShape));
return true;
virtual js::BaseShape* onBaseShapeEdge(js::BaseShape* base) {
onChild(JS::GCCellPtr(base, JS::TraceKind::BaseShape));
return base;
}
virtual bool onJitCodeEdge(js::jit::JitCode** codep) {
onChild(JS::GCCellPtr(*codep, JS::TraceKind::JitCode));
return true;
virtual js::jit::JitCode* onJitCodeEdge(js::jit::JitCode* code) {
onChild(JS::GCCellPtr(code, JS::TraceKind::JitCode));
return code;
}
virtual bool onScopeEdge(js::Scope** scopep) {
onChild(JS::GCCellPtr(*scopep, JS::TraceKind::Scope));
return true;
virtual js::Scope* onScopeEdge(js::Scope* scope) {
onChild(JS::GCCellPtr(scope, JS::TraceKind::Scope));
return scope;
}
virtual bool onRegExpSharedEdge(js::RegExpShared** sharedp) {
onChild(JS::GCCellPtr(*sharedp, JS::TraceKind::RegExpShared));
return true;
virtual js::RegExpShared* onRegExpSharedEdge(js::RegExpShared* shared) {
onChild(JS::GCCellPtr(shared, JS::TraceKind::RegExpShared));
return shared;
}
TracingContext context_;

Просмотреть файл

@ -17,19 +17,19 @@ struct ClearEdgesTracer final : public GenericTracer {
ClearEdgesTracer();
template <typename T>
inline bool clearEdge(T** thingp);
inline T* onEdge(T* thing);
bool onObjectEdge(JSObject** objp) override;
bool onStringEdge(JSString** strp) override;
bool onSymbolEdge(JS::Symbol** symp) override;
bool onBigIntEdge(JS::BigInt** bip) override;
bool onScriptEdge(js::BaseScript** scriptp) override;
bool onShapeEdge(js::Shape** shapep) override;
bool onObjectGroupEdge(js::ObjectGroup** groupp) override;
bool onBaseShapeEdge(js::BaseShape** basep) override;
bool onJitCodeEdge(js::jit::JitCode** codep) override;
bool onScopeEdge(js::Scope** scopep) override;
bool onRegExpSharedEdge(js::RegExpShared** sharedp) override;
JSObject* onObjectEdge(JSObject* obj) override;
JSString* onStringEdge(JSString* str) override;
JS::Symbol* onSymbolEdge(JS::Symbol* sym) override;
JS::BigInt* onBigIntEdge(JS::BigInt* bi) override;
js::BaseScript* onScriptEdge(js::BaseScript* script) override;
js::Shape* onShapeEdge(js::Shape* shape) override;
js::ObjectGroup* onObjectGroupEdge(js::ObjectGroup* group) override;
js::BaseShape* onBaseShapeEdge(js::BaseShape* base) override;
js::jit::JitCode* onJitCodeEdge(js::jit::JitCode* code) override;
js::Scope* onScopeEdge(js::Scope* scope) override;
js::RegExpShared* onRegExpSharedEdge(js::RegExpShared* shared) override;
};
} // namespace gc

Просмотреть файл

@ -2178,41 +2178,40 @@ bool GCRuntime::relocateArenas(Zone* zone, JS::GCReason reason,
}
template <typename T>
inline bool MovingTracer::updateEdge(T** thingp) {
auto thing = *thingp;
inline T* MovingTracer::onEdge(T* thing) {
if (thing->runtimeFromAnyThread() == runtime() && IsForwarded(thing)) {
*thingp = Forwarded(thing);
thing = Forwarded(thing);
}
return true;
return thing;
}
bool MovingTracer::onObjectEdge(JSObject** objp) { return updateEdge(objp); }
bool MovingTracer::onShapeEdge(Shape** shapep) { return updateEdge(shapep); }
bool MovingTracer::onStringEdge(JSString** stringp) {
return updateEdge(stringp);
JSObject* MovingTracer::onObjectEdge(JSObject* obj) { return onEdge(obj); }
Shape* MovingTracer::onShapeEdge(Shape* shape) { return onEdge(shape); }
JSString* MovingTracer::onStringEdge(JSString* string) {
return onEdge(string);
}
bool MovingTracer::onScriptEdge(js::BaseScript** scriptp) {
return updateEdge(scriptp);
js::BaseScript* MovingTracer::onScriptEdge(js::BaseScript* script) {
return onEdge(script);
}
bool MovingTracer::onBaseShapeEdge(BaseShape** basep) {
return updateEdge(basep);
BaseShape* MovingTracer::onBaseShapeEdge(BaseShape* base) {
return onEdge(base);
}
bool MovingTracer::onScopeEdge(Scope** scopep) { return updateEdge(scopep); }
bool MovingTracer::onRegExpSharedEdge(RegExpShared** sharedp) {
return updateEdge(sharedp);
Scope* MovingTracer::onScopeEdge(Scope* scope) { return onEdge(scope); }
RegExpShared* MovingTracer::onRegExpSharedEdge(RegExpShared* shared) {
return onEdge(shared);
}
bool MovingTracer::onBigIntEdge(BigInt** bip) { return updateEdge(bip); }
bool MovingTracer::onObjectGroupEdge(ObjectGroup** groupp) {
return updateEdge(groupp);
BigInt* MovingTracer::onBigIntEdge(BigInt* bi) { return onEdge(bi); }
ObjectGroup* MovingTracer::onObjectGroupEdge(ObjectGroup* group) {
return onEdge(group);
}
bool MovingTracer::onSymbolEdge(JS::Symbol** symp) {
MOZ_ASSERT(!(*symp)->isForwarded());
return true;
JS::Symbol* MovingTracer::onSymbolEdge(JS::Symbol* sym) {
MOZ_ASSERT(!sym->isForwarded());
return sym;
}
bool MovingTracer::onJitCodeEdge(jit::JitCode** jitp) {
MOZ_ASSERT(!(*jitp)->isForwarded());
return true;
jit::JitCode* MovingTracer::onJitCodeEdge(jit::JitCode* jit) {
MOZ_ASSERT(!jit->isForwarded());
return jit;
}
void Zone::prepareForCompacting() {
@ -8903,48 +8902,53 @@ js::gc::ClearEdgesTracer::ClearEdgesTracer()
: ClearEdgesTracer(TlsContext.get()->runtime()) {}
template <typename S>
inline bool js::gc::ClearEdgesTracer::clearEdge(S** thingp) {
inline S* js::gc::ClearEdgesTracer::onEdge(S* thing) {
// We don't handle removing pointers to nursery edges from the store buffer
// with this tracer.
MOZ_ASSERT(!IsInsideNursery(*thingp));
// with this tracer. Check that this doesn't happen.
MOZ_ASSERT(!IsInsideNursery(thing));
InternalBarrierMethods<S*>::preBarrier(*thingp);
*thingp = nullptr;
return false;
// Fire the pre-barrier since we're removing an edge from the graph.
InternalBarrierMethods<S*>::preBarrier(thing);
// Return nullptr to clear the edge.
return nullptr;
}
bool js::gc::ClearEdgesTracer::onObjectEdge(JSObject** objp) {
return clearEdge(objp);
JSObject* js::gc::ClearEdgesTracer::onObjectEdge(JSObject* obj) {
return onEdge(obj);
}
bool js::gc::ClearEdgesTracer::onStringEdge(JSString** strp) {
return clearEdge(strp);
JSString* js::gc::ClearEdgesTracer::onStringEdge(JSString* str) {
return onEdge(str);
}
bool js::gc::ClearEdgesTracer::onSymbolEdge(JS::Symbol** symp) {
return clearEdge(symp);
JS::Symbol* js::gc::ClearEdgesTracer::onSymbolEdge(JS::Symbol* sym) {
return onEdge(sym);
}
bool js::gc::ClearEdgesTracer::onBigIntEdge(JS::BigInt** bip) {
return clearEdge(bip);
JS::BigInt* js::gc::ClearEdgesTracer::onBigIntEdge(JS::BigInt* bi) {
return onEdge(bi);
}
bool js::gc::ClearEdgesTracer::onScriptEdge(js::BaseScript** scriptp) {
return clearEdge(scriptp);
js::BaseScript* js::gc::ClearEdgesTracer::onScriptEdge(js::BaseScript* script) {
return onEdge(script);
}
bool js::gc::ClearEdgesTracer::onShapeEdge(js::Shape** shapep) {
return clearEdge(shapep);
js::Shape* js::gc::ClearEdgesTracer::onShapeEdge(js::Shape* shape) {
return onEdge(shape);
}
bool js::gc::ClearEdgesTracer::onObjectGroupEdge(js::ObjectGroup** groupp) {
return clearEdge(groupp);
js::ObjectGroup* js::gc::ClearEdgesTracer::onObjectGroupEdge(
js::ObjectGroup* group) {
return onEdge(group);
}
bool js::gc::ClearEdgesTracer::onBaseShapeEdge(js::BaseShape** basep) {
return clearEdge(basep);
js::BaseShape* js::gc::ClearEdgesTracer::onBaseShapeEdge(js::BaseShape* base) {
return onEdge(base);
}
bool js::gc::ClearEdgesTracer::onJitCodeEdge(js::jit::JitCode** codep) {
return clearEdge(codep);
js::jit::JitCode* js::gc::ClearEdgesTracer::onJitCodeEdge(
js::jit::JitCode* code) {
return onEdge(code);
}
bool js::gc::ClearEdgesTracer::onScopeEdge(js::Scope** scopep) {
return clearEdge(scopep);
js::Scope* js::gc::ClearEdgesTracer::onScopeEdge(js::Scope* scope) {
return onEdge(scope);
}
bool js::gc::ClearEdgesTracer::onRegExpSharedEdge(js::RegExpShared** sharedp) {
return clearEdge(sharedp);
js::RegExpShared* js::gc::ClearEdgesTracer::onRegExpSharedEdge(
js::RegExpShared* shared) {
return onEdge(shared);
}
JS_PUBLIC_API void js::gc::FinalizeDeadNurseryObject(JSContext* cx,

Просмотреть файл

@ -223,21 +223,21 @@ struct MovingTracer final : public GenericTracer {
: GenericTracer(rt, JS::TracerKind::Moving,
JS::WeakMapTraceAction::TraceKeysAndValues) {}
bool onObjectEdge(JSObject** objp) override;
bool onShapeEdge(Shape** shapep) override;
bool onStringEdge(JSString** stringp) override;
bool onScriptEdge(js::BaseScript** scriptp) override;
bool onBaseShapeEdge(BaseShape** basep) override;
bool onScopeEdge(Scope** scopep) override;
bool onRegExpSharedEdge(RegExpShared** sharedp) override;
bool onBigIntEdge(BigInt** bip) override;
bool onObjectGroupEdge(ObjectGroup** groupp) override;
bool onSymbolEdge(JS::Symbol** symp) override;
bool onJitCodeEdge(jit::JitCode** jitp) override;
JSObject* onObjectEdge(JSObject* obj) override;
Shape* onShapeEdge(Shape* shape) override;
JSString* onStringEdge(JSString* string) override;
js::BaseScript* onScriptEdge(js::BaseScript* script) override;
BaseShape* onBaseShapeEdge(BaseShape* base) override;
Scope* onScopeEdge(Scope* scope) override;
RegExpShared* onRegExpSharedEdge(RegExpShared* shared) override;
BigInt* onBigIntEdge(BigInt* bi) override;
ObjectGroup* onObjectGroupEdge(ObjectGroup* group) override;
JS::Symbol* onSymbolEdge(JS::Symbol* sym) override;
jit::JitCode* onJitCodeEdge(jit::JitCode* jit) override;
private:
template <typename T>
bool updateEdge(T** thingp);
T* onEdge(T* thingp);
};
struct SweepingTracer final : public GenericTracer {
@ -245,21 +245,21 @@ struct SweepingTracer final : public GenericTracer {
: GenericTracer(rt, JS::TracerKind::Sweeping,
JS::WeakMapTraceAction::TraceKeysAndValues) {}
bool onObjectEdge(JSObject** objp) override;
bool onShapeEdge(Shape** shapep) override;
bool onStringEdge(JSString** stringp) override;
bool onScriptEdge(js::BaseScript** scriptp) override;
bool onBaseShapeEdge(BaseShape** basep) override;
bool onJitCodeEdge(jit::JitCode** jitp) override;
bool onScopeEdge(Scope** scopep) override;
bool onRegExpSharedEdge(RegExpShared** sharedp) override;
bool onBigIntEdge(BigInt** bip) override;
bool onObjectGroupEdge(js::ObjectGroup** groupp) override;
bool onSymbolEdge(JS::Symbol** symp) override;
JSObject* onObjectEdge(JSObject* obj) override;
Shape* onShapeEdge(Shape* shape) override;
JSString* onStringEdge(JSString* string) override;
js::BaseScript* onScriptEdge(js::BaseScript* script) override;
BaseShape* onBaseShapeEdge(BaseShape* base) override;
jit::JitCode* onJitCodeEdge(jit::JitCode* jit) override;
Scope* onScopeEdge(Scope* scope) override;
RegExpShared* onRegExpSharedEdge(RegExpShared* shared) override;
BigInt* onBigIntEdge(BigInt* bi) override;
js::ObjectGroup* onObjectGroupEdge(js::ObjectGroup* group) override;
JS::Symbol* onSymbolEdge(JS::Symbol* sym) override;
private:
template <typename T>
bool sweepEdge(T** thingp);
T* onEdge(T* thingp);
};
// Structure for counting how many times objects in a particular group have

Просмотреть файл

@ -3774,19 +3774,17 @@ size_t js::TenuringTracer::moveBigIntToTenured(JS::BigInt* dst, JS::BigInt* src,
/*** IsMarked / IsAboutToBeFinalized ****************************************/
template <typename T>
static inline void CheckIsMarkedThing(T* thingp) {
#define IS_SAME_TYPE_OR(name, type, _, _1) std::is_same_v<type*, T> ||
static inline void CheckIsMarkedThing(T* thing) {
#define IS_SAME_TYPE_OR(name, type, _, _1) std::is_same_v<type, T> ||
static_assert(JS_FOR_EACH_TRACEKIND(IS_SAME_TYPE_OR) false,
"Only the base cell layout types are allowed into "
"marking/tracing internals");
#undef IS_SAME_TYPE_OR
#ifdef DEBUG
MOZ_ASSERT(thingp);
MOZ_ASSERT(*thingp);
MOZ_ASSERT(thing);
// Allow any thread access to uncollected things.
T thing = *thingp;
if (thing->isPermanentAndMayBeShared()) {
return;
}
@ -3812,7 +3810,8 @@ static inline void CheckIsMarkedThing(T* thingp) {
template <typename T>
static inline bool ShouldCheckMarkState(JSRuntime* rt, T** thingp) {
CheckIsMarkedThing(thingp);
MOZ_ASSERT(thingp);
CheckIsMarkedThing(*thingp);
MOZ_ASSERT(!IsInsideNursery(*thingp));
TenuredCell& thing = (*thingp)->asTenured();
@ -3863,8 +3862,9 @@ bool js::gc::IsAboutToBeFinalizedInternal(T** thingp) {
// Don't depend on the mark state of other cells during finalization.
MOZ_ASSERT(!CurrentThreadIsGCFinalizing());
CheckIsMarkedThing(thingp);
MOZ_ASSERT(thingp);
T* thing = *thingp;
CheckIsMarkedThing(thing);
JSRuntime* rt = thing->runtimeFromAnyThread();
/* Permanent atoms are never finalized by non-owning runtimes. */
@ -3904,13 +3904,13 @@ bool js::gc::IsAboutToBeFinalizedInternal(T* thingp) {
}
template <typename T>
inline bool SweepingTracer::sweepEdge(T** thingp) {
CheckIsMarkedThing(thingp);
T* thing = *thingp;
inline T* SweepingTracer::onEdge(T* thing) {
CheckIsMarkedThing(thing);
JSRuntime* rt = thing->runtimeFromAnyThread();
if (thing->isPermanentAndMayBeShared() && runtime() != rt) {
return true;
return thing;
}
// TODO: We should assert the zone of the tenured cell is in Sweeping state,
@ -3919,36 +3919,37 @@ inline bool SweepingTracer::sweepEdge(T** thingp) {
// Bug 1071218 : Refactor Debugger::sweepAll and
// JitRuntime::SweepJitcodeGlobalTable to work per sweep group
if (!thing->isMarkedAny()) {
*thingp = nullptr;
return false;
return nullptr;
}
return true;
return thing;
}
bool SweepingTracer::onObjectEdge(JSObject** objp) { return sweepEdge(objp); }
bool SweepingTracer::onShapeEdge(Shape** shapep) { return sweepEdge(shapep); }
bool SweepingTracer::onStringEdge(JSString** stringp) {
return sweepEdge(stringp);
JSObject* SweepingTracer::onObjectEdge(JSObject* obj) { return onEdge(obj); }
Shape* SweepingTracer::onShapeEdge(Shape* shape) { return onEdge(shape); }
JSString* SweepingTracer::onStringEdge(JSString* string) {
return onEdge(string);
}
bool SweepingTracer::onScriptEdge(js::BaseScript** scriptp) {
return sweepEdge(scriptp);
js::BaseScript* SweepingTracer::onScriptEdge(js::BaseScript* script) {
return onEdge(script);
}
bool SweepingTracer::onBaseShapeEdge(BaseShape** basep) {
return sweepEdge(basep);
BaseShape* SweepingTracer::onBaseShapeEdge(BaseShape* base) {
return onEdge(base);
}
bool SweepingTracer::onJitCodeEdge(jit::JitCode** jitp) {
return sweepEdge(jitp);
jit::JitCode* SweepingTracer::onJitCodeEdge(jit::JitCode* jit) {
return onEdge(jit);
}
bool SweepingTracer::onScopeEdge(Scope** scopep) { return sweepEdge(scopep); }
bool SweepingTracer::onRegExpSharedEdge(RegExpShared** sharedp) {
return sweepEdge(sharedp);
Scope* SweepingTracer::onScopeEdge(Scope* scope) { return onEdge(scope); }
RegExpShared* SweepingTracer::onRegExpSharedEdge(RegExpShared* shared) {
return onEdge(shared);
}
bool SweepingTracer::onObjectGroupEdge(ObjectGroup** groupp) {
return sweepEdge(groupp);
ObjectGroup* SweepingTracer::onObjectGroupEdge(ObjectGroup* group) {
return onEdge(group);
}
BigInt* SweepingTracer::onBigIntEdge(BigInt* bi) { return onEdge(bi); }
JS::Symbol* SweepingTracer::onSymbolEdge(JS::Symbol* sym) {
return onEdge(sym);
}
bool SweepingTracer::onBigIntEdge(BigInt** bip) { return sweepEdge(bip); }
bool SweepingTracer::onSymbolEdge(JS::Symbol** symp) { return sweepEdge(symp); }
namespace js {
namespace gc {

Просмотреть файл

@ -496,37 +496,47 @@ class BufferGrayRootsTracer final : public GenericTracer {
// Set to false if we OOM while buffering gray roots.
bool bufferingGrayRootsFailed;
bool onObjectEdge(JSObject** objp) override { return bufferRoot(*objp); }
bool onStringEdge(JSString** stringp) override {
return bufferRoot(*stringp);
JSObject* onObjectEdge(JSObject* obj) override { return bufferRoot(obj); }
JSString* onStringEdge(JSString* string) override {
return bufferRoot(string);
}
bool onScriptEdge(js::BaseScript** scriptp) override {
return bufferRoot(*scriptp);
js::BaseScript* onScriptEdge(js::BaseScript* script) override {
return bufferRoot(script);
}
bool onSymbolEdge(JS::Symbol** symbolp) override {
return bufferRoot(*symbolp);
JS::Symbol* onSymbolEdge(JS::Symbol* symbol) override {
return bufferRoot(symbol);
}
bool onBigIntEdge(JS::BigInt** bip) override { return bufferRoot(*bip); }
JS::BigInt* onBigIntEdge(JS::BigInt* bi) override { return bufferRoot(bi); }
bool onShapeEdge(js::Shape** shapep) override { return unsupportedEdge(); }
bool onObjectGroupEdge(js::ObjectGroup** groupp) override {
return unsupportedEdge();
js::Shape* onShapeEdge(js::Shape* shape) override {
unsupportedEdge();
return nullptr;
}
bool onBaseShapeEdge(js::BaseShape** basep) override {
return unsupportedEdge();
js::ObjectGroup* onObjectGroupEdge(js::ObjectGroup* group) override {
unsupportedEdge();
return nullptr;
}
bool onJitCodeEdge(js::jit::JitCode** codep) override {
return unsupportedEdge();
js::BaseShape* onBaseShapeEdge(js::BaseShape* base) override {
unsupportedEdge();
return nullptr;
}
bool onScopeEdge(js::Scope** scopep) override { return unsupportedEdge(); }
bool onRegExpSharedEdge(js::RegExpShared** sharedp) override {
return unsupportedEdge();
js::jit::JitCode* onJitCodeEdge(js::jit::JitCode* code) override {
unsupportedEdge();
return nullptr;
}
js::Scope* onScopeEdge(js::Scope* scope) override {
unsupportedEdge();
return nullptr;
}
js::RegExpShared* onRegExpSharedEdge(js::RegExpShared* shared) override {
unsupportedEdge();
return nullptr;
}
bool unsupportedEdge() { MOZ_CRASH("Unsupported gray root edge kind"); }
void unsupportedEdge() { MOZ_CRASH("Unsupported gray root edge kind"); }
template <typename T>
inline bool bufferRoot(T* thing);
inline T* bufferRoot(T* thing);
public:
explicit BufferGrayRootsTracer(JSRuntime* rt)
@ -560,7 +570,7 @@ void js::gc::GCRuntime::bufferGrayRoots() {
}
template <typename T>
inline bool BufferGrayRootsTracer::bufferRoot(T* thing) {
inline T* BufferGrayRootsTracer::bufferRoot(T* thing) {
MOZ_ASSERT(JS::RuntimeHeapIsBusy());
MOZ_ASSERT(thing);
// Check if |thing| is corrupt by calling a method that touches the heap.
@ -583,7 +593,7 @@ inline bool BufferGrayRootsTracer::bufferRoot(T* thing) {
}
}
return true;
return thing;
}
void GCRuntime::markBufferedGrayRoots(JS::Zone* zone) {

Просмотреть файл

@ -38,42 +38,46 @@ void CheckTracedThing(JSTracer* trc, T thing);
/*** Callback Tracer Dispatch ***********************************************/
static inline bool DispatchToOnEdge(GenericTracer* trc, JSObject** objp) {
return trc->onObjectEdge(objp);
static inline JSObject* DispatchToOnEdge(GenericTracer* trc, JSObject* obj) {
return trc->onObjectEdge(obj);
}
static inline bool DispatchToOnEdge(GenericTracer* trc, JSString** strp) {
return trc->onStringEdge(strp);
static inline JSString* DispatchToOnEdge(GenericTracer* trc, JSString* str) {
return trc->onStringEdge(str);
}
static inline bool DispatchToOnEdge(GenericTracer* trc, JS::Symbol** symp) {
return trc->onSymbolEdge(symp);
static inline JS::Symbol* DispatchToOnEdge(GenericTracer* trc,
JS::Symbol* sym) {
return trc->onSymbolEdge(sym);
}
static inline bool DispatchToOnEdge(GenericTracer* trc, JS::BigInt** bip) {
return trc->onBigIntEdge(bip);
static inline JS::BigInt* DispatchToOnEdge(GenericTracer* trc, JS::BigInt* bi) {
return trc->onBigIntEdge(bi);
}
static inline bool DispatchToOnEdge(GenericTracer* trc,
js::BaseScript** scriptp) {
return trc->onScriptEdge(scriptp);
static inline js::BaseScript* DispatchToOnEdge(GenericTracer* trc,
js::BaseScript* script) {
return trc->onScriptEdge(script);
}
static inline bool DispatchToOnEdge(GenericTracer* trc, js::Shape** shapep) {
return trc->onShapeEdge(shapep);
static inline js::Shape* DispatchToOnEdge(GenericTracer* trc,
js::Shape* shape) {
return trc->onShapeEdge(shape);
}
static inline bool DispatchToOnEdge(GenericTracer* trc,
js::ObjectGroup** groupp) {
return trc->onObjectGroupEdge(groupp);
static inline js::ObjectGroup* DispatchToOnEdge(GenericTracer* trc,
js::ObjectGroup* group) {
return trc->onObjectGroupEdge(group);
}
static inline bool DispatchToOnEdge(GenericTracer* trc, js::BaseShape** basep) {
return trc->onBaseShapeEdge(basep);
static inline js::BaseShape* DispatchToOnEdge(GenericTracer* trc,
js::BaseShape* base) {
return trc->onBaseShapeEdge(base);
}
static inline bool DispatchToOnEdge(GenericTracer* trc,
js::jit::JitCode** codep) {
return trc->onJitCodeEdge(codep);
static inline js::jit::JitCode* DispatchToOnEdge(GenericTracer* trc,
js::jit::JitCode* code) {
return trc->onJitCodeEdge(code);
}
static inline bool DispatchToOnEdge(GenericTracer* trc, js::Scope** scopep) {
return trc->onScopeEdge(scopep);
static inline js::Scope* DispatchToOnEdge(GenericTracer* trc,
js::Scope* scope) {
return trc->onScopeEdge(scope);
}
static inline bool DispatchToOnEdge(GenericTracer* trc,
js::RegExpShared** sharedp) {
return trc->onRegExpSharedEdge(sharedp);
static inline js::RegExpShared* DispatchToOnEdge(GenericTracer* trc,
js::RegExpShared* shared) {
return trc->onRegExpSharedEdge(shared);
}
template <typename T>
@ -81,7 +85,13 @@ bool DoCallback(GenericTracer* trc, T** thingp, const char* name) {
CheckTracedThing(trc, *thingp);
JS::AutoTracingName ctx(trc, name);
return DispatchToOnEdge(trc, thingp);
T* thing = *thingp;
T* post = DispatchToOnEdge(trc, thing);
if (post != thing) {
*thingp = post;
}
return post;
}
#define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(name, type, _, _1) \
template bool DoCallback<type>(GenericTracer*, type**, const char*);
@ -90,21 +100,29 @@ JS_FOR_EACH_TRACEKIND(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS);
template <typename T>
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, name, &ret](auto t) {
if (!DoCallback(trc, &t, name)) {
auto thing = MapGCThingTyped(*thingp, [trc, &ret](auto thing) {
CheckTracedThing(trc, thing);
auto* post = DispatchToOnEdge(trc, thing);
if (!post) {
ret = false;
return TaggedPtr<T>::empty();
}
return TaggedPtr<T>::wrap(t);
return TaggedPtr<T>::wrap(post);
});
// Only update *thingp if the value changed, to avoid TSan false positives for
// template objects when using DumpHeapTracer or UbiNode tracers while Ion
// compiling off-thread.
if (thing.isSome() && thing.value() != *thingp) {
*thingp = thing.value();
}
return ret;
}
template bool DoCallback<JS::Value>(GenericTracer*, JS::Value*, const char*);