mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1154085 - Move eager scanning under the ambit of GCMarker::traverse; r=sfink
This commit is contained in:
parent
a4f65244cc
commit
7dd975f78d
@ -42,15 +42,11 @@ void * const js::NullPtr::constNullValue = nullptr;
|
||||
|
||||
JS_PUBLIC_DATA(void * const) JS::NullPtr::constNullValue = nullptr;
|
||||
|
||||
static inline void
|
||||
static void
|
||||
PushMarkStack(GCMarker* gcmarker, JSObject* thing) {
|
||||
gcmarker->traverse(thing);
|
||||
}
|
||||
static inline void
|
||||
PushMarkStack(GCMarker* gcmarker, JSFunction* thing) {
|
||||
gcmarker->traverse(static_cast<JSObject*>(thing));
|
||||
}
|
||||
static inline void
|
||||
static void
|
||||
PushMarkStack(GCMarker* gcmarker, ObjectGroup* thing) {
|
||||
gcmarker->traverse(thing);
|
||||
}
|
||||
@ -58,23 +54,38 @@ static void
|
||||
PushMarkStack(GCMarker* gcmarker, jit::JitCode* thing) {
|
||||
gcmarker->traverse(thing);
|
||||
}
|
||||
static inline void
|
||||
static void
|
||||
PushMarkStack(GCMarker* gcmarker, JSScript* thing) {
|
||||
gcmarker->traverse(thing);
|
||||
}
|
||||
static inline void
|
||||
static void
|
||||
PushMarkStack(GCMarker* gcmarker, LazyScript* thing) {
|
||||
gcmarker->traverse(thing);
|
||||
}
|
||||
static void
|
||||
PushMarkStack(GCMarker* gcmarker, Shape* thing) {
|
||||
gcmarker->traverse(thing);
|
||||
}
|
||||
static void
|
||||
PushMarkStack(GCMarker* gcmarker, BaseShape* thing) {
|
||||
gcmarker->traverse(thing);
|
||||
}
|
||||
static void
|
||||
PushMarkStack(GCMarker* gcmarker, JSString* str) {
|
||||
// Permanent atoms might not be associated with this runtime.
|
||||
if (str->isPermanentAtom())
|
||||
return;
|
||||
|
||||
static inline void
|
||||
PushMarkStack(GCMarker* gcmarker, Shape* thing);
|
||||
static inline void
|
||||
PushMarkStack(GCMarker* gcmarker, BaseShape* thing);
|
||||
static inline void
|
||||
PushMarkStack(GCMarker* gcmarker, JSString* thing);
|
||||
static inline void
|
||||
PushMarkStack(GCMarker* gcmarker, JS::Symbol* thing);
|
||||
gcmarker->traverse(str);
|
||||
}
|
||||
static void
|
||||
PushMarkStack(GCMarker* gcmarker, JS::Symbol* sym) {
|
||||
// Well-known symbols might not be associated with this runtime.
|
||||
if (sym->isWellKnownSymbol())
|
||||
return;
|
||||
|
||||
gcmarker->traverse(sym);
|
||||
}
|
||||
|
||||
/*** Object Marking ***/
|
||||
|
||||
@ -236,7 +247,7 @@ CheckMarkedThing<jsid>(JSTracer* trc, jsid id)
|
||||
|
||||
// A C++ version of JSGCTraceKind
|
||||
enum class TraceKind {
|
||||
#define NAMES(name, _) name,
|
||||
#define NAMES(name, _, __) name,
|
||||
FOR_EACH_GC_LAYOUT(NAMES)
|
||||
#undef NAMES
|
||||
};
|
||||
@ -298,7 +309,7 @@ template <typename T,
|
||||
: IsBaseOf<LazyScript, T>::value ? TraceKind::LazyScript
|
||||
: TraceKind::ObjectGroup>
|
||||
struct BaseGCType;
|
||||
#define IMPL_BASE_GC_TYPE(name, type_) \
|
||||
#define IMPL_BASE_GC_TYPE(name, type_, _) \
|
||||
template <typename T> struct BaseGCType<T, TraceKind:: name> { typedef type_ type; };
|
||||
FOR_EACH_GC_LAYOUT(IMPL_BASE_GC_TYPE);
|
||||
#undef IMPL_BASE_GC_TYPE
|
||||
@ -412,7 +423,7 @@ template <typename T>
|
||||
void
|
||||
DispatchToTracer(JSTracer* trc, T* thingp, const char* name)
|
||||
{
|
||||
#define IS_SAME_TYPE_OR(name, type) mozilla::IsSame<type*, T>::value ||
|
||||
#define IS_SAME_TYPE_OR(name, type, _) mozilla::IsSame<type*, T>::value ||
|
||||
static_assert(
|
||||
FOR_EACH_GC_LAYOUT(IS_SAME_TYPE_OR)
|
||||
mozilla::IsSame<T, JS::Value>::value ||
|
||||
@ -550,7 +561,7 @@ template <typename T>
|
||||
static inline void
|
||||
CheckIsMarkedThing(T* thingp)
|
||||
{
|
||||
#define IS_SAME_TYPE_OR(name, type) mozilla::IsSame<type*, T>::value ||
|
||||
#define IS_SAME_TYPE_OR(name, type, _) mozilla::IsSame<type*, T>::value ||
|
||||
static_assert(
|
||||
FOR_EACH_GC_LAYOUT(IS_SAME_TYPE_OR)
|
||||
false, "Only the base cell layout types are allowed into marking/tracing internals");
|
||||
@ -930,23 +941,6 @@ MaybePushMarkStackBetweenSlices(GCMarker* gcmarker, JSObject* thing)
|
||||
gcmarker->traverse(thing);
|
||||
}
|
||||
|
||||
static void
|
||||
ScanShape(GCMarker* gcmarker, Shape* shape);
|
||||
|
||||
static void
|
||||
PushMarkStack(GCMarker* gcmarker, Shape* thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), thing);
|
||||
MOZ_ASSERT(!IsInsideNursery(thing));
|
||||
|
||||
/* We mark shapes directly rather than pushing on the stack. */
|
||||
if (thing->markIfUnmarked(gcmarker->markColor()))
|
||||
ScanShape(gcmarker, thing);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ScanBaseShape(GCMarker* gcmarker, BaseShape* base);
|
||||
|
||||
void
|
||||
BaseShape::traceChildren(JSTracer* trc)
|
||||
{
|
||||
@ -958,49 +952,38 @@ BaseShape::traceChildren(JSTracer* trc)
|
||||
TraceManuallyBarrieredEdge(trc, &global, "global");
|
||||
}
|
||||
|
||||
static void
|
||||
PushMarkStack(GCMarker* gcmarker, BaseShape* thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), thing);
|
||||
MOZ_ASSERT(!IsInsideNursery(thing));
|
||||
|
||||
/* We mark base shapes directly rather than pushing on the stack. */
|
||||
if (thing->markIfUnmarked(gcmarker->markColor()))
|
||||
ScanBaseShape(gcmarker, thing);
|
||||
}
|
||||
|
||||
static void
|
||||
ScanShape(GCMarker* gcmarker, Shape* shape)
|
||||
inline void
|
||||
GCMarker::eagerlyMarkChildren(Shape* shape)
|
||||
{
|
||||
restart:
|
||||
PushMarkStack(gcmarker, shape->base());
|
||||
PushMarkStack(this, shape->base());
|
||||
|
||||
const BarrieredBase<jsid>& id = shape->propidRef();
|
||||
if (JSID_IS_STRING(id))
|
||||
PushMarkStack(gcmarker, JSID_TO_STRING(id));
|
||||
PushMarkStack(this, JSID_TO_STRING(id));
|
||||
else if (JSID_IS_SYMBOL(id))
|
||||
PushMarkStack(gcmarker, JSID_TO_SYMBOL(id));
|
||||
PushMarkStack(this, JSID_TO_SYMBOL(id));
|
||||
|
||||
if (shape->hasGetterObject())
|
||||
MaybePushMarkStackBetweenSlices(gcmarker, shape->getterObject());
|
||||
MaybePushMarkStackBetweenSlices(this, shape->getterObject());
|
||||
|
||||
if (shape->hasSetterObject())
|
||||
MaybePushMarkStackBetweenSlices(gcmarker, shape->setterObject());
|
||||
MaybePushMarkStackBetweenSlices(this, shape->setterObject());
|
||||
|
||||
shape = shape->previous();
|
||||
if (shape && shape->markIfUnmarked(gcmarker->markColor()))
|
||||
if (shape && shape->markIfUnmarked(this->markColor()))
|
||||
goto restart;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ScanBaseShape(GCMarker* gcmarker, BaseShape* base)
|
||||
inline void
|
||||
GCMarker::eagerlyMarkChildren(BaseShape* base)
|
||||
{
|
||||
base->assertConsistency();
|
||||
|
||||
base->compartment()->mark();
|
||||
|
||||
if (GlobalObject* global = base->compartment()->unsafeUnbarrieredMaybeGlobal())
|
||||
gcmarker->traverse(global);
|
||||
traverse(global);
|
||||
|
||||
/*
|
||||
* All children of the owned base shape are consistent with its
|
||||
@ -1010,7 +993,7 @@ ScanBaseShape(GCMarker* gcmarker, BaseShape* base)
|
||||
if (base->isOwned()) {
|
||||
UnownedBaseShape* unowned = base->baseUnowned();
|
||||
MOZ_ASSERT(base->compartment() == unowned->compartment());
|
||||
unowned->markIfUnmarked(gcmarker->markColor());
|
||||
unowned->markIfUnmarked(markColor());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1091,52 +1074,20 @@ ScanRope(GCMarker* gcmarker, JSRope* rope)
|
||||
MOZ_ASSERT(savedPos == gcmarker->stack.position());
|
||||
}
|
||||
|
||||
static inline void
|
||||
ScanString(GCMarker* gcmarker, JSString* str)
|
||||
inline void
|
||||
GCMarker::eagerlyMarkChildren(JSString* str)
|
||||
{
|
||||
if (str->isLinear())
|
||||
ScanLinearString(gcmarker, &str->asLinear());
|
||||
ScanLinearString(this, &str->asLinear());
|
||||
else
|
||||
ScanRope(gcmarker, &str->asRope());
|
||||
ScanRope(this, &str->asRope());
|
||||
}
|
||||
|
||||
static inline void
|
||||
PushMarkStack(GCMarker* gcmarker, JSString* str)
|
||||
{
|
||||
// Permanent atoms might not be associated with this runtime.
|
||||
if (str->isPermanentAtom())
|
||||
return;
|
||||
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), str);
|
||||
|
||||
/*
|
||||
* As string can only refer to other strings we fully scan its GC graph
|
||||
* using the explicit stack when navigating the rope tree to avoid
|
||||
* dealing with strings on the stack in drainMarkStack.
|
||||
*/
|
||||
if (str->markIfUnmarked())
|
||||
ScanString(gcmarker, str);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ScanSymbol(GCMarker* gcmarker, JS::Symbol* sym)
|
||||
inline void
|
||||
GCMarker::eagerlyMarkChildren(JS::Symbol* sym)
|
||||
{
|
||||
if (JSString* desc = sym->description())
|
||||
PushMarkStack(gcmarker, desc);
|
||||
}
|
||||
|
||||
static inline void
|
||||
PushMarkStack(GCMarker* gcmarker, JS::Symbol* sym)
|
||||
{
|
||||
// Well-known symbols might not be associated with this runtime.
|
||||
if (sym->isWellKnownSymbol())
|
||||
return;
|
||||
|
||||
JS_COMPARTMENT_ASSERT(gcmarker->runtime(), sym);
|
||||
MOZ_ASSERT(!IsInsideNursery(sym));
|
||||
|
||||
if (sym->markIfUnmarked())
|
||||
ScanSymbol(gcmarker, sym);
|
||||
PushMarkStack(this, desc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1441,7 +1392,7 @@ GCMarker::markAndScanString(JSObject* source, JSString* str)
|
||||
JS_COMPARTMENT_ASSERT(runtime(), str);
|
||||
MOZ_ASSERT(runtime()->isAtomsZone(str->zone()) || str->zone() == source->zone());
|
||||
if (str->markIfUnmarked())
|
||||
ScanString(this, str);
|
||||
eagerlyMarkChildren(str);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1452,7 +1403,7 @@ GCMarker::markAndScanSymbol(JSObject* source, JS::Symbol* sym)
|
||||
JS_COMPARTMENT_ASSERT(runtime(), sym);
|
||||
MOZ_ASSERT(runtime()->isAtomsZone(sym->zone()) || sym->zone() == source->zone());
|
||||
if (sym->markIfUnmarked())
|
||||
ScanSymbol(this, sym);
|
||||
eagerlyMarkChildren(sym);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1698,6 +1649,17 @@ GCMarker::dispatchToTraceChildren(T* thing)
|
||||
thing->traceChildren(this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
GCMarker::mark(T* thing)
|
||||
{
|
||||
JS_COMPARTMENT_ASSERT(runtime(), thing);
|
||||
MOZ_ASSERT(!IsInsideNursery(gc::TenuredCell::fromPointer(thing)));
|
||||
return gc::ParticipatesInCC<T>::value
|
||||
? gc::TenuredCell::fromPointer(thing)->markIfUnmarked(markColor())
|
||||
: gc::TenuredCell::fromPointer(thing)->markIfUnmarked(gc::BLACK);
|
||||
}
|
||||
|
||||
struct TraceChildrenFunctor {
|
||||
template <typename T>
|
||||
void operator()(JSTracer* trc, void* thing) {
|
||||
|
@ -37,7 +37,7 @@ DoCallback(JS::CallbackTracer* trc, T* thingp, const char* name)
|
||||
JS::AutoTracingName ctx(trc, name);
|
||||
trc->invoke((void**)thingp, kind);
|
||||
}
|
||||
#define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(name, type) \
|
||||
#define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(name, type, _) \
|
||||
template void DoCallback<type*>(JS::CallbackTracer*, type**, const char*);
|
||||
FOR_EACH_GC_LAYOUT(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS);
|
||||
#undef INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS
|
||||
|
@ -161,6 +161,11 @@ class GCMarker : public JSTracer
|
||||
void traverse(JSObject* thing) { markAndPush(ObjectTag, thing); }
|
||||
void traverse(ObjectGroup* thing) { markAndPush(GroupTag, thing); }
|
||||
void traverse(jit::JitCode* thing) { markAndPush(JitCodeTag, thing); }
|
||||
// Mark the given GC thing and then eagerly mark all children.
|
||||
void traverse(Shape* thing) { markAndScan(thing); }
|
||||
void traverse(BaseShape* thing) { markAndScan(thing); }
|
||||
void traverse(JSString* thing) { markAndScan(thing); }
|
||||
void traverse(JS::Symbol* thing) { markAndScan(thing); }
|
||||
// The following traverse methods traverse immediately, go out-of-line to do so.
|
||||
void traverse(JSScript* thing) { markAndTraverse(thing); }
|
||||
void traverse(LazyScript* thing) { markAndTraverse(thing); }
|
||||
@ -250,6 +255,16 @@ class GCMarker : public JSTracer
|
||||
pushTaggedPtr(tag, thing);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void markAndScan(T* thing) {
|
||||
if (mark(thing))
|
||||
eagerlyMarkChildren(thing);
|
||||
}
|
||||
void eagerlyMarkChildren(Shape* shape);
|
||||
void eagerlyMarkChildren(BaseShape* base);
|
||||
void eagerlyMarkChildren(JSString* str);
|
||||
void eagerlyMarkChildren(JS::Symbol* sym);
|
||||
|
||||
template <typename T>
|
||||
void markAndTraverse(T* thing) {
|
||||
if (mark(thing))
|
||||
@ -263,11 +278,7 @@ class GCMarker : public JSTracer
|
||||
// Mark the given GC thing, but do not trace its children. Return true
|
||||
// if the thing became marked.
|
||||
template <typename T>
|
||||
bool mark(T* thing) {
|
||||
JS_COMPARTMENT_ASSERT(runtime(), thing);
|
||||
MOZ_ASSERT(!IsInsideNursery(gc::TenuredCell::fromPointer(thing)));
|
||||
return gc::TenuredCell::fromPointer(thing)->markIfUnmarked(markColor());
|
||||
}
|
||||
bool mark(T* thing);
|
||||
|
||||
void pushTaggedPtr(StackTag tag, void* ptr) {
|
||||
checkZone(ptr);
|
||||
|
@ -24,16 +24,17 @@
|
||||
#include "vm/NativeObject.h"
|
||||
|
||||
#define FOR_EACH_GC_LAYOUT(D) \
|
||||
D(Object, JSObject) \
|
||||
D(String, JSString) \
|
||||
D(Symbol, JS::Symbol) \
|
||||
D(Script, JSScript) \
|
||||
D(AccessorShape, js::AccessorShape) \
|
||||
D(Shape, js::Shape) \
|
||||
D(BaseShape, js::BaseShape) \
|
||||
D(JitCode, js::jit::JitCode) \
|
||||
D(LazyScript, js::LazyScript) \
|
||||
D(ObjectGroup, js::ObjectGroup)
|
||||
/* PrettyName TypeName AddToCCKind */ \
|
||||
D(AccessorShape, js::AccessorShape, true) \
|
||||
D(BaseShape, js::BaseShape, true) \
|
||||
D(JitCode, js::jit::JitCode, true) \
|
||||
D(LazyScript, js::LazyScript, true) \
|
||||
D(Object, JSObject, true) \
|
||||
D(ObjectGroup, js::ObjectGroup, true) \
|
||||
D(Script, JSScript, true) \
|
||||
D(Shape, js::Shape, true) \
|
||||
D(String, JSString, false) \
|
||||
D(Symbol, JS::Symbol, false)
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -84,6 +85,12 @@ template <> struct MapTypeToFinalizeKind<JSExternalString> { static const Alloc
|
||||
template <> struct MapTypeToFinalizeKind<JS::Symbol> { static const AllocKind kind = AllocKind::SYMBOL; };
|
||||
template <> struct MapTypeToFinalizeKind<jit::JitCode> { static const AllocKind kind = AllocKind::JITCODE; };
|
||||
|
||||
template <typename T> struct ParticipatesInCC {};
|
||||
#define EXPAND_PARTICIPATES_IN_CC(_, type, addToCCKind) \
|
||||
template <> struct ParticipatesInCC<type> { static const bool value = addToCCKind; };
|
||||
FOR_EACH_GC_LAYOUT(EXPAND_PARTICIPATES_IN_CC)
|
||||
#undef EXPAND_PARTICIPATES_IN_CC
|
||||
|
||||
static inline bool
|
||||
IsNurseryAllocable(AllocKind kind)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user