Bug 1413914 - Add zeal mode to check gray marking invariants after every GC r=sfink
authorJon Coppeard <jcoppeard@mozilla.com>
Fri, 03 Nov 2017 10:25:25 +0000
changeset 443299 c5561749c1c64793c31699d46bbf12cc0c69815c
parent 443298 203ea4c2406fc81abd51fe7d6ba81c49e655f70f
child 443300 101466a6bd46d25c6e079e9e1e07b342afcc0735
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1413914
milestone58.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 1413914 - Add zeal mode to check gray marking invariants after every GC r=sfink
js/src/gc/GCEnum.h
js/src/gc/Verifier.cpp
js/src/jit-test/tests/gc/bug-1413914.js
js/src/jsfriendapi.h
js/src/jsgc.cpp
--- a/js/src/gc/GCEnum.h
+++ b/js/src/gc/GCEnum.h
@@ -67,21 +67,22 @@ enum class AbortReason {
     D(IncrementalMarkAllThenFinish, 9) \
     D(IncrementalMultipleSlices, 10)   \
     D(IncrementalMarkingValidator, 11) \
     D(ElementsBarrier, 12)             \
     D(CheckHashTablesOnMinorGC, 13)    \
     D(Compact, 14)                     \
     D(CheckHeapAfterGC, 15)            \
     D(CheckNursery, 16)                \
-    D(IncrementalSweepThenFinish, 17)
+    D(IncrementalSweepThenFinish, 17)  \
+    D(CheckGrayMarking, 18)
 
 enum class ZealMode {
 #define ZEAL_MODE(name, value) name = value,
     JS_FOR_EACH_ZEAL_MODE(ZEAL_MODE)
 #undef ZEAL_MODE
-    Limit = 17
+    Limit = 18
 };
 
 } /* namespace gc */
 } /* namespace js */
 
 #endif /* gc_GCEnum_h */
--- a/js/src/gc/Verifier.cpp
+++ b/js/src/gc/Verifier.cpp
@@ -651,17 +651,17 @@ js::gc::CheckHeapAfterGC(JSRuntime* rt)
     AutoTraceSession session(rt, JS::HeapState::Tracing);
     CheckHeapTracer tracer(rt);
     if (tracer.init())
         tracer.check(session.lock);
 }
 
 #endif /* JSGC_HASH_TABLE_CHECKS */
 
-#ifdef DEBUG
+#if defined(JS_GC_ZEAL) || defined(DEBUG)
 
 class CheckGrayMarkingTracer final : public HeapCheckTracerBase
 {
   public:
     explicit CheckGrayMarkingTracer(JSRuntime* rt);
     bool check(AutoLockForExclusiveAccess& lock);
 
   private:
@@ -718,9 +718,9 @@ js::CheckGrayMarkingState(JSRuntime* rt)
     AutoTraceSession session(rt, JS::HeapState::Tracing);
     CheckGrayMarkingTracer tracer(rt);
     if (!tracer.init())
         return true; // Ignore failure
 
     return tracer.check(session.lock);
 }
 
-#endif // DEBUG
+#endif // defined(JS_GC_ZEAL) || defined(DEBUG)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1413914.js
@@ -0,0 +1,4 @@
+let a = grayRoot();
+a[0] = {};
+gczeal(18);
+gc();
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -527,17 +527,17 @@ IterateGrayObjects(JS::Zone* zone, GCThi
 
 /**
  * Invoke cellCallback on every gray JSObject in the given zone while cycle
  * collection is in progress.
  */
 extern JS_FRIEND_API(void)
 IterateGrayObjectsUnderCC(JS::Zone* zone, GCThingCallback cellCallback, void* data);
 
-#ifdef DEBUG
+#if defined(JS_GC_ZEAL) || defined(DEBUG)
 // Trace the heap and check there are no black to gray edges. These are
 // not allowed since the cycle collector could throw away the gray thing and
 // leave a dangling pointer.
 //
 // This doesn't trace weak maps as these are handled separately.
 extern JS_FRIEND_API(bool)
 CheckGrayMarkingState(JSRuntime* rt);
 #endif
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -998,17 +998,18 @@ const char* gc::ZealModeHelpText =
     "    9: (IncrementalMarkAllThenFinish) Incremental GC in two slices: 1) mark all 2) new marking and finish\n"
     "   10: (IncrementalMultipleSlices) Incremental GC in multiple slices\n"
     "   11: (IncrementalMarkingValidator) Verify incremental marking\n"
     "   12: (ElementsBarrier) Always use the individual element post-write barrier, regardless of elements size\n"
     "   13: (CheckHashTablesOnMinorGC) Check internal hashtables on minor GC\n"
     "   14: (Compact) Perform a shrinking collection every N allocations\n"
     "   15: (CheckHeapAfterGC) Walk the heap to check its integrity after every GC\n"
     "   16: (CheckNursery) Check nursery integrity on minor GC\n"
-    "   17: (IncrementalSweepThenFinish) Incremental GC in two slices: 1) start sweeping 2) finish collection\n";
+    "   17: (IncrementalSweepThenFinish) Incremental GC in two slices: 1) start sweeping 2) finish collection\n"
+    "   18: (CheckGrayMarking) Check gray marking invariants after every GC\n";
 
 // The set of zeal modes that control incremental slices. These modes are
 // mutually exclusive.
 static const mozilla::EnumSet<ZealMode> IncrementalSliceZealModes = {
     ZealMode::IncrementalRootsThenFinish,
     ZealMode::IncrementalMarkAllThenFinish,
     ZealMode::IncrementalMultipleSlices,
     ZealMode::IncrementalSweepThenFinish
@@ -7505,16 +7506,19 @@ GCRuntime::collect(bool nonincrementalBy
     if (reason == JS::gcreason::COMPARTMENT_REVIVED)
         maybeDoCycleCollection();
 
 #ifdef JS_GC_ZEAL
     if (rt->hasZealMode(ZealMode::CheckHeapAfterGC)) {
         gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PhaseKind::TRACE_HEAP);
         CheckHeapAfterGC(rt);
     }
+    if (rt->hasZealMode(ZealMode::CheckGrayMarking)) {
+        MOZ_RELEASE_ASSERT(CheckGrayMarkingState(rt));
+    }
 #endif
 }
 
 js::AutoEnqueuePendingParseTasksAfterGC::~AutoEnqueuePendingParseTasksAfterGC()
 {
     if (!OffThreadParsingMustWaitForGC(gc_.rt))
         EnqueuePendingParseTasksAfterGC(gc_.rt);
 }