Bug 1401141 - Fix ZonesIter to return helper thread zones that are not yet being used r=sfink
authorJon Coppeard <jcoppeard@mozilla.com>
Wed, 20 Sep 2017 10:25:08 +0100
changeset 433830 598b7dc5fb33e8eb624c69207747b96e325ecef3
parent 433829 98c159aec57e9231e10c2a9d373c3a8eb079c45a
child 433831 38375565ef08fbc63dc4b3f98eee84ebd4e67a8b
push id1567
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 12:36:05 +0000
treeherdermozilla-release@e512c14a0406 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1401141
milestone57.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 1401141 - Fix ZonesIter to return helper thread zones that are not yet being used r=sfink
js/src/gc/Zone.cpp
js/src/gc/Zone.h
js/src/jit-test/tests/gc/bug-1401141.js
js/src/jsgc.cpp
--- a/js/src/gc/Zone.cpp
+++ b/js/src/gc/Zone.cpp
@@ -99,18 +99,16 @@ Zone::init(bool isSystemArg)
            markedAtoms().init() &&
            atomCache().init() &&
            regExps.init();
 }
 
 void
 Zone::setNeedsIncrementalBarrier(bool needs)
 {
-    MOZ_ASSERT_IF(needs && isAtomsZone(),
-                  !runtimeFromActiveCooperatingThread()->hasHelperThreadZones());
     MOZ_ASSERT_IF(needs, canCollect());
     needsIncrementalBarrier_ = needs;
 }
 
 void
 Zone::beginSweepTypes(FreeOp* fop, bool releaseTypes)
 {
     AutoClearTypeInferenceStateOnOOM oom(this);
@@ -293,25 +291,24 @@ Zone::hasMarkedCompartments()
             return true;
     }
     return false;
 }
 
 bool
 Zone::canCollect()
 {
+    // The atoms zone cannot be collected while off-thread parsing is taking
+    // place.
+    if (isAtomsZone())
+        return !runtimeFromAnyThread()->hasHelperThreadZones();
+
     // Zones that will be or are currently used by other threads cannot be
     // collected.
-    if (!isAtomsZone() && group()->createdForHelperThread())
-        return false;
-
-    JSRuntime* rt = runtimeFromAnyThread();
-    if (isAtomsZone() && rt->hasHelperThreadZones())
-        return false;
-    return true;
+    return !group()->createdForHelperThread();
 }
 
 void
 Zone::notifyObservingDebuggers()
 {
     for (CompartmentsInZoneIter comps(this); !comps.done(); comps.next()) {
         JSRuntime* rt = runtimeFromAnyThread();
         RootedGlobalObject global(TlsContext.get(), comps->unsafeUnbarrieredMaybeGlobal());
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -689,27 +689,27 @@ class ZoneGroupsIter
     ZoneGroup** it;
     ZoneGroup** end;
 
   public:
     explicit ZoneGroupsIter(JSRuntime* rt) : iterMarker(&rt->gc) {
         it = rt->gc.groups().begin();
         end = rt->gc.groups().end();
 
-        if (!done() && (*it)->createdForHelperThread())
+        if (!done() && (*it)->usedByHelperThread())
             next();
     }
 
     bool done() const { return it == end; }
 
     void next() {
         MOZ_ASSERT(!done());
         do {
             it++;
-        } while (!done() && (*it)->createdForHelperThread());
+        } while (!done() && (*it)->usedByHelperThread());
     }
 
     ZoneGroup* get() const {
         MOZ_ASSERT(!done());
         return *it;
     }
 
     operator ZoneGroup*() const { return get(); }
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1401141.js
@@ -0,0 +1,13 @@
+if (!('gczeal' in this))
+    quit();
+if (helperThreadCount() == 0)
+    quit();
+
+gczeal(15,1);
+setGCCallback({
+  action: "majorGC",
+});
+gcslice(3);
+var lfGlobal = newGlobal();
+lfGlobal.offThreadCompileScript("");
+
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -4026,17 +4026,17 @@ RelazifyFunctions(Zone* zone, AllocKind 
             fun->maybeRelazify(rt);
     }
 }
 
 static bool
 ShouldCollectZone(Zone* zone, JS::gcreason::Reason reason)
 {
     // If we are repeating a GC because we noticed dead compartments haven't
-    // been collected, then only collect zones contianing those compartments.
+    // been collected, then only collect zones containing those compartments.
     if (reason == JS::gcreason::COMPARTMENT_REVIVED) {
         for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next()) {
             if (comp->scheduledForDestruction)
                 return true;
         }
 
         return false;
     }
@@ -4058,17 +4058,17 @@ ShouldCollectZone(Zone* zone, JS::gcreas
     // active thread.
     //
     // Otherwise, we always schedule a GC in the atoms zone so that atoms which
     // the other collected zones are using are marked, and we can update the
     // set of atoms in use by the other collected zones at the end of the GC.
     if (zone->isAtomsZone())
         return TlsContext.get()->canCollectAtoms();
 
-    return true;
+    return zone->canCollect();
 }
 
 bool
 GCRuntime::prepareZonesForCollection(JS::gcreason::Reason reason, bool* isFullOut,
                                      AutoLockForExclusiveAccess& lock)
 {
 #ifdef DEBUG
     /* Assert that zone state is as we expect */
@@ -6701,31 +6701,29 @@ AutoGCSlice::AutoGCSlice(JSRuntime* rt)
          * Clear needsIncrementalBarrier early so we don't do any write
          * barriers during GC. We don't need to update the Ion barriers (which
          * is expensive) because Ion code doesn't run during GC. If need be,
          * we'll update the Ion barriers in ~AutoGCSlice.
          */
         if (zone->isGCMarking()) {
             MOZ_ASSERT(zone->needsIncrementalBarrier());
             zone->setNeedsIncrementalBarrier(false);
-        } else {
-            MOZ_ASSERT(!zone->needsIncrementalBarrier());
-        }
+        }
+        MOZ_ASSERT(!zone->needsIncrementalBarrier());
     }
 }
 
 AutoGCSlice::~AutoGCSlice()
 {
     /* We can't use GCZonesIter if this is the end of the last slice. */
     for (ZonesIter zone(runtime, WithAtoms); !zone.done(); zone.next()) {
+        MOZ_ASSERT(!zone->needsIncrementalBarrier());
         if (zone->isGCMarking()) {
             zone->setNeedsIncrementalBarrier(true);
             zone->arenas.purge();
-        } else {
-            zone->setNeedsIncrementalBarrier(false);
         }
     }
 }
 
 void
 GCRuntime::pushZealSelectedObjects()
 {
 #ifdef JS_GC_ZEAL