mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-05 16:22:53 +00:00
Backed out changeset 2a694bf4a9de (bug 1323241) for causing frequent GC crashes in CI.
This commit is contained in:
parent
e9ea578bba
commit
f35d8f4f3b
@ -644,12 +644,12 @@ ExposeGCThingToActiveJS(JS::GCCellPtr thing)
|
||||
if (thing.mayBeOwnedByOtherRuntime())
|
||||
return;
|
||||
|
||||
JS::shadow::Runtime* rt = detail::GetCellRuntime(thing.asCell());
|
||||
JS::shadow::Runtime* rt = detail::GetGCThingRuntime(thing.unsafeAsUIntPtr());
|
||||
MOZ_DIAGNOSTIC_ASSERT(rt->allowGCBarriers());
|
||||
|
||||
if (IsIncrementalBarrierNeededOnTenuredGCThing(rt, thing))
|
||||
JS::IncrementalReferenceBarrier(thing);
|
||||
else if (!thing.mayBeOwnedByOtherRuntime() && js::gc::detail::CellIsMarkedGray(thing.asCell()))
|
||||
else if (JS::GCThingIsMarkedGray(thing))
|
||||
JS::UnmarkGrayGCThingRecursively(thing);
|
||||
}
|
||||
|
||||
|
@ -280,6 +280,14 @@ GetGCThingMarkBitmap(const uintptr_t addr)
|
||||
return reinterpret_cast<uintptr_t*>(bmap_addr);
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE JS::shadow::Runtime*
|
||||
GetGCThingRuntime(const uintptr_t addr)
|
||||
{
|
||||
MOZ_ASSERT(addr);
|
||||
const uintptr_t rt_addr = (addr & ~ChunkMask) | ChunkRuntimeOffset;
|
||||
return *reinterpret_cast<JS::shadow::Runtime**>(rt_addr);
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
GetGCThingMarkWordAndMask(const uintptr_t addr, uint32_t color,
|
||||
uintptr_t** wordp, uintptr_t* maskp)
|
||||
@ -302,35 +310,16 @@ GetGCThingZone(const uintptr_t addr)
|
||||
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE JS::shadow::Runtime*
|
||||
GetCellRuntime(const Cell* cell)
|
||||
{
|
||||
MOZ_ASSERT(cell);
|
||||
const uintptr_t addr = uintptr_t(cell);
|
||||
const uintptr_t rt_addr = (addr & ~ChunkMask) | ChunkRuntimeOffset;
|
||||
return *reinterpret_cast<JS::shadow::Runtime**>(rt_addr);
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
CellIsMarkedGray(const Cell* cell)
|
||||
{
|
||||
MOZ_ASSERT(cell);
|
||||
if (js::gc::IsInsideNursery(cell))
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(!js::gc::IsInsideNursery(cell));
|
||||
uintptr_t* word, mask;
|
||||
js::gc::detail::GetGCThingMarkWordAndMask(uintptr_t(cell), js::gc::GRAY, &word, &mask);
|
||||
return *word & mask;
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
CellIsMarkedGrayIfKnown(const Cell* cell)
|
||||
{
|
||||
MOZ_ASSERT(cell);
|
||||
auto rt = js::gc::detail::GetCellRuntime(cell);
|
||||
return rt->areGCGrayBitsValid() && CellIsMarkedGray(cell);
|
||||
}
|
||||
|
||||
} /* namespace detail */
|
||||
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
@ -370,9 +359,11 @@ GetObjectZone(JSObject* obj);
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
GCThingIsMarkedGray(GCCellPtr thing)
|
||||
{
|
||||
if (js::gc::IsInsideNursery(thing.asCell()))
|
||||
return false;
|
||||
if (thing.mayBeOwnedByOtherRuntime())
|
||||
return false;
|
||||
return js::gc::detail::CellIsMarkedGrayIfKnown(thing.asCell());
|
||||
return js::gc::detail::CellIsMarkedGray(thing.asCell());
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(JS::TraceKind)
|
||||
|
@ -309,8 +309,14 @@ ObjectIsTenured(const Heap<JSObject*>& obj)
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
ObjectIsMarkedGray(JSObject* obj)
|
||||
{
|
||||
auto cell = reinterpret_cast<js::gc::Cell*>(obj);
|
||||
return js::gc::detail::CellIsMarkedGrayIfKnown(cell);
|
||||
/*
|
||||
* GC things residing in the nursery cannot be gray: they have no mark bits.
|
||||
* All live objects in the nursery are moved to tenured at the beginning of
|
||||
* each GC slice, so the gray marker never sees nursery things.
|
||||
*/
|
||||
if (js::gc::IsInsideNursery(reinterpret_cast<js::gc::Cell*>(obj)))
|
||||
return false;
|
||||
return js::gc::detail::CellIsMarkedGray(reinterpret_cast<js::gc::Cell*>(obj));
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
@ -322,8 +328,7 @@ ObjectIsMarkedGray(const JS::Heap<JSObject*>& obj)
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
ScriptIsMarkedGray(JSScript* script)
|
||||
{
|
||||
auto cell = reinterpret_cast<js::gc::Cell*>(script);
|
||||
return js::gc::detail::CellIsMarkedGrayIfKnown(cell);
|
||||
return js::gc::detail::CellIsMarkedGray(reinterpret_cast<js::gc::Cell*>(script));
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
|
@ -816,6 +816,9 @@ class GCRuntime
|
||||
bool isFullGc() const { return isFull; }
|
||||
bool isCompactingGc() const { return isCompacting; }
|
||||
|
||||
bool areGrayBitsValid() const { return grayBitsValid; }
|
||||
void setGrayBitsInvalid() { grayBitsValid = false; }
|
||||
|
||||
bool minorGCRequested() const { return minorGCTriggerReason != JS::gcreason::NO_REASON; }
|
||||
bool majorGCRequested() const { return majorGCTriggerReason != JS::gcreason::NO_REASON; }
|
||||
bool isGcNeeded() { return minorGCRequested() || majorGCRequested(); }
|
||||
@ -1127,6 +1130,12 @@ class GCRuntime
|
||||
resetBufferedGrayRoots();
|
||||
}
|
||||
|
||||
/*
|
||||
* The gray bits can become invalid if UnmarkGray overflows the stack. A
|
||||
* full GC will reset this bit, since it fills in all the gray bits.
|
||||
*/
|
||||
bool grayBitsValid;
|
||||
|
||||
mozilla::Atomic<JS::gcreason::Reason, mozilla::Relaxed> majorGCTriggerReason;
|
||||
|
||||
JS::gcreason::Reason minorGCTriggerReason;
|
||||
|
@ -2917,7 +2917,7 @@ UnmarkGrayTracer::onChild(const JS::GCCellPtr& thing)
|
||||
* If we run out of stack, we take a more drastic measure: require that
|
||||
* we GC again before the next CC.
|
||||
*/
|
||||
runtime()->setGCGrayBitsValid(false);
|
||||
runtime()->gc.setGrayBitsInvalid();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ BEGIN_TEST(testGCCellPtr)
|
||||
JS::GCCellPtr copy = objcell;
|
||||
CHECK(copy == objcell);
|
||||
|
||||
CHECK(js::gc::detail::GetCellRuntime(scriptcell.asCell()) == cx->runtime());
|
||||
CHECK(js::gc::detail::GetGCThingRuntime(scriptcell.unsafeAsUIntPtr()) == cx->runtime());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -597,7 +597,7 @@ js::TraceWeakMaps(WeakMapTracer* trc)
|
||||
extern JS_FRIEND_API(bool)
|
||||
js::AreGCGrayBitsValid(JSContext* cx)
|
||||
{
|
||||
return cx->areGCGrayBitsValid();
|
||||
return cx->gc.areGrayBitsValid();
|
||||
}
|
||||
|
||||
JS_FRIEND_API(bool)
|
||||
|
@ -823,6 +823,7 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
|
||||
numActiveZoneIters(0),
|
||||
cleanUpEverything(false),
|
||||
grayBufferState(GCRuntime::GrayBufferState::Unused),
|
||||
grayBitsValid(false),
|
||||
majorGCTriggerReason(JS::gcreason::NO_REASON),
|
||||
minorGCTriggerReason(JS::gcreason::NO_REASON),
|
||||
fullGCForAtomsRequested_(false),
|
||||
@ -5447,7 +5448,7 @@ GCRuntime::endSweepPhase(bool destroyingRuntime, AutoLockForExclusiveAccess& loc
|
||||
|
||||
/* If we finished a full GC, then the gray bits are correct. */
|
||||
if (isFull)
|
||||
rt->setGCGrayBitsValid(true);
|
||||
grayBitsValid = true;
|
||||
}
|
||||
|
||||
finishMarkingValidation();
|
||||
|
@ -187,16 +187,11 @@ struct Runtime
|
||||
|
||||
js::gc::StoreBuffer* gcStoreBufferPtr_;
|
||||
|
||||
// The gray bits can become invalid if UnmarkGray overflows the stack. A
|
||||
// full GC will reset this bit, since it fills in all the gray bits.
|
||||
bool gcGrayBitsValid_;
|
||||
|
||||
public:
|
||||
Runtime()
|
||||
: heapState_(JS::HeapState::Idle)
|
||||
, allowGCBarriers_(true)
|
||||
, gcStoreBufferPtr_(nullptr)
|
||||
, gcGrayBitsValid_(false)
|
||||
{}
|
||||
|
||||
bool isHeapBusy() const { return heapState() != JS::HeapState::Idle; }
|
||||
@ -212,9 +207,6 @@ struct Runtime
|
||||
|
||||
js::gc::StoreBuffer* gcStoreBufferPtr() { return gcStoreBufferPtr_; }
|
||||
|
||||
bool areGCGrayBitsValid() const { return gcGrayBitsValid_; }
|
||||
void setGCGrayBitsValid(bool valid) { gcGrayBitsValid_ = valid; }
|
||||
|
||||
const JSRuntime* asRuntime() const {
|
||||
return reinterpret_cast<const JSRuntime*>(this);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user