Backed out changeset ebdebc9251be (bug 1084651)
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 07 Nov 2014 15:30:49 +0100
changeset 238897 a7693b2b12c4df8276bb2c5ac342a621d5981864
parent 238896 bb67cf33bad8591db4e950000dcd05dc0189837d
child 238898 002e8ed9ddf34fe1cbdf942152b5b32896ac3018
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1084651
milestone36.0a1
backs outebdebc9251be6e51419036f8580e7df511077a78
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
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();