diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 8239e669dd65..7b8a36740f61 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -1007,24 +1007,6 @@ gc::MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name) MarkValueInternal(trc, v); } -bool -gc::IsCellMarked(Cell **thingp) -{ - return IsMarked(thingp); -} - -bool -gc::IsCellAboutToBeFinalized(Cell **thingp) -{ - return IsAboutToBeFinalized(thingp); -} - -bool -gc::IsCellAboutToBeFinalizedFromAnyThread(Cell **thingp) -{ - return IsAboutToBeFinalizedFromAnyThread(thingp); -} - /*** Push Mark Stack ***/ #define JS_COMPARTMENT_ASSERT(rt, thing) \ diff --git a/js/src/gc/Marking.h b/js/src/gc/Marking.h index 4d67bc900f32..2f489ecd86fd 100644 --- a/js/src/gc/Marking.h +++ b/js/src/gc/Marking.h @@ -320,15 +320,6 @@ Mark(JSTracer *trc, ScopeObject **obj, const char *name) MarkObjectUnbarriered(trc, obj, name); } -bool -IsCellMarked(Cell **thingp); - -bool -IsCellAboutToBeFinalized(Cell **thing); - -bool -IsCellAboutToBeFinalizedFromAnyThread(Cell **thing); - inline bool IsMarked(BarrieredBase *v) { diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index f35edc0f9ff3..be51b6d50c04 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -203,8 +203,15 @@ class WrapperMapRef : public BufferableRef CrossCompartmentKey prior = key; if (key.debugger) Mark(trc, &key.debugger, "CCW debugger"); - if (key.kind != CrossCompartmentKey::StringWrapper) + if (key.kind == CrossCompartmentKey::ObjectWrapper || + key.kind == CrossCompartmentKey::DebuggerObject || + key.kind == CrossCompartmentKey::DebuggerEnvironment || + key.kind == CrossCompartmentKey::DebuggerSource) + { + MOZ_ASSERT(IsInsideNursery(key.wrapped) || + key.wrapped->asTenured().getTraceKind() == JSTRACE_OBJECT); Mark(trc, reinterpret_cast(&key.wrapped), "CCW wrapped object"); + } if (key.debugger == prior.debugger && key.wrapped == prior.wrapped) return; @@ -630,7 +637,30 @@ JSCompartment::sweepCrossCompartmentWrappers() /* Remove dead wrappers from the table. */ for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) { CrossCompartmentKey key = e.front().key(); - bool keyDying = IsCellAboutToBeFinalizedFromAnyThread(&key.wrapped); + bool keyDying; + switch (key.kind) { + case CrossCompartmentKey::ObjectWrapper: + case CrossCompartmentKey::DebuggerObject: + case CrossCompartmentKey::DebuggerEnvironment: + case CrossCompartmentKey::DebuggerSource: + MOZ_ASSERT(IsInsideNursery(key.wrapped) || + key.wrapped->asTenured().getTraceKind() == JSTRACE_OBJECT); + keyDying = IsObjectAboutToBeFinalizedFromAnyThread( + reinterpret_cast(&key.wrapped)); + break; + case CrossCompartmentKey::StringWrapper: + MOZ_ASSERT(key.wrapped->asTenured().getTraceKind() == JSTRACE_STRING); + keyDying = IsStringAboutToBeFinalizedFromAnyThread( + reinterpret_cast(&key.wrapped)); + break; + case CrossCompartmentKey::DebuggerScript: + MOZ_ASSERT(key.wrapped->asTenured().getTraceKind() == JSTRACE_SCRIPT); + keyDying = IsScriptAboutToBeFinalizedFromAnyThread( + reinterpret_cast(&key.wrapped)); + break; + default: + MOZ_CRASH("Unknown key kind"); + } bool valDying = IsValueAboutToBeFinalizedFromAnyThread(e.front().value().unsafeGet()); bool dbgDying = key.debugger && IsObjectAboutToBeFinalizedFromAnyThread(&key.debugger); if (keyDying || valDying || dbgDying) { diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index c291df45d850..2871070a1353 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -1935,13 +1935,6 @@ CanRelocateAllocKind(AllocKind kind) return kind <= FINALIZE_OBJECT_LAST; } -static bool -CanRelocateTraceKind(JSGCTraceKind kind) -{ - return kind == JSTRACE_OBJECT; -} - - size_t ArenaHeader::countFreeCells() { size_t count = 0; @@ -2255,21 +2248,16 @@ void MovingTracer::Visit(JSTracer *jstrc, void **thingp, JSGCTraceKind kind) { TenuredCell *thing = TenuredCell::fromPointer(*thingp); - if (!CanRelocateTraceKind(kind)) { - MOZ_ASSERT(!IsForwarded(thing)); + + // Currently we only relocate objects. + if (kind != JSTRACE_OBJECT) { + MOZ_ASSERT(!RelocationOverlay::isCellForwarded(thing)); return; } - Zone *zone = thing->zoneFromAnyThread(); - if (!zone->isGCCompacting()) { - MOZ_ASSERT(!IsForwarded(thing)); - return; - } - - if (IsForwarded(thing)) { - Cell *dst = Forwarded(thing); - *thingp = dst; - } + JSObject *obj = reinterpret_cast(thing); + if (IsForwarded(obj)) + *thingp = Forwarded(obj); } void @@ -5506,7 +5494,7 @@ GCRuntime::compactPhase(bool lastGC, JS::gcreason::Reason reason) for (ArenaHeader *arena = relocatedList; arena; arena = arena->next) { for (ArenaCellIterUnderFinalize i(arena); !i.done(); i.next()) { TenuredCell *src = i.getCell(); - MOZ_ASSERT(IsForwarded(src)); + MOZ_ASSERT(RelocationOverlay::isCellForwarded(src)); TenuredCell *dest = Forwarded(src); MOZ_ASSERT(src->isMarked(BLACK) == dest->isMarked(BLACK)); MOZ_ASSERT(src->isMarked(GRAY) == dest->isMarked(GRAY)); diff --git a/js/src/jsgc.h b/js/src/jsgc.h index a49bc4720553..0de539582a00 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -1182,6 +1182,10 @@ class RelocationOverlay RelocationOverlay *next() const { return next_; } + + static bool isCellForwarded(Cell *cell) { + return fromCell(cell)->isForwarded(); + } }; /* Functions for checking and updating things that might be moved by compacting GC. */ @@ -1193,7 +1197,6 @@ class RelocationOverlay return value; \ } \ -TYPE_MIGHT_BE_FORWARDED(Cell, true) TYPE_MIGHT_BE_FORWARDED(JSObject, true) TYPE_MIGHT_BE_FORWARDED(JSString, false) TYPE_MIGHT_BE_FORWARDED(JS::Symbol, false) @@ -1272,7 +1275,7 @@ inline void CheckGCThingAfterMovingGC(T *t) { MOZ_ASSERT_IF(t, !IsInsideNursery(t)); - MOZ_ASSERT_IF(t, !IsForwarded(t)); + MOZ_ASSERT_IF(t, !RelocationOverlay::isCellForwarded(t)); } inline void diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp index 021a703ca12a..e55a39a50b5a 100644 --- a/js/src/vm/TypeInference.cpp +++ b/js/src/vm/TypeInference.cpp @@ -3073,11 +3073,20 @@ js::TypeMonitorCallSlow(JSContext *cx, JSObject *callee, const CallArgs &args, b static inline bool IsAboutToBeFinalized(TypeSet::ObjectKey **keyp) { - // Mask out the low bit indicating whether this is a group or JS object. - uintptr_t flagBit = uintptr_t(*keyp) & 1; - gc::Cell *tmp = reinterpret_cast(uintptr_t(*keyp) & ~1); - bool isAboutToBeFinalized = IsCellAboutToBeFinalized(&tmp); - *keyp = reinterpret_cast(uintptr_t(tmp) | flagBit); + TypeSet::ObjectKey *key = *keyp; + bool isAboutToBeFinalized; + if (key->isGroup()) { + ObjectGroup *group = key->groupNoBarrier(); + isAboutToBeFinalized = IsObjectGroupAboutToBeFinalized(&group); + if (!isAboutToBeFinalized) + *keyp = TypeSet::ObjectKey::get(group); + } else { + MOZ_ASSERT(key->isSingleton()); + JSObject *singleton = key->singletonNoBarrier(); + isAboutToBeFinalized = IsObjectAboutToBeFinalized(&singleton); + if (!isAboutToBeFinalized) + *keyp = TypeSet::ObjectKey::get(singleton); + } return isAboutToBeFinalized; }