Bug 1268992 - Assert that the heap is empty after a shutdown GC; r=jonco

--HG--
extra : rebase_source : 089c7d6750bae6a53e8b952806353539faf8ff9b
This commit is contained in:
Terrence Cole 2016-04-26 15:25:29 -07:00
parent 83fc354edc
commit 010e6e8304
5 changed files with 76 additions and 3 deletions

View File

@ -141,7 +141,7 @@ public:
IMPL_EVENT_HANDLER(load)
IMPL_EVENT_HANDLER(timeout)
IMPL_EVENT_HANDLER(loadend)
virtual void DisconnectFromOwner() override;
};

View File

@ -807,8 +807,6 @@ class GCRuntime
bool isFullGc() const { return isFull; }
bool isCompactingGc() const { return isCompacting; }
bool shouldCleanUpEverything() { return cleanUpEverything; }
bool areGrayBitsValid() const { return grayBitsValid; }
void setGrayBitsInvalid() { grayBitsValid = false; }

View File

@ -113,6 +113,34 @@ enum class AllocKind {
LAST = LIMIT - 1
};
#define FOR_EACH_ALLOCKIND(D) \
/* PrettyName TypeName */ \
D(FUNCTION, JSFunction) \
D(FUNCTION_EXTENDED, JSFunction) \
D(OBJECT0, JSObject) \
D(OBJECT0_BACKGROUND, JSObject) \
D(OBJECT2, JSObject) \
D(OBJECT2_BACKGROUND, JSObject) \
D(OBJECT4, JSObject) \
D(OBJECT4_BACKGROUND, JSObject) \
D(OBJECT8, JSObject) \
D(OBJECT8_BACKGROUND, JSObject) \
D(OBJECT12, JSObject) \
D(OBJECT12_BACKGROUND, JSObject) \
D(OBJECT16, JSObject) \
D(OBJECT16_BACKGROUND, JSObject) \
D(SCRIPT, JSScript) \
D(LAZY_SCRIPT, js::LazyScript) \
D(SHAPE, js::Shape) \
D(ACCESSOR_SHAPE, js::AccessorShape) \
D(BASE_SHAPE, js::BaseShape) \
D(OBJECT_GROUP, js::ObjectGroup) \
D(FAT_INLINE_STRING, JSFatInlineString) \
D(STRING, JSString) \
D(EXTERNAL_STRING, JSExternalString) \
D(SYMBOL, JS::Symbol) \
D(JITCODE, js::JitCode)
static_assert(int(AllocKind::FIRST) == 0, "Various places depend on AllocKind starting at 0, "
"please audit them carefully!");
static_assert(int(AllocKind::OBJECT_FIRST) == 0, "Various places depend on AllocKind::OBJECT_FIRST "

View File

@ -3888,8 +3888,15 @@ GCRuntime::sweepZones(FreeOp* fop, bool destroyingRuntime)
!zone->hasMarkedCompartments();
if (zoneIsDead || destroyingRuntime)
{
// We have just finished sweeping, so we should have freed any
// empty arenas back to their Chunk for future allocation.
zone->arenas.checkEmptyFreeLists();
// We are about to delete the Zone; this will leave the Zone*
// in the arena header dangling if there are any arenas
// remaining at this point.
zone->arenas.checkEmptyArenaLists();
if (callback)
callback(zone);
@ -3905,6 +3912,37 @@ GCRuntime::sweepZones(FreeOp* fop, bool destroyingRuntime)
zones.shrinkTo(write - zones.begin());
}
#ifdef DEBUG
static const char*
AllocKindToAscii(AllocKind kind)
{
switch(kind) {
#define MAKE_CASE(name, _) case AllocKind:: name: return #name;
FOR_EACH_ALLOCKIND(MAKE_CASE)
#undef MAKE_CASE
case AllocKind::LIMIT: MOZ_FALLTHROUGH;
default: MOZ_CRASH("Unknown AllocKind in AllocKindToAscii");
}
}
#endif // DEBUG
void
ArenaLists::checkEmptyArenaList(AllocKind kind)
{
#ifdef DEBUG
if (!arenaLists[kind].isEmpty()) {
for (Arena* current = arenaLists[kind].head(); current; current = current->next) {
for (ArenaCellIterUnderFinalize i(current); !i.done(); i.next()) {
Cell* t = i.get<Cell>();
MOZ_ASSERT(t->asTenured().isMarked(), "unmarked cells should have been finalized");
fprintf(stderr, "ERROR: GC found live Cell %p of kind %s at shutdown\n",
t, AllocKindToAscii(kind));
}
}
}
#endif // DEBUG
}
void
GCRuntime::purgeRuntime()
{

View File

@ -739,10 +739,19 @@ class ArenaLists
#endif
}
void checkEmptyArenaLists() {
#ifdef DEBUG
for (auto i : AllAllocKinds())
checkEmptyArenaList(i);
#endif
}
void checkEmptyFreeList(AllocKind kind) {
MOZ_ASSERT(freeLists[kind]->isEmpty());
}
void checkEmptyArenaList(AllocKind kind);
bool relocateArenas(Zone* zone, Arena*& relocatedListOut, JS::gcreason::Reason reason,
SliceBudget& sliceBudget, gcstats::Statistics& stats);