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

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

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

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

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

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

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

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

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

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

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