зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
2eb7622b4a
Коммит
16aaee1d65
|
@ -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
|
||||||
|
|
108
js/src/gc/GC.cpp
108
js/src/gc/GC.cpp
|
@ -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*);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче