зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1322420 - Expose cells found via iteration r=sfink a=abillings
This commit is contained in:
Родитель
ec2c66fd1f
Коммит
942694dd48
|
@ -629,8 +629,6 @@ BarriersAreAllowedOnCurrentThread();
|
|||
static MOZ_ALWAYS_INLINE void
|
||||
ExposeGCThingToActiveJS(JS::GCCellPtr thing)
|
||||
{
|
||||
MOZ_ASSERT(thing.kind() != JS::TraceKind::Shape);
|
||||
|
||||
// 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.
|
||||
|
|
|
@ -1057,15 +1057,6 @@ AddLazyFunctionsForCompartment(JSContext* cx, AutoObjectVector& lazyFunctions, A
|
|||
continue;
|
||||
}
|
||||
|
||||
// This creates a new reference to an object that an ongoing incremental
|
||||
// GC may find to be unreachable. Treat as if we're reading a weak
|
||||
// reference and trigger the read barrier.
|
||||
if (cx->zone()->needsIncrementalBarrier())
|
||||
fun->readBarrier(fun);
|
||||
|
||||
// TODO: The above checks should be rolled into the cell iterator (see
|
||||
// bug 1322971).
|
||||
|
||||
if (fun->isInterpretedLazy()) {
|
||||
LazyScript* lazy = fun->lazyScriptOrNull();
|
||||
if (lazy && lazy->sourceObject() && !lazy->hasUncompiledEnclosingScript()) {
|
||||
|
|
|
@ -3560,8 +3560,8 @@ ArenaLists::checkEmptyArenaList(AllocKind kind)
|
|||
max_cells = atol(env);
|
||||
for (Arena* current = arenaLists(kind).head(); current; current = current->next) {
|
||||
for (ArenaCellIterUnderGC i(current); !i.done(); i.next()) {
|
||||
Cell* t = i.get<Cell>();
|
||||
MOZ_ASSERT(t->asTenured().isMarked(), "unmarked cells should have been finalized");
|
||||
TenuredCell* t = i.getCell();
|
||||
MOZ_ASSERT(t->isMarked(), "unmarked cells should have been finalized");
|
||||
if (++num_live <= max_cells) {
|
||||
fprintf(stderr, "ERROR: GC found live Cell %p of kind %s at shutdown\n",
|
||||
t, AllocKindToAscii(kind));
|
||||
|
|
|
@ -102,6 +102,12 @@ class ArenaIter
|
|||
}
|
||||
};
|
||||
|
||||
enum CellIterNeedsBarrier : uint8_t
|
||||
{
|
||||
CellIterDoesntNeedBarrier = 0,
|
||||
CellIterMayNeedBarrier = 1
|
||||
};
|
||||
|
||||
class ArenaCellIterImpl
|
||||
{
|
||||
size_t firstThingOffset;
|
||||
|
@ -109,6 +115,8 @@ class ArenaCellIterImpl
|
|||
Arena* arenaAddr;
|
||||
FreeSpan span;
|
||||
uint_fast16_t thing;
|
||||
JS::TraceKind traceKind;
|
||||
bool needsBarrier;
|
||||
mozilla::DebugOnly<bool> initialized;
|
||||
|
||||
// Upon entry, |thing| points to any thing (free or used) and finds the
|
||||
|
@ -128,17 +136,32 @@ class ArenaCellIterImpl
|
|||
|
||||
public:
|
||||
ArenaCellIterImpl()
|
||||
: firstThingOffset(0), thingSize(0), arenaAddr(nullptr), thing(0), initialized(false) {}
|
||||
: firstThingOffset(0),
|
||||
thingSize(0),
|
||||
arenaAddr(nullptr),
|
||||
thing(0),
|
||||
traceKind(JS::TraceKind::Null),
|
||||
needsBarrier(false),
|
||||
initialized(false)
|
||||
{}
|
||||
|
||||
explicit ArenaCellIterImpl(Arena* arena) : initialized(false) { init(arena); }
|
||||
explicit ArenaCellIterImpl(Arena* arena, CellIterNeedsBarrier mayNeedBarrier)
|
||||
: initialized(false)
|
||||
{
|
||||
init(arena, mayNeedBarrier);
|
||||
}
|
||||
|
||||
void init(Arena* arena) {
|
||||
void init(Arena* arena, CellIterNeedsBarrier mayNeedBarrier) {
|
||||
MOZ_ASSERT(!initialized);
|
||||
MOZ_ASSERT(arena);
|
||||
MOZ_ASSERT_IF(!mayNeedBarrier,
|
||||
CurrentThreadIsPerformingGC() || CurrentThreadIsGCSweeping());
|
||||
initialized = true;
|
||||
AllocKind kind = arena->getAllocKind();
|
||||
firstThingOffset = Arena::firstThingOffset(kind);
|
||||
thingSize = Arena::thingSize(kind);
|
||||
traceKind = MapAllocToTraceKind(kind);
|
||||
needsBarrier = mayNeedBarrier && !JS::CurrentThreadIsHeapCollecting();
|
||||
reset(arena);
|
||||
}
|
||||
|
||||
|
@ -161,11 +184,20 @@ class ArenaCellIterImpl
|
|||
|
||||
TenuredCell* getCell() const {
|
||||
MOZ_ASSERT(!done());
|
||||
return reinterpret_cast<TenuredCell*>(uintptr_t(arenaAddr) + thing);
|
||||
TenuredCell* cell = reinterpret_cast<TenuredCell*>(uintptr_t(arenaAddr) + thing);
|
||||
|
||||
// This can result in a a new reference being created to an object that
|
||||
// an ongoing incremental GC may find to be unreachable, so we may need
|
||||
// a barrier here.
|
||||
if (needsBarrier)
|
||||
ExposeGCThingToActiveJS(JS::GCCellPtr(cell, traceKind));
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
template<typename T> T* get() const {
|
||||
MOZ_ASSERT(!done());
|
||||
MOZ_ASSERT(JS::MapTypeToTraceKind<T>::kind == traceKind);
|
||||
return static_cast<T*>(getCell());
|
||||
}
|
||||
|
||||
|
@ -185,7 +217,7 @@ class ArenaCellIter : public ArenaCellIterImpl
|
|||
{
|
||||
public:
|
||||
explicit ArenaCellIter(Arena* arena)
|
||||
: ArenaCellIterImpl(arena)
|
||||
: ArenaCellIterImpl(arena, CellIterMayNeedBarrier)
|
||||
{
|
||||
MOZ_ASSERT(JS::CurrentThreadIsHeapTracing());
|
||||
}
|
||||
|
@ -195,7 +227,7 @@ class ArenaCellIterUnderGC : public ArenaCellIterImpl
|
|||
{
|
||||
public:
|
||||
explicit ArenaCellIterUnderGC(Arena* arena)
|
||||
: ArenaCellIterImpl(arena)
|
||||
: ArenaCellIterImpl(arena, CellIterDoesntNeedBarrier)
|
||||
{
|
||||
MOZ_ASSERT(CurrentThreadIsPerformingGC());
|
||||
}
|
||||
|
@ -205,7 +237,7 @@ class ArenaCellIterUnderFinalize : public ArenaCellIterImpl
|
|||
{
|
||||
public:
|
||||
explicit ArenaCellIterUnderFinalize(Arena* arena)
|
||||
: ArenaCellIterImpl(arena)
|
||||
: ArenaCellIterImpl(arena, CellIterDoesntNeedBarrier)
|
||||
{
|
||||
MOZ_ASSERT(CurrentThreadIsGCSweeping());
|
||||
}
|
||||
|
@ -248,7 +280,7 @@ class ZoneCellIter<TenuredCell> {
|
|||
rt->gc.waitBackgroundSweepEnd();
|
||||
arenaIter.init(zone, kind);
|
||||
if (!arenaIter.done())
|
||||
cellIter.init(arenaIter.get());
|
||||
cellIter.init(arenaIter.get(), CellIterMayNeedBarrier);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
Загрузка…
Ссылка в новой задаче