Bug 1275448 - Don't crash on shutdown due to non-empty type descriptors set if we leak r=sfink
authorJon Coppeard <jcoppeard@mozilla.com>
Fri, 22 Jul 2016 13:57:10 +0100
changeset 348462 c9abfc5925a2af00d0eb3e61a6316efc7e83f9de
parent 348461 31163bfc3cb4f849c25c9f756bdfe3639b45b9fe
child 348463 82e2bfbaf3270ed3237e340e708d6f7838bfcc7e
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1275448
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1275448 - Don't crash on shutdown due to non-empty type descriptors set if we leak r=sfink
js/src/gc/Zone.cpp
js/src/jsgc.cpp
js/src/jsgc.h
--- a/js/src/gc/Zone.cpp
+++ b/js/src/gc/Zone.cpp
@@ -53,18 +53,16 @@ JS::Zone::Zone(JSRuntime* rt)
 
     AutoLockGC lock(rt);
     threshold.updateAfterGC(8192, GC_NORMAL, rt->gc.tunables, rt->gc.schedulingState, lock);
     setGCMaxMallocBytes(rt->gc.maxMallocBytesAllocated() * 0.9);
 }
 
 Zone::~Zone()
 {
-    MOZ_ASSERT_IF(typeDescrObjects.initialized(), typeDescrObjects.empty());
-
     JSRuntime* rt = runtimeFromMainThread();
     if (this == rt->gc.systemZone)
         rt->gc.systemZone = nullptr;
 
     js_delete(debuggers);
     js_delete(jitZone_);
 }
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -3548,23 +3548,24 @@ GCRuntime::sweepZones(FreeOp* fop, bool 
             {
                 // 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();
+                mozilla::DebugOnly<bool> arenasEmpty = zone->arenas.checkEmptyArenaLists();
 
                 if (callback)
                     callback(zone);
 
                 zone->sweepCompartments(fop, false, destroyingRuntime);
                 MOZ_ASSERT(zone->compartments.empty());
+                MOZ_ASSERT_IF(arenasEmpty, zone->typeDescrObjects.empty());
                 fop->delete_(zone);
                 stats.sweptZone();
                 continue;
             }
             zone->sweepCompartments(fop, true, destroyingRuntime);
         }
         *write++ = zone;
     }
@@ -3582,31 +3583,34 @@ FOR_EACH_ALLOCKIND(MAKE_CASE)
 #undef MAKE_CASE
 
       default:
         MOZ_CRASH("Unknown AllocKind in AllocKindToAscii");
     }
 }
 #endif // DEBUG
 
-void
+bool
 ArenaLists::checkEmptyArenaList(AllocKind kind)
 {
+    bool empty = true;
 #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));
+                empty = false;
             }
         }
     }
 #endif // DEBUG
+    return empty;
 }
 
 void
 GCRuntime::purgeRuntime(AutoLockForExclusiveAccess& lock)
 {
     for (GCCompartmentsIter comp(rt); !comp.done(); comp.next())
         comp->purge();
 
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -736,28 +736,32 @@ class ArenaLists
 
     void checkEmptyFreeLists() {
 #ifdef DEBUG
         for (auto i : AllAllocKinds())
             checkEmptyFreeList(i);
 #endif
     }
 
-    void checkEmptyArenaLists() {
+    bool checkEmptyArenaLists() {
+        bool empty = true;
 #ifdef DEBUG
-        for (auto i : AllAllocKinds())
-            checkEmptyArenaList(i);
+        for (auto i : AllAllocKinds()) {
+            if (!checkEmptyArenaList(i))
+                empty = false;
+        }
 #endif
+        return empty;
     }
 
     void checkEmptyFreeList(AllocKind kind) {
         MOZ_ASSERT(freeLists[kind]->isEmpty());
     }
 
-    void checkEmptyArenaList(AllocKind kind);
+    bool checkEmptyArenaList(AllocKind kind);
 
     bool relocateArenas(Zone* zone, Arena*& relocatedListOut, JS::gcreason::Reason reason,
                         SliceBudget& sliceBudget, gcstats::Statistics& stats);
 
     void queueForegroundObjectsForSweep(FreeOp* fop);
     void queueForegroundThingsForSweep(FreeOp* fop);
 
     void mergeForegroundSweptObjectArenas();