Bug 1318384 - Add AbortReason::CompartmentRevived so repeated GCs don't get counted under NonIncrementalRequested r=billm
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 22 Nov 2016 10:32:11 +0000
changeset 371075 45b2377336150fcbe2a477e1719b0059956c5b5d
parent 371074 fdc0f9d0f338042f35c0d8d56555801b63a277da
child 371076 e453f2aaef941b6516ff8852282741369771c7ad
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1318384
milestone53.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 1318384 - Add AbortReason::CompartmentRevived so repeated GCs don't get counted under NonIncrementalRequested r=billm
js/src/gc/GCRuntime.h
js/src/jsgc.cpp
js/src/jsgc.h
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -942,32 +942,33 @@ class GCRuntime
 
     friend class BackgroundAllocTask;
     friend class AutoMaybeStartBackgroundAllocation;
     bool wantBackgroundAllocation(const AutoLockGC& lock) const;
     void startBackgroundAllocTaskIfIdle();
 
     void requestMajorGC(JS::gcreason::Reason reason);
     SliceBudget defaultBudget(JS::gcreason::Reason reason, int64_t millis);
-    void budgetIncrementalGC(SliceBudget& budget, AutoLockForExclusiveAccess& lock);
+    void budgetIncrementalGC(JS::gcreason::Reason reason, SliceBudget& budget,
+                             AutoLockForExclusiveAccess& lock);
     void resetIncrementalGC(AbortReason reason, AutoLockForExclusiveAccess& lock);
 
     // Assert if the system state is such that we should never
     // receive a request to do GC work.
     void checkCanCallAPI();
 
     // Check if the system state is such that GC has been supressed
     // or otherwise delayed.
     MOZ_MUST_USE bool checkIfGCAllowedInCurrentState(JS::gcreason::Reason reason);
 
     gcstats::ZoneGCStats scanZonesBeforeGC();
     void collect(bool nonincrementalByAPI, SliceBudget budget, JS::gcreason::Reason reason) JS_HAZ_GC_CALL;
     MOZ_MUST_USE bool gcCycle(bool nonincrementalByAPI, SliceBudget& budget,
                               JS::gcreason::Reason reason);
-    bool shouldRepeatForDeadZone();
+    bool shouldRepeatForDeadZone(JS::gcreason::Reason reason);
     void incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason reason,
                                  AutoLockForExclusiveAccess& lock);
 
     void pushZealSelectedObjects();
     void purgeRuntime(AutoLockForExclusiveAccess& lock);
     MOZ_MUST_USE bool beginMarkPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAccess& lock);
     bool shouldPreserveJITCode(JSCompartment* comp, int64_t currentTime,
                                JS::gcreason::Reason reason);
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -5999,33 +5999,34 @@ gc::IsIncrementalGCUnsafe(JSRuntime* rt)
 
     if (!rt->gc.isIncrementalGCAllowed())
         return gc::AbortReason::IncrementalDisabled;
 
     return gc::AbortReason::None;
 }
 
 void
