Bug 1102542 - Release any relocated arenas on out of memory r=terrence
authorJon Coppeard <jcoppeard@mozilla.com>
Mon, 24 Nov 2014 10:42:21 +0000
changeset 241536 69d3b8413102b6d86d7b059f27fc03a6ba01b6ff
parent 241535 b7c0e6bce748b3fc7ec114996a10bcbdcc3d2fde
child 241537 d266732061313282251a470f799d14b22fac53ca
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1102542
milestone36.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 1102542 - Release any relocated arenas on out of memory r=terrence
js/src/gc/GCRuntime.h
js/src/jsgc.cpp
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -606,16 +606,17 @@ class GCRuntime
     void sweepTypesAfterCompacting(Zone *zone);
     void sweepZoneAfterCompacting(Zone *zone);
     void compactPhase(bool lastGC);
     ArenaHeader *relocateArenas();
     void updateAllCellPointersParallel(ArenasToUpdate &source);
     void updateAllCellPointersSerial(MovingTracer *trc, ArenasToUpdate &source);
     void updatePointersToRelocatedCells();
     void releaseRelocatedArenas(ArenaHeader *relocatedList);
+    void releaseRelocatedArenasWithoutUnlocking(ArenaHeader *relocatedList, const AutoLockGC& lock);
 #ifdef DEBUG
     void protectRelocatedArenas(ArenaHeader *relocatedList);
     void unprotectRelocatedArenas(ArenaHeader *relocatedList);
 #endif
 #endif
     void finishCollection();
 
     void computeNonIncrementalMarkingForValidation();
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2727,19 +2727,25 @@ GCRuntime::unprotectRelocatedArenas(Aren
 #endif
     }
 }
 #endif
 
 void
 GCRuntime::releaseRelocatedArenas(ArenaHeader *relocatedList)
 {
+    AutoLockGC lock(rt);
+    releaseRelocatedArenasWithoutUnlocking(relocatedList, lock);
+    expireChunksAndArenas(true, lock);
+}
+
+void
+GCRuntime::releaseRelocatedArenasWithoutUnlocking(ArenaHeader *relocatedList, const AutoLockGC &lock)
+{
     // Release the relocated arenas, now containing only forwarding pointers
-    AutoLockGC lock(rt);
-
     unsigned count = 0;
     while (relocatedList) {
         ArenaHeader *aheader = relocatedList;
         relocatedList = relocatedList->next;
 
         // Clear the mark bits
         aheader->unmarkAll();
 
@@ -2754,18 +2760,16 @@ GCRuntime::releaseRelocatedArenas(ArenaH
 #if defined(JS_CRASH_DIAGNOSTICS) || defined(JS_GC_ZEAL)
         JS_POISON(reinterpret_cast<void *>(arena->thingsStart(thingKind)),
                   JS_MOVED_TENURED_PATTERN, Arena::thingsSpan(thingSize));
 #endif
 
         releaseArena(aheader, lock);
         ++count;
     }
-
-    expireChunksAndArenas(true, lock);
 }
 
 #endif // JSGC_COMPACTING
 
 void
 ReleaseArenaList(JSRuntime *rt, ArenaHeader *aheader, const AutoLockGC &lock)
 {
     ArenaHeader *next;
@@ -6401,16 +6405,23 @@ GCRuntime::onOutOfMallocMemory()
 }
 
 void
 GCRuntime::onOutOfMallocMemory(const AutoLockGC &lock)
 {
     // Throw away any excess chunks we have lying around.
     freeEmptyChunks(rt, lock);
 
+    // Release any relocated areans we may be holding on to.
+#if defined(JSGC_COMPACTING) && defined(DEBUG)
+    unprotectRelocatedArenas(relocatedArenasToRelease);
+    releaseRelocatedArenasWithoutUnlocking(relocatedArenasToRelease, lock);
+    relocatedArenasToRelease = nullptr;
+#endif
+
     // Immediately decommit as many arenas as possible in the hopes that this
     // might let the OS scrape together enough pages to satisfy the failing
     // malloc request.
     decommitAllWithoutUnlocking(lock);
 }
 
 void
 GCRuntime::minorGC(JS::gcreason::Reason reason)