Backed out changeset ebdebc9251be (bug 1084651)
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 07 Nov 2014 15:30:49 +0100
changeset 230797 a7693b2b12c4df8276bb2c5ac342a621d5981864
parent 230796 bb67cf33bad8591db4e950000dcd05dc0189837d
child 230798 002e8ed9ddf34fe1cbdf942152b5b32896ac3018
push id7326
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:58:42 +0000
treeherdermozilla-aurora@d3a3b2a0f2f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1084651
milestone36.0a1
backs outebdebc9251be6e51419036f8580e7df511077a78
Backed out changeset ebdebc9251be (bug 1084651)
js/public/SliceBudget.h
js/src/builtin/TestingFunctions.cpp
js/src/jsapi-tests/testGCFinalizeCallback.cpp
js/src/jsapi-tests/testWeakMap.cpp
js/src/jsgc.cpp
xpcom/base/nsCycleCollector.cpp
--- a/js/public/SliceBudget.h
+++ b/js/public/SliceBudget.h
@@ -6,75 +6,61 @@
 
 #ifndef js_SliceBudget_h
 #define js_SliceBudget_h
 
 #include <stdint.h>
 
 namespace js {
 
-struct JS_PUBLIC_API(TimeBudget)
-{
-    int64_t budget;
-
-    explicit TimeBudget(int64_t milliseconds) { budget = milliseconds; }
-};
-
-struct JS_PUBLIC_API(WorkBudget)
-{
-    int64_t budget;
-
-    explicit WorkBudget(int64_t work) { budget = work; }
-};
-
 /*
- * This class records how much work has been done in a given collection slice,
- * so that we can return before pausing for too long. Some slices are allowed
- * to run for unlimited time, and others are bounded. To reduce the number of
- * gettimeofday calls, we only check the time every 1000 operations.
+ * This class records how much work has been done in a given collection slice, so that
+ * we can return before pausing for too long. Some slices are allowed to run for
+ * unlimited time, and others are bounded. To reduce the number of gettimeofday
+ * calls, we only check the time every 1000 operations.
  */
 struct JS_PUBLIC_API(SliceBudget)
 {
     int64_t deadline; /* in microseconds */
     intptr_t counter;
 
     static const intptr_t CounterReset = 1000;
 
     static const int64_t Unlimited = 0;
+    static int64_t TimeBudget(int64_t millis);
+    static int64_t WorkBudget(int64_t work);
 
-    /* Use to create an unlimited budget. */
+    /* Equivalent to SliceBudget(UnlimitedBudget). */
     SliceBudget();
 
-    /* Instantiate as SliceBudget(TimeBudget(n)). */
-    explicit SliceBudget(TimeBudget time);
-
-    /* Instantiate as SliceBudget(WorkBudget(n)). */
-    explicit SliceBudget(WorkBudget work);
+    /* Instantiate as SliceBudget(Time/WorkBudget(n)). */
+    explicit SliceBudget(int64_t budget);
 
     void reset() {
         deadline = unlimitedDeadline;
         counter = unlimitedStartCounter;
     }
 
     void step(intptr_t amt = 1) {
         counter -= amt;
     }
 
+    bool checkOverBudget();
+
     bool isOverBudget() {
         if (counter >= 0)
             return false;
         return checkOverBudget();
     }
 
     bool isUnlimited() {
         return deadline == unlimitedDeadline;
     }
 
-  private:
-    bool checkOverBudget();
-
+private:
     static const int64_t unlimitedDeadline = INT64_MAX;
     static const intptr_t unlimitedStartCounter = INTPTR_MAX;
+
 };
 
 } // namespace js
 
 #endif /* js_SliceBudget_h */
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -628,17 +628,17 @@ GCSlice(JSContext *cx, unsigned argc, Va
         return false;
     }
 
     SliceBudget budget;
     if (args.length() == 1) {
         uint32_t work = 0;
         if (!ToUint32(cx, args[0], &work))
             return false;
-        budget = SliceBudget(WorkBudget(work));
+        budget = SliceBudget(SliceBudget::WorkBudget(work));
     }
 
     cx->runtime()->gc.gcDebugSlice(budget);
     args.rval().setUndefined();
     return true;
 }
 
 static bool
--- a/js/src/jsapi-tests/testGCFinalizeCallback.cpp
+++ b/js/src/jsapi-tests/testGCFinalizeCallback.cpp
@@ -82,23 +82,23 @@ BEGIN_TEST(testGCFinalizeCallback)
 
 #ifdef JS_GC_ZEAL
 
     /* Full GC with reset due to new compartment, becoming compartment GC. */
 
     FinalizeCalls = 0;
     JS_SetGCZeal(cx, 9, 1000000);
     JS::PrepareForFullGC(rt);