-GCRuntime::budgetIncrementalGC(SliceBudget& budget, AutoLockForExclusiveAccess& lock)
+GCRuntime::budgetIncrementalGC(JS::gcreason::Reason reason, SliceBudget& budget,
+                               AutoLockForExclusiveAccess& lock)
 {
     AbortReason unsafeReason = IsIncrementalGCUnsafe(rt);
+    if (unsafeReason == AbortReason::None) {
+        if (reason == JS::gcreason::COMPARTMENT_REVIVED)
+            unsafeReason = gc::AbortReason::CompartmentRevived;
+        else if (mode != JSGC_MODE_INCREMENTAL)
+            unsafeReason = gc::AbortReason::ModeChange;
+    }
+
     if (unsafeReason != AbortReason::None) {
         resetIncrementalGC(unsafeReason, lock);
         budget.makeUnlimited();
         stats.nonincremental(unsafeReason);
         return;
     }
 
-    if (mode != JSGC_MODE_INCREMENTAL) {
-        resetIncrementalGC(AbortReason::ModeChange, lock);
-        budget.makeUnlimited();
-        stats.nonincremental(AbortReason::ModeChange);
-        return;
-    }
-
     if (isTooMuchMalloc()) {
         budget.makeUnlimited();
         stats.nonincremental(AbortReason::MallocBytesTrigger);
     }
 
     bool reset = false;
     for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
         if (zone->usage.gcBytes() >= zone->threshold.gcTriggerBytes()) {
@@ -6173,17 +6174,17 @@ GCRuntime::gcCycle(bool nonincrementalBy
         // the caller expects this GC to collect certain objects, and we need
         // to make sure to collect everything possible.
         if (reason != JS::gcreason::ALLOC_TRIGGER)
             resetIncrementalGC(gc::AbortReason::NonIncrementalRequested, session.lock);
 
         stats.nonincremental(gc::AbortReason::NonIncrementalRequested);
         budget.makeUnlimited();
     } else {
-        budgetIncrementalGC(budget, session.lock);
+        budgetIncrementalGC(reason, budget, session.lock);
     }
 
     /* The GC was reset, so we need a do-over. */
     if (prevState != State::NotActive && !isIncrementalGCInProgress())
         return true;
 
     TraceMajorGCStart();
 
@@ -6293,18 +6294,20 @@ GCRuntime::checkIfGCAllowedInCurrentStat
     if (deterministicOnly && !IsDeterministicGCReason(reason))
         return false;
 #endif
 
     return true;
 }
 
 bool
-GCRuntime::shouldRepeatForDeadZone()
-{
+GCRuntime::shouldRepeatForDeadZone(JS::gcreason::Reason reason)
+{
+    MOZ_ASSERT_IF(reason == JS::gcreason::COMPARTMENT_REVIVED, !isIncremental);
+
     if (!isIncremental || isIncrementalGCInProgress())
         return false;
 
     for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
         if (c->scheduledForDestruction)
             return true;
     }
 
@@ -6340,25 +6343,24 @@ GCRuntime::collect(bool nonincrementalBy
     do {
         poked = false;
         bool wasReset = gcCycle(nonincrementalByAPI, budget, reason);
 
         bool repeatForDeadZone = false;
         if (poked && cleanUpEverything) {
             /* Need to re-schedule all zones for GC. */
             JS::PrepareForFullGC(rt->contextFromMainThread());
-        } else if (shouldRepeatForDeadZone() && !wasReset) {
+        } else if (shouldRepeatForDeadZone(reason) && !wasReset) {
             /*
              * This code makes an extra effort to collect compartments that we
              * thought were dead at the start of the GC. See the large comment
              * in beginMarkPhase.
              */
             repeatForDeadZone = true;
             reason = JS::gcreason::COMPARTMENT_REVIVED;
-            nonincrementalByAPI = true;
         }
 
         /*
          * If we reset an existing GC, we need to start a new one. Also, we
          * repeat GCs that happen during shutdown (the gcShouldCleanUpEverything
          * case) until we can be sure that no additional garbage is created
          * (which typically happens if roots are dropped during finalizers).
          */
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -55,17 +55,18 @@ enum class State {
     D(None) \
     D(NonIncrementalRequested) \
     D(AbortRequested) \
     D(KeepAtomsSet) \
     D(IncrementalDisabled) \
     D(ModeChange) \
     D(MallocBytesTrigger) \
     D(GCBytesTrigger) \
-    D(ZoneChange)
+    D(ZoneChange) \
+    D(CompartmentRevived)
 enum class AbortReason {
 #define MAKE_REASON(name) name,
     GC_ABORT_REASONS(MAKE_REASON)
 #undef MAKE_REASON
 };
 
 /*
  * Map from C++ type to alloc kind for non-object types. JSObject does not have