Bug 919638 - Part 2: Change warmup semantics to be sequential in slices, low to high. (r=nmatsakis)
authorShu-yu Guo <shu@rfrn.org>
Fri, 10 Jan 2014 02:25:34 -0800
changeset 162921 976a1fe9f0807fa2a93688e9aea9afa4d4506361
parent 162920 464e261cbcbe791df57a30053f83444519cc30a5
child 162922 1e4903ca67df1e513ffbd61d3765e07398e778d2
push id25975
push userryanvm@gmail.com
push dateFri, 10 Jan 2014 19:46:47 +0000
treeherderautoland@e89afc241513 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnmatsakis
bugs919638
milestone29.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 919638 - Part 2: Change warmup semantics to be sequential in slices, low to high. (r=nmatsakis)
js/src/vm/ForkJoin.cpp
--- a/js/src/vm/ForkJoin.cpp
+++ b/js/src/vm/ForkJoin.cpp
@@ -41,17 +41,18 @@ using mozilla::ThreadLocal;
 ///////////////////////////////////////////////////////////////////////////
 // Degenerate configurations
 //
 // When JS_THREADSAFE or JS_ION is not defined, we simply run the
 // |func| callback sequentially.  We also forego the feedback
 // altogether.
 
 static bool
-ExecuteSequentially(JSContext *cx_, HandleValue funVal, bool *complete, uint16_t numSlices);
+ExecuteSequentially(JSContext *cx_, HandleValue funVal, bool *complete,
+                    uint16_t sliceStart, uint16_t numSlices);
 
 #if !defined(JS_THREADSAFE) || !defined(JS_ION)
 bool
 js::ForkJoin(JSContext *cx, CallArgs &args)
 {
     RootedValue argZero(cx, args[0]);
     bool complete = false; // since warmup is false, will always complete
     return ExecuteSequentially(cx, argZero, &complete);
@@ -145,20 +146,21 @@ js::ParallelTestsShouldPass(JSContext *c
 #endif // !JS_THREADSAFE || !JS_ION
 
 ///////////////////////////////////////////////////////////////////////////
 // All configurations
 //
 // Some code that is shared between degenerate and parallel configurations.
 
 static bool
-ExecuteSequentially(JSContext *cx, HandleValue funVal, bool *complete, uint16_t numSlices)
+ExecuteSequentially(JSContext *cx, HandleValue funVal, bool *complete,
+                    uint16_t sliceStart, uint16_t numSlices)
 {
     bool allComplete = true;
-    for (uint16_t i = 0; i < numSlices; i++) {
+    for (uint16_t i = sliceStart; i < numSlices; i++) {
         FastInvokeGuard fig(cx, funVal);
         InvokeArgs &args = fig.args();
         if (!args.init(2))
             return false;
         args.setCallee(funVal);
         args.setThis(UndefinedValue());
         args[0].setInt32(i);
         args[1].setBoolean(!!cx->runtime()->parallelWarmup);
@@ -278,16 +280,17 @@ class ForkJoinOperation
     };
 
     JSContext *cx_;
     HandleObject fun_;
     Vector<ParallelBailoutRecord, 16> bailoutRecords_;
     AutoScriptVector worklist_;
     Vector<WorklistData, 16> worklistData_;
     ForkJoinMode mode_;
+    uint16_t warmupSlice_;
     uint16_t numSlices_;
 
     TrafficLight enqueueInitialScript(ExecutionStatus *status);
     TrafficLight compileForParallelExecution(ExecutionStatus *status);
     TrafficLight warmupExecution(bool stopIfComplete,
                                  ExecutionStatus *status);
     TrafficLight parallelExecution(ExecutionStatus *status);
     TrafficLight sequentialExecution(bool disqualified, ExecutionStatus *status);
@@ -543,16 +546,17 @@ js::ForkJoinOperation::ForkJoinOperation
     bailoutScript(cx),
     bailoutBytecode(nullptr),
     cx_(cx),
     fun_(fun),
     bailoutRecords_(cx),
     worklist_(cx),
     worklistData_(cx),
     mode_(mode),
+    warmupSlice_(0),
     numSlices_(numSlices)
 { }
 
 ExecutionStatus
 js::ForkJoinOperation::apply()
 {
     ExecutionStatus status;
 
@@ -968,17 +972,17 @@ js::ForkJoinOperation::sequentialExecuti
 {
     // XXX use disqualified to set parallelIon to ION_DISABLED_SCRIPT?
 
     Spew(SpewOps, "Executing sequential execution (disqualified=%d).",
          disqualified);
 
     bool complete = false;
     RootedValue funVal(cx_, ObjectValue(*fun_));
-    if (!ExecuteSequentially(cx_, funVal, &complete, numSlices_))
+    if (!ExecuteSequentially(cx_, funVal, &complete, 0, numSlices_))
         return ExecutionFatal;
 
     // When invoked without the warmup flag set to true, the kernel
     // function OUGHT to complete successfully, barring an exception.
     JS_ASSERT(complete);
     return ExecutionSequential;
 }
 
@@ -1126,30 +1130,45 @@ js::ForkJoinOperation::invalidateBailedO
 }
 
 js::ForkJoinOperation::TrafficLight
 js::ForkJoinOperation::warmupExecution(bool stopIfComplete, ExecutionStatus *status)
 {
     // GreenLight: warmup succeeded, still more work to do
     // RedLight: fatal error or warmup completed all work (check status)
 
-    Spew(SpewOps, "Executing warmup.");
+    Spew(SpewOps, "Executing warmup of slice %u.", warmupSlice_);
 
     AutoEnterWarmup warmup(cx_->runtime());
     RootedValue funVal(cx_, ObjectValue(*fun_));
     bool complete;
-    if (!ExecuteSequentially(cx_, funVal, &complete, numSlices_)) {
+    uint32_t warmupTo = Min<uint16_t>(warmupSlice_ + 1, numSlices_);
+    if (!ExecuteSequentially(cx_, funVal, &complete, warmupSlice_, warmupTo)) {
         *status = ExecutionFatal;
         return RedLight;
     }
 
-    if (complete && stopIfComplete) {
-        Spew(SpewOps, "Warmup execution finished all the work.");
-        *status = ExecutionWarmup;
-        return RedLight;
+    if (complete) {
+        warmupSlice_ = warmupTo;
+        if (warmupSlice_ == numSlices_) {
+            if (stopIfComplete) {
+                Spew(SpewOps, "Warmup execution finished all the work.");
+                *status = ExecutionWarmup;
+                return RedLight;
+            }
+
+            // If we finished all slices in warmup, be sure check the
+            // interrupt flag. This is because we won't be running more JS
+            // code, and thus no more automatic checking of the interrupt
+            // flag.
+            if (!js_HandleExecutionInterrupt(cx_)) {
+                *status = ExecutionFatal;
+                return RedLight;
+            }
+        }
     }
 
     return GreenLight;
 }
 
 js::ForkJoinOperation::TrafficLight
 js::ForkJoinOperation::parallelExecution(ExecutionStatus *status)
 {