Bug 1144832 - Move grayBufferState manipulation out of GCMarker; r=jonco
authorTerrence Cole <terrence@mozilla.com>
Thu, 19 Mar 2015 08:50:32 -0700
changeset 263331 83c8a3ff722b2897d5d1c37ddbc3e5ceed7015dc
parent 263330 8f19e666277d0140bb0250caa007ce10709534a2
child 263332 a31a1564808af4f0ac21199049a903f670edd8d9
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1144832
milestone39.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 1144832 - Move grayBufferState manipulation out of GCMarker; r=jonco
js/src/gc/RootMarking.cpp
js/src/gc/Tracer.cpp
js/src/gc/Tracer.h
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -557,33 +557,31 @@ void
 js::gc::GCRuntime::bufferGrayRoots()
 {
     // Precondition: the state has been reset to "unused" after the last GC
     //               and the zone's buffers have been cleared.
     MOZ_ASSERT(grayBufferState == GrayBufferState::Unused);
     for (GCZonesIter zone(rt); !zone.done(); zone.next())
         MOZ_ASSERT(zone->gcGrayRoots.empty());
 
-    // The state starts at "Okay" and may be toggled to "Failed" if we OOM
-    // while marking.
-    grayBufferState = GrayBufferState::Okay;
-
     // Transform the GCMarker into an unholy CallbackTracer doppleganger.
     MOZ_ASSERT(!IsMarkingGray(&marker));
     MOZ_ASSERT(IsMarkingTracer(&marker));
     MOZ_ASSERT(!marker.callback);
+    MOZ_ASSERT(!marker.bufferingGrayRootsFailed);
     marker.callback = GCMarker::GrayCallback;
     MOZ_ASSERT(IsMarkingGray(&marker));
 
     if (JSTraceDataOp op = grayRootTracer.op)
         (*op)(&marker, grayRootTracer.data);
 
+    // Propagate the failure flag from the marker to the runtime.
+    grayBufferState = marker.bufferingGrayRootsFailed
+                      ? GrayBufferState::Failed
+                      : GrayBufferState::Okay;
+
     // Restore the GCMarker to its former correctness.
     MOZ_ASSERT(IsMarkingGray(&marker));
+    marker.bufferingGrayRootsFailed = false;
     marker.callback = nullptr;
     MOZ_ASSERT(!IsMarkingGray(&marker));
     MOZ_ASSERT(IsMarkingTracer(&marker));
-
-    // Postcondition: the state remains at "Okay", or has been toggled to
-    //                "Failed" during marking.
-    MOZ_ASSERT(grayBufferState == GrayBufferState::Okay ||
-               grayBufferState == GrayBufferState::Failed);
 }
--- a/js/src/gc/Tracer.cpp
+++ b/js/src/gc/Tracer.cpp
@@ -508,16 +508,17 @@ MarkStack::sizeOfExcludingThis(mozilla::
 }
 
 /*
  * DoNotTraceWeakMaps: the GC is recomputing the liveness of WeakMap entries,
  * so we delay visting entries.
  */
 GCMarker::GCMarker(JSRuntime *rt)
   : JSTracer(rt, nullptr, DoNotTraceWeakMaps),
+    bufferingGrayRootsFailed(false),
     stack(size_t(-1)),
     color(BLACK),
     unmarkedArenaStackTop(nullptr),
     markLaterArenas(0),
     started(false),
     strictCompartmentChecking(false)
 {
 }
@@ -667,17 +668,17 @@ GCRuntime::markBufferedGrayRoots(JS::Zon
     }
 }
 
 void
 GCMarker::appendGrayRoot(void *thing, JSGCTraceKind kind)
 {
     MOZ_ASSERT(started);
 
-    if (runtime()->gc.grayBufferState == GCRuntime::GrayBufferState::Failed)
+    if (bufferingGrayRootsFailed)
         return;
 
     GrayRoot root(thing, kind);
 #ifdef DEBUG
     root.debugPrinter = debugPrinter();
     root.debugPrintArg = debugPrintArg();
     root.debugPrintIndex = debugPrintIndex();
 #endif
@@ -694,18 +695,18 @@ GCMarker::appendGrayRoot(void *thing, JS
             break;
           case JSTRACE_SCRIPT:
             static_cast<JSScript *>(thing)->compartment()->maybeAlive = true;
             break;
           default:
             break;
         }
         if (!zone->gcGrayRoots.append(root)) {
+            bufferingGrayRootsFailed = true;
             resetBufferedGrayRoots();
-            runtime()->gc.grayBufferState = GCRuntime::GrayBufferState::Failed;
         }
     }
 }
 
 void
 GCMarker::GrayCallback(JSTracer *trc, void **thingp, JSGCTraceKind kind)
 {
     MOZ_ASSERT(thingp);
--- a/js/src/gc/Tracer.h
+++ b/js/src/gc/Tracer.h
@@ -196,16 +196,19 @@ class GCMarker : public JSTracer
     }
 
     bool isDrained() {
         return isMarkStackEmpty() && !unmarkedArenaStackTop;
     }
 
     bool drainMarkStack(SliceBudget &budget);
 
+    /* Set to false if we OOM while buffering gray roots. */
+    bool bufferingGrayRootsFailed;
+
     void resetBufferedGrayRoots();
 
     static void GrayCallback(JSTracer *trc, void **thing, JSGCTraceKind kind);
 
     void setGCMode(JSGCMode mode) { stack.setGCMode(mode); }
 
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;