-    js::SliceBudget budget(js::WorkBudget(1));
+    js::SliceBudget budget(js::SliceBudget::WorkBudget(1));
     rt->gc.gcDebugSlice(budget);
     CHECK(rt->gc.state() == js::gc::MARK);
     CHECK(rt->gc.isFullGc());
 
     JS::RootedObject global4(cx, createTestGlobal());
-    budget = js::SliceBudget(js::WorkBudget(1));
+    budget = js::SliceBudget(js::SliceBudget::WorkBudget(1));
     rt->gc.gcDebugSlice(budget);
     CHECK(rt->gc.state() == js::gc::NO_INCREMENTAL);
     CHECK(!rt->gc.isFullGc());
     CHECK(checkMultipleGroups());
     CHECK(checkFinalizeStatus());
 
     for (unsigned i = 0; i < FinalizeCalls - 1; ++i)
         CHECK(!IsCompartmentGCBuffer[i]);
--- a/js/src/jsapi-tests/testWeakMap.cpp
+++ b/js/src/jsapi-tests/testWeakMap.cpp
@@ -84,31 +84,31 @@ BEGIN_TEST(testWeakMap_keyDelegates)
 
     SetKeyDelegate(key, delegate);
 
     /*
      * Perform an incremental GC, introducing an unmarked CCW to force the map
      * zone to finish marking before the delegate zone.
      */
     CHECK(newCCW(map, delegate));
-    js::SliceBudget budget(js::WorkBudget(1000000));
+    js::SliceBudget budget(js::SliceBudget::WorkBudget(1000000));
     rt->gc.gcDebugSlice(budget);
 #ifdef DEBUG
     CHECK(map->zone()->lastZoneGroupIndex() < delegate->zone()->lastZoneGroupIndex());
 #endif
 
     /* Add our entry to the weakmap. */
     JS::RootedValue val(cx, JS::Int32Value(1));
     CHECK(SetWeakMapEntry(cx, map, key, val));
     CHECK(checkSize(map, 1));
 
     /* Check the delegate keeps the entry alive even if the key is not reachable. */
     key = nullptr;
     CHECK(newCCW(map, delegate));
-    budget = js::SliceBudget(js::WorkBudget(100000));
+    budget = js::SliceBudget(js::SliceBudget::WorkBudget(100000));
     rt->gc.gcDebugSlice(budget);
     CHECK(checkSize(map, 1));
 
     /*
      * Check that the zones finished marking at the same time, which is
      * neccessary because of the presence of the delegate and the CCW.
      */
 #ifdef DEBUG
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2925,35 +2925,45 @@ GCRuntime::refillFreeListInGC(Zone *zone
     MOZ_ASSERT(allocator.arenas.freeLists[thingKind].isEmpty());
     mozilla::DebugOnly<JSRuntime *> rt = zone->runtimeFromMainThread();
     MOZ_ASSERT(rt->isHeapMajorCollecting());
     MOZ_ASSERT(!rt->gc.isBackgroundSweeping());
 
     return allocator.arenas.allocateFromArena(zone, thingKind);
 }
 
+/* static */ int64_t
+SliceBudget::TimeBudget(int64_t millis)
+{
+    return millis * PRMJ_USEC_PER_MSEC;
+}
+
+/* static */ int64_t
+SliceBudget::WorkBudget(int64_t work)
+{
+    /* For work = 0 not to mean Unlimited, we subtract 1. */
+    return -work - 1;
+}
+
 SliceBudget::SliceBudget()
 {
     reset();
 }
 
-SliceBudget::SliceBudget(TimeBudget time)
-{
-    if (time.budget == Unlimited) {
+SliceBudget::SliceBudget(int64_t budget)
+{
+    if (budget == Unlimited) {
         reset();
-    } else {
-        deadline = PRMJ_Now() + time.budget * PRMJ_USEC_PER_MSEC;
+    } else if (budget > 0) {
+        deadline = PRMJ_Now() + budget;
         counter = CounterReset;
-    }
-}
-
-SliceBudget::SliceBudget(WorkBudget work)
-{
-    deadline = 0;
-    counter = work.budget;
+    } else {
+        deadline = 0;
+        counter = -budget - 1;
+    }
 }
 
 bool
 SliceBudget::checkOverBudget()
 {
     bool over = PRMJ_Now() > deadline;
     if (!over)
         counter = CounterReset;
@@ -6102,23 +6112,23 @@ GCRuntime::gc(JSGCInvocationKind gckind,
     collect(false, budget, gckind, reason);
 }
 
 void
 GCRuntime::gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis)
 {
     SliceBudget budget;
     if (millis)
-        budget = SliceBudget(TimeBudget(millis));
+        budget = SliceBudget(SliceBudget::TimeBudget(millis));
     else if (reason == JS::gcreason::ALLOC_TRIGGER)
-        budget = SliceBudget(TimeBudget(sliceBudget));
+        budget = SliceBudget(SliceBudget::TimeBudget(sliceBudget));
     else if (schedulingState.inHighFrequencyGCMode() && tunables.isDynamicMarkSliceEnabled())
-        budget = SliceBudget(TimeBudget(sliceBudget * IGC_MARK_SLICE_MULTIPLIER));
+        budget = SliceBudget(SliceBudget::TimeBudget(sliceBudget * IGC_MARK_SLICE_MULTIPLIER));
     else
-        budget = SliceBudget(TimeBudget(sliceBudget));
+        budget = SliceBudget(SliceBudget::TimeBudget(sliceBudget));
 
     collect(true, budget, gckind, reason);
 }
 
 void
 GCRuntime::gcFinalSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason)
 {
     SliceBudget budget;
@@ -6439,20 +6449,20 @@ GCRuntime::runDebugGC()
              * Start with a small slice limit and double it every slice. This
              * ensure that we get multiple slices, and collection runs to
              * completion.
              */
             if (initialState == NO_INCREMENTAL)
                 incrementalLimit = zealFrequency / 2;
             else
                 incrementalLimit *= 2;
-            budget = SliceBudget(WorkBudget(incrementalLimit));
+            budget = SliceBudget(SliceBudget::WorkBudget(incrementalLimit));
         } else {
             // This triggers incremental GC but is actually ignored by IncrementalMarkSlice.
-            budget = SliceBudget(WorkBudget(1));
+            budget = SliceBudget(SliceBudget::WorkBudget(1));
         }
 
         collect(true, budget, GC_NORMAL, JS::gcreason::DEBUG_GC);
 
         /*
          * For multi-slice zeal, reset the slice size when we get to the sweep
          * phase.
          */
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -3617,19 +3617,17 @@ nsCycleCollector::Collect(ccType aCCType
         break;
       case CleanupPhase:
         PrintPhase("CleanupAfterCollection");
         CleanupAfterCollection();
         continueSlice = false;
         break;
     }
     if (continueSlice) {
-      // Force SliceBudget::isOverBudget to check the time.
-      aBudget.step(SliceBudget::CounterReset);
-      continueSlice = !aBudget.isOverBudget();
+      continueSlice = !aBudget.checkOverBudget();
     }
   } while (continueSlice);
 
   // Clear mActivelyCollecting here to ensure that a recursive call to
   // Collect() does something.
   mActivelyCollecting = false;
 
   if (aCCType != SliceCC && !startedIdle) {
@@ -4196,17 +4194,17 @@ nsCycleCollector_collectSlice(int64_t aS
   MOZ_ASSERT(data);
   MOZ_ASSERT(data->mCollector);
 
   PROFILER_LABEL("nsCycleCollector", "collectSlice",
                  js::ProfileEntry::Category::CC);
 
   SliceBudget budget;
   if (aSliceTime >= 0) {
-    budget = SliceBudget(js::TimeBudget(aSliceTime));
+    budget = SliceBudget(SliceBudget::TimeBudget(aSliceTime));
   }
   data->mCollector->Collect(SliceCC, budget, nullptr);
 }
 
 void
 nsCycleCollector_collectSliceWork(int64_t aSliceWork)
 {
   CollectorData* data = sCollectorData.get();
@@ -4215,17 +4213,17 @@ nsCycleCollector_collectSliceWork(int64_
   MOZ_ASSERT(data);
   MOZ_ASSERT(data->mCollector);
 
   PROFILER_LABEL("nsCycleCollector", "collectSliceWork",
                  js::ProfileEntry::Category::CC);
 
   SliceBudget budget;
   if (aSliceWork >= 0) {
-    budget = SliceBudget(js::WorkBudget(aSliceWork));
+    budget = SliceBudget(SliceBudget::WorkBudget(aSliceWork));
   }
   data->mCollector->Collect(SliceCC, budget, nullptr);
 }
 
 void
 nsCycleCollector_prepareForGarbageCollection()
 {
   CollectorData* data = sCollectorData.get();