mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1147180 - Introduce a new, strongly-typed tracing path; r=jonco, r=sfink
This commit is contained in:
parent
23e404d42b
commit
b1eef6cb11
@ -119,7 +119,7 @@ class JS_PUBLIC_API(JSTracer)
|
||||
}
|
||||
|
||||
void setTracingName(const char* name) {
|
||||
setTracingDetails(nullptr, (void*)name, size_t(-1));
|
||||
setTracingDetails(nullptr, (void*)name, InvalidIndex);
|
||||
}
|
||||
|
||||
// Remove the currently set tracing details.
|
||||
@ -128,6 +128,8 @@ class JS_PUBLIC_API(JSTracer)
|
||||
debugPrintArg_ = nullptr;
|
||||
}
|
||||
|
||||
const static size_t InvalidIndex = size_t(-1);
|
||||
|
||||
// Return true if tracing details are currently set.
|
||||
bool hasTracingDetails() const;
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "gc/Marking.h"
|
||||
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/IntegerRange.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include "jsprf.h"
|
||||
|
||||
@ -31,6 +33,9 @@ using namespace js;
|
||||
using namespace js::gc;
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::IsBaseOf;
|
||||
using mozilla::IsSame;
|
||||
using mozilla::MakeRange;
|
||||
|
||||
void * const js::NullPtr::constNullValue = nullptr;
|
||||
|
||||
@ -147,24 +152,33 @@ AsGCMarker(JSTracer* trc)
|
||||
return static_cast<GCMarker*>(trc);
|
||||
}
|
||||
|
||||
template <typename T> bool ThingIsPermanentAtom(T* thing) { return false; }
|
||||
template <> bool ThingIsPermanentAtom<JSString>(JSString* str) { return str->isPermanentAtom(); }
|
||||
template <> bool ThingIsPermanentAtom<JSFlatString>(JSFlatString* str) { return str->isPermanentAtom(); }
|
||||
template <> bool ThingIsPermanentAtom<JSLinearString>(JSLinearString* str) { return str->isPermanentAtom(); }
|
||||
template <> bool ThingIsPermanentAtom<JSAtom>(JSAtom* atom) { return atom->isPermanent(); }
|
||||
template <> bool ThingIsPermanentAtom<PropertyName>(PropertyName* name) { return name->isPermanent(); }
|
||||
template <> bool ThingIsPermanentAtom<JS::Symbol>(JS::Symbol* sym) { return sym->isWellKnownSymbol(); }
|
||||
template <typename T> bool ThingIsPermanentAtomOrWellKnownSymbol(T* thing) { return false; }
|
||||
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSString>(JSString* str) {
|
||||
return str->isPermanentAtom();
|
||||
}
|
||||
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSFlatString>(JSFlatString* str) {
|
||||
return str->isPermanentAtom();
|
||||
}
|
||||
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSLinearString>(JSLinearString* str) {
|
||||
return str->isPermanentAtom();
|
||||
}
|
||||
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSAtom>(JSAtom* atom) {
|
||||
return atom->isPermanent();
|
||||
}
|
||||
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<PropertyName>(PropertyName* name) {
|
||||
return name->isPermanent();
|
||||
}
|
||||
template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JS::Symbol>(JS::Symbol* sym) {
|
||||
return sym->isWellKnownSymbol();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline void
|
||||
CheckMarkedThing(JSTracer* trc, T** thingp)
|
||||
CheckMarkedThing(JSTracer* trc, T thing)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(trc);
|
||||
MOZ_ASSERT(thingp);
|
||||
|
||||
T* thing = *thingp;
|
||||
MOZ_ASSERT(*thingp);
|
||||
MOZ_ASSERT(thing);
|
||||
|
||||
thing = MaybeForwarded(thing);
|
||||
|
||||
@ -173,13 +187,13 @@ CheckMarkedThing(JSTracer* trc, T** thingp)
|
||||
return;
|
||||
|
||||
MOZ_ASSERT_IF(!MovingTracer::IsMovingTracer(trc) && !Nursery::IsMinorCollectionTracer(trc),
|
||||
!IsForwarded(*thingp));
|
||||
!IsForwarded(thing));
|
||||
|
||||
/*
|
||||
* Permanent atoms are not associated with this runtime, but will be ignored
|
||||
* during marking.
|
||||
*/
|
||||
if (ThingIsPermanentAtom(thing))
|
||||
if (ThingIsPermanentAtomOrWellKnownSymbol(thing))
|
||||
return;
|
||||
|
||||
Zone* zone = thing->zoneFromAnyThread();
|
||||
@ -189,10 +203,10 @@ CheckMarkedThing(JSTracer* trc, T** thingp)
|
||||
MOZ_ASSERT_IF(!MovingTracer::IsMovingTracer(trc), CurrentThreadCanAccessRuntime(rt));
|
||||
|
||||
MOZ_ASSERT(zone->runtimeFromAnyThread() == trc->runtime());
|
||||
MOZ_ASSERT(trc->hasTracingDetails());
|
||||
|
||||
MOZ_ASSERT(thing->isAligned());
|
||||
MOZ_ASSERT(MapTypeToTraceKind<T>::kind == GetGCThingTraceKind(thing));
|
||||
MOZ_ASSERT(MapTypeToTraceKind<typename mozilla::RemovePointer<T>::Type>::kind ==
|
||||
GetGCThingTraceKind(thing));
|
||||
|
||||
/*
|
||||
* Do not check IsMarkingTracer directly -- it should only be used in paths
|
||||
@ -226,6 +240,37 @@ CheckMarkedThing(JSTracer* trc, T** thingp)
|
||||
#endif
|
||||
}
|
||||
|
||||
template<>
|
||||
void
|
||||
CheckMarkedThing<Value>(JSTracer* trc, Value val)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (val.isString())
|
||||
CheckMarkedThing(trc, val.toString());
|
||||
else if (val.isObject())
|
||||
CheckMarkedThing(trc, &val.toObject());
|
||||
else if (val.isSymbol())
|
||||
CheckMarkedThing(trc, val.toSymbol());
|
||||
#endif
|
||||
}
|
||||
|
||||
template <>
|
||||
void
|
||||
CheckMarkedThing<jsid>(JSTracer* trc, jsid id)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (JSID_IS_STRING(id))
|
||||
CheckMarkedThing(trc, JSID_TO_STRING(id));
|
||||
else if (JSID_IS_SYMBOL(id))
|
||||
CheckMarkedThing(trc, JSID_TO_SYMBOL(id));
|
||||
#endif
|
||||
}
|
||||
|
||||
#define JS_ROOT_MARKING_ASSERT(trc) \
|
||||
MOZ_ASSERT_IF(trc->isMarkingTracer(), \
|
||||
trc->runtime()->gc.state() == NO_INCREMENTAL || \
|
||||
trc->runtime()->gc.state() == MARK_ROOTS);
|
||||
|
||||
/*
|
||||
* We only set the maybeAlive flag for objects and scripts. It's assumed that,
|
||||
* if a compartment is alive, then it will have at least some live object or
|
||||
@ -260,12 +305,328 @@ SetMaybeAliveFlag(JSScript* thing)
|
||||
thing->compartment()->maybeAlive = true;
|
||||
}
|
||||
|
||||
#define FOR_EACH_GC_LAYOUT(D) \
|
||||
D(Object, JSObject) \
|
||||
D(String, JSString) \
|
||||
D(Symbol, JS::Symbol) \
|
||||
D(Script, JSScript) \
|
||||
D(Shape, js::Shape) \
|
||||
D(BaseShape, js::BaseShape) \
|
||||
D(JitCode, js::jit::JitCode) \
|
||||
D(LazyScript, js::LazyScript) \
|
||||
D(ObjectGroup, js::ObjectGroup)
|
||||
|
||||
// A C++ version of JSGCTraceKind
|
||||
enum class TraceKind {
|
||||
#define NAMES(name, _) name,
|
||||
FOR_EACH_GC_LAYOUT(NAMES)
|
||||
#undef NAMES
|
||||
};
|
||||
|
||||
#define FOR_EACH_GC_POINTER_TYPE(D) \
|
||||
D(BaseShape*) \
|
||||
D(UnownedBaseShape*) \
|
||||
D(jit::JitCode*) \
|
||||
D(NativeObject*) \
|
||||
D(ArrayObject*) \
|
||||
D(ArgumentsObject*) \
|
||||
D(ArrayBufferObject*) \
|
||||
D(ArrayBufferObjectMaybeShared*) \
|
||||
D(ArrayBufferViewObject*) \
|
||||
D(DebugScopeObject*) \
|
||||
D(GlobalObject*) \
|
||||
D(JSObject*) \
|
||||
D(JSFunction*) \
|
||||
D(NestedScopeObject*) \
|
||||
D(PlainObject*) \
|
||||
D(SavedFrame*) \
|
||||
D(ScopeObject*) \
|
||||
D(SharedArrayBufferObject*) \
|
||||
D(SharedTypedArrayObject*) \
|
||||
D(JSScript*) \
|
||||
D(LazyScript*) \
|
||||
D(Shape*) \
|
||||
D(JSAtom*) \
|
||||
D(JSString*) \
|
||||
D(JSFlatString*) \
|
||||
D(JSLinearString*) \
|
||||
D(PropertyName*) \
|
||||
D(JS::Symbol*) \
|
||||
D(js::ObjectGroup*) \
|
||||
D(Value) \
|
||||
D(jsid)
|
||||
|
||||
// The second parameter to BaseGCType is derived automatically based on T. The
|
||||
// relation here is that for any T, the TraceKind will automatically,
|
||||
// statically select the correct Cell layout for marking. Below, we instantiate
|
||||
// each override with a declaration of the most derived layout type.
|
||||
//
|
||||
// Usage:
|
||||
// BaseGCType<T>::type
|
||||
//
|
||||
// Examples:
|
||||
// BaseGCType<JSFunction>::type => JSObject
|
||||
// BaseGCType<UnownedBaseShape>::type => BaseShape
|
||||
// etc.
|
||||
template <typename T,
|
||||
TraceKind = IsBaseOf<JSObject, T>::value ? TraceKind::Object
|
||||
: IsBaseOf<JSString, T>::value ? TraceKind::String
|
||||
: IsBaseOf<JS::Symbol, T>::value ? TraceKind::Symbol
|
||||
: IsBaseOf<JSScript, T>::value ? TraceKind::Script
|
||||
: IsBaseOf<Shape, T>::value ? TraceKind::Shape
|
||||
: IsBaseOf<BaseShape, T>::value ? TraceKind::BaseShape
|
||||
: IsBaseOf<jit::JitCode, T>::value ? TraceKind::JitCode
|
||||
: IsBaseOf<LazyScript, T>::value ? TraceKind::LazyScript
|
||||
: TraceKind::ObjectGroup>
|
||||
struct BaseGCType;
|
||||
#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
|
||||
|
||||
// Our barrier templates are parameterized on the pointer types so that we can
|
||||
// share the definitions with Value and jsid. Thus, we need to strip the
|
||||
// pointer before sending the type to BaseGCType and re-add it on the other
|
||||
// side. As such:
|
||||
template <typename T> struct PtrBaseGCType {};
|
||||
template <> struct PtrBaseGCType<Value> { typedef Value type; };
|
||||
template <> struct PtrBaseGCType<jsid> { typedef jsid type; };
|
||||
template <typename T> struct PtrBaseGCType<T*> { typedef typename BaseGCType<T>::type* type; };
|
||||
|
||||
template <typename T> void DispatchToTracer(JSTracer* trc, T* thingp, const char* name, size_t i);
|
||||
template <typename T> void DoTracing(JS::CallbackTracer* trc, T* thingp, const char* name, size_t i);
|
||||
template <typename T> void DoMarking(GCMarker* gcmarker, T thing);
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
js::TraceEdge(JSTracer* trc, BarrieredBase<T>* thingp, const char* name)
|
||||
{
|
||||
auto layout = reinterpret_cast<typename PtrBaseGCType<T>::type*>(thingp->unsafeGet());
|
||||
DispatchToTracer(trc, layout, name, JSTracer::InvalidIndex);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
js::TraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, const char* name)
|
||||
{
|
||||
auto layout = reinterpret_cast<typename PtrBaseGCType<T>::type*>(thingp);
|
||||
DispatchToTracer(trc, layout, name, JSTracer::InvalidIndex);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
js::TraceRoot(JSTracer* trc, T* thingp, const char* name)
|
||||
{
|
||||
JS_ROOT_MARKING_ASSERT(trc);
|
||||
auto layout = reinterpret_cast<typename PtrBaseGCType<T>::type*>(thingp);
|
||||
DispatchToTracer(trc, layout, name, JSTracer::InvalidIndex);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
js::TraceRange(JSTracer* trc, size_t len, BarrieredBase<T>* thingp, const char* name)
|
||||
{
|
||||
for (auto i : MakeRange(len)) {
|
||||
auto layout = reinterpret_cast<typename PtrBaseGCType<T>::type*>(&thingp[i]);
|
||||
DispatchToTracer(trc, layout, name, i);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
js::TraceRootRange(JSTracer* trc, size_t len, T* thingp, const char* name)
|
||||
{
|
||||
JS_ROOT_MARKING_ASSERT(trc);
|
||||
for (auto i : MakeRange(len)) {
|
||||
auto layout = reinterpret_cast<typename PtrBaseGCType<T>::type*>(&thingp[i]);
|
||||
DispatchToTracer(trc, layout, name, i);
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiate a copy of the Tracing templates for each derived type.
|
||||
#define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(type) \
|
||||
template void js::TraceEdge<type>(JSTracer*, BarrieredBase<type>*, const char*); \
|
||||
template void js::TraceManuallyBarrieredEdge<type>(JSTracer*, type*, const char*); \
|
||||
template void js::TraceRoot<type>(JSTracer*, type*, const char*); \
|
||||
template void js::TraceRange<type>(JSTracer*, size_t, BarrieredBase<type>*, const char*); \
|
||||
template void js::TraceRootRange<type>(JSTracer*, size_t, type*, const char*);
|
||||
FOR_EACH_GC_POINTER_TYPE(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS)
|
||||
#undef INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS
|
||||
|
||||
// This method is responsible for dynamic dispatch to the real tracer
|
||||
// implementation. Consider replacing this choke point with virtual dispatch:
|
||||
// a sufficiently smart C++ compiler may be able to devirtualize some paths.
|
||||
template <typename T>
|
||||
void
|
||||
DispatchToTracer(JSTracer* trc, T* thingp, const char* name, size_t i)
|
||||
{
|
||||
#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 ||
|
||||
mozilla::IsSame<T, jsid>::value,
|
||||
"Only the base cell layout types are allowed into marking/tracing internals");
|
||||
#undef IS_SAME_TYPE_OR
|
||||
CheckMarkedThing(trc, *thingp);
|
||||
|
||||
if (trc->isMarkingTracer())
|
||||
return DoMarking(static_cast<GCMarker*>(trc), *thingp);
|
||||
return DoTracing(static_cast<JS::CallbackTracer*>(trc), thingp, name, i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline bool
|
||||
MustSkipMarking(T thing)
|
||||
{
|
||||
// Don't mark things outside a zone if we are in a per-zone GC.
|
||||
return !thing->zone()->isGCMarking();
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
MustSkipMarking<JSObject*>(JSObject* obj)
|
||||
{
|
||||
// We may mark a Nursery thing outside the context of the
|
||||
// MinorCollectionTracer because of a pre-barrier. The pre-barrier is not
|
||||
// needed in this case because we perform a minor collection before each
|
||||
// incremental slice.
|
||||
if (IsInsideNursery(obj))
|
||||
return true;
|
||||
|
||||
// Don't mark things outside a zone if we are in a per-zone GC. It is
|
||||
// faster to check our own arena header, which we can do since we know that
|
||||
// the object is tenured.
|
||||
return !TenuredCell::fromPointer(obj)->zone()->isGCMarking();
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
MustSkipMarking<JSString*>(JSString* str)
|
||||
{
|
||||
// Don't mark permanent atoms, as they may be associated with another
|
||||
// runtime. Note that PushMarkStack() also checks this, but we need to not
|
||||
// run the isGCMarking test from off-main-thread, so have to check it here
|
||||
// too.
|
||||
return str->isPermanentAtom() ||
|
||||
!str->zone()->isGCMarking();
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
MustSkipMarking<JS::Symbol*>(JS::Symbol* sym)
|
||||
{
|
||||
// As for JSString, don't touch a globally owned well-known symbol from
|
||||
// off-main-thread.
|
||||
return sym->isWellKnownSymbol() ||
|
||||
!sym->zone()->isGCMarking();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
DoMarking(GCMarker* gcmarker, T thing)
|
||||
{
|
||||
// Do per-type marking precondition checks.
|
||||
if (MustSkipMarking(thing))
|
||||
return;
|
||||
|
||||
PushMarkStack(gcmarker, thing);
|
||||
|
||||
// Mark the compartment as live.
|
||||
SetMaybeAliveFlag(thing);
|
||||
}
|
||||
|
||||
template <>
|
||||
void
|
||||
DoMarking<Value>(GCMarker* gcmarker, Value val)
|
||||
{
|
||||
if (val.isString())
|
||||
DoMarking(gcmarker, val.toString());
|
||||
else if (val.isObject())
|
||||
DoMarking(gcmarker, &val.toObject());
|
||||
else if (val.isSymbol())
|
||||
DoMarking(gcmarker, val.toSymbol());
|
||||
else
|
||||
gcmarker->clearTracingDetails();
|
||||
}
|
||||
|
||||
template <>
|
||||
void
|
||||
DoMarking<jsid>(GCMarker* gcmarker, jsid id)
|
||||
{
|
||||
if (JSID_IS_STRING(id))
|
||||
DoMarking(gcmarker, JSID_TO_STRING(id));
|
||||
else if (JSID_IS_SYMBOL(id))
|
||||
DoMarking(gcmarker, JSID_TO_SYMBOL(id));
|
||||
else
|
||||
gcmarker->clearTracingDetails();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
DoTracing(JS::CallbackTracer* trc, T* thingp, const char* name, size_t i)
|
||||
{
|
||||
JSGCTraceKind kind = MapTypeToTraceKind<typename mozilla::RemovePointer<T>::Type>::kind;
|
||||
trc->setTracingIndex(name, i);
|
||||
trc->invoke((void**)thingp, kind);
|
||||
trc->unsetTracingLocation();
|
||||
}
|
||||
|
||||
template <>
|
||||
void
|
||||
DoTracing<Value>(JS::CallbackTracer* trc, Value* vp, const char* name, size_t i)
|
||||
{
|
||||
if (vp->isObject()) {
|
||||
JSObject* prior = &vp->toObject();
|
||||
JSObject* obj = prior;
|
||||
DoTracing(trc, &obj, name, i);
|
||||
if (obj != prior)
|
||||
vp->setObjectOrNull(obj);
|
||||
} else if (vp->isString()) {
|
||||
JSString* prior = vp->toString();
|
||||
JSString* str = prior;
|
||||
DoTracing(trc, &str, name, i);
|
||||
if (str != prior)
|
||||
vp->setString(str);
|
||||
} else if (vp->isSymbol()) {
|
||||
JS::Symbol* prior = vp->toSymbol();
|
||||
JS::Symbol* sym = prior;
|
||||
DoTracing(trc, &sym, name, i);
|
||||
if (sym != prior)
|
||||
vp->setSymbol(sym);
|
||||
} else {
|
||||
/* Unset realLocation manually if we do not call MarkInternal. */
|
||||
trc->unsetTracingLocation();
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void
|
||||
DoTracing<jsid>(JS::CallbackTracer* trc, jsid* idp, const char* name, size_t i)
|
||||
{
|
||||
if (JSID_IS_STRING(*idp)) {
|
||||
JSString* prior = JSID_TO_STRING(*idp);
|
||||
JSString* str = prior;
|
||||
DoTracing(trc, &str, name, i);
|
||||
if (str != prior)
|
||||
*idp = NON_INTEGER_ATOM_TO_JSID(reinterpret_cast<JSAtom*>(str));
|
||||
} else if (JSID_IS_SYMBOL(*idp)) {
|
||||
JS::Symbol* prior = JSID_TO_SYMBOL(*idp);
|
||||
JS::Symbol* sym = prior;
|
||||
DoTracing(trc, &sym, name, i);
|
||||
if (sym != prior)
|
||||
*idp = SYMBOL_TO_JSID(sym);
|
||||
} else {
|
||||
/* Unset realLocation manually if we do not call MarkInternal. */
|
||||
trc->unsetTracingLocation();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void
|
||||
MarkInternal(JSTracer* trc, T** thingp)
|
||||
{
|
||||
CheckMarkedThing(trc, thingp);
|
||||
T* thing = *thingp;
|
||||
CheckMarkedThing(trc, thing);
|
||||
|
||||
if (trc->isMarkingTracer()) {
|
||||
/*
|
||||
@ -282,7 +643,7 @@ MarkInternal(JSTracer* trc, T** thingp)
|
||||
* runtime. Note that PushMarkStack() also checks this, but the tests
|
||||
* and maybeAlive write below should only be done on the main thread.
|
||||
*/
|
||||
if (ThingIsPermanentAtom(thing))
|
||||
if (ThingIsPermanentAtomOrWellKnownSymbol(thing))
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -302,11 +663,6 @@ MarkInternal(JSTracer* trc, T** thingp)
|
||||
trc->clearTracingDetails();
|
||||
}
|
||||
|
||||
#define JS_ROOT_MARKING_ASSERT(trc) \
|
||||
MOZ_ASSERT_IF(trc->isMarkingTracer(), \
|
||||
trc->runtime()->gc.state() == NO_INCREMENTAL || \
|
||||
trc->runtime()->gc.state() == MARK_ROOTS);
|
||||
|
||||
namespace js {
|
||||
namespace gc {
|
||||
|
||||
@ -333,7 +689,7 @@ MarkPermanentAtom(JSTracer* trc, JSAtom* atom, const char* name)
|
||||
|
||||
MOZ_ASSERT(atom->isPermanent());
|
||||
|
||||
CheckMarkedThing(trc, &atom);
|
||||
CheckMarkedThing(trc, atom);
|
||||
|
||||
if (trc->isMarkingTracer()) {
|
||||
// Atoms do not refer to other GC things so don't need to go on the mark stack.
|
||||
@ -358,7 +714,7 @@ MarkWellKnownSymbol(JSTracer* trc, JS::Symbol* sym)
|
||||
trc->setTracingName("wellKnownSymbols");
|
||||
|
||||
MOZ_ASSERT(sym->isWellKnownSymbol());
|
||||
CheckMarkedThing(trc, &sym);
|
||||
CheckMarkedThing(trc, sym);
|
||||
if (trc->isMarkingTracer()) {
|
||||
// Permanent atoms are marked before well-known symbols.
|
||||
MOZ_ASSERT(sym->description()->isMarked());
|
||||
@ -417,7 +773,7 @@ template <typename T>
|
||||
static bool
|
||||
IsMarked(T** thingp)
|
||||
{
|
||||
MOZ_ASSERT_IF(!ThingIsPermanentAtom(*thingp),
|
||||
MOZ_ASSERT_IF(!ThingIsPermanentAtomOrWellKnownSymbol(*thingp),
|
||||
CurrentThreadCanAccessRuntime((*thingp)->runtimeFromMainThread()));
|
||||
return IsMarkedFromAnyThread(thingp);
|
||||
}
|
||||
@ -447,7 +803,7 @@ template <typename T>
|
||||
static bool
|
||||
IsAboutToBeFinalized(T** thingp)
|
||||
{
|
||||
MOZ_ASSERT_IF(!ThingIsPermanentAtom(*thingp),
|
||||
MOZ_ASSERT_IF(!ThingIsPermanentAtomOrWellKnownSymbol(*thingp),
|
||||
CurrentThreadCanAccessRuntime((*thingp)->runtimeFromMainThread()));
|
||||
return IsAboutToBeFinalizedFromAnyThread(thingp);
|
||||
}
|
||||
@ -463,7 +819,7 @@ IsAboutToBeFinalizedFromAnyThread(T** thingp)
|
||||
JSRuntime* rt = thing->runtimeFromAnyThread();
|
||||
|
||||
/* Permanent atoms are never finalized by non-owning runtimes. */
|
||||
if (ThingIsPermanentAtom(thing) && !TlsPerThreadData.get()->associatedWith(rt))
|
||||
if (ThingIsPermanentAtomOrWellKnownSymbol(thing) && !TlsPerThreadData.get()->associatedWith(rt))
|
||||
return false;
|
||||
|
||||
Nursery& nursery = rt->gc.nursery;
|
||||
|
@ -37,6 +37,28 @@ struct IonScript;
|
||||
struct VMFunction;
|
||||
}
|
||||
|
||||
/*** Tracing ***/
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
TraceEdge(JSTracer* trc, BarrieredBase<T>* thingp, const char* name);
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
TraceRoot(JSTracer* trc, T* thingp, const char* name);
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
TraceManuallyBarrieredEdge(JSTracer* trc, T* thingp, const char* name);
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
TraceRange(JSTracer* trc, size_t len, BarrieredBase<T>* thingp, const char* name);
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
TraceRootRange(JSTracer* trc, size_t len, T* thingp, const char* name);
|
||||
|
||||
namespace gc {
|
||||
|
||||
/*** Object Marking ***/
|
||||
|
Loading…
Reference in New Issue
Block a user