Bug 1322420 - Expose cells found via iteration r=sfink a=abillings

This commit is contained in:
Jon Coppeard 2017-02-10 10:22:38 +00:00
Родитель ec2c66fd1f
Коммит 942694dd48
4 изменённых файлов: 42 добавлений и 21 удалений

Просмотреть файл

@ -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: