Bug 1316447 - Baldr: hoist CanUseExtraThreads promise logic (r=bbouvier)
authorLuke Wagner <luke@mozilla.com>
Thu, 10 Nov 2016 08:38:18 -0600
changeset 322083 4b46d55b13bd99548b00112c2894bb4ccae4f5bf
parent 322082 f290780813ad71a516cb0886d52c83e0dc99716b
child 322084 bfd4da2301e55c335edd2d762d53b07a5f07faf1
push id21
push usermaklebus@msu.edu
push dateThu, 01 Dec 2016 06:22:08 +0000
reviewersbbouvier
bugs1316447
milestone52.0a1
Bug 1316447 - Baldr: hoist CanUseExtraThreads promise logic (r=bbouvier) MozReview-Commit-ID: K8EMFhTwMLC
js/src/builtin/Promise.cpp
js/src/builtin/Promise.h
js/src/vm/HelperThreads.cpp
js/src/vm/HelperThreads.h
js/src/wasm/WasmJS.cpp
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -2683,16 +2683,24 @@ PromiseTask::finish(JSContext* cx)
 
 void
 PromiseTask::cancel(JSContext* cx)
 {
     MOZ_ASSERT(cx == runtime_);
     js_delete(this);
 }
 
+bool
+PromiseTask::executeAndFinish(JSContext* cx)
+{
+    MOZ_ASSERT(!CanUseExtraThreads());
+    execute();
+    return finishPromise(cx, promise_);
+}
+
 static JSObject*
 CreatePromisePrototype(JSContext* cx, JSProtoKey key)
 {
     return cx->global()->createBlankPrototype(cx, &PromiseObject::protoClass_);
 }
 
 static const JSFunctionSpec promise_methods[] = {
     JS_SELF_HOSTED_FN("catch", "Promise_catch", 1, 0),
--- a/js/src/builtin/Promise.h
+++ b/js/src/builtin/Promise.h
@@ -160,16 +160,20 @@ class PromiseTask : public JS::AsyncTask
     ~PromiseTask();
     JSRuntime* runtime() const { return runtime_; }
 
     // Called on a helper thread after StartAsyncTask. After execute()
     // completes, the JS::FinishAsyncTaskCallback will be called. If this fails
     // the task will be enqueued for deletion at some future point without ever
     // calling finishPromise().
     virtual void execute() = 0;
+
+    // May be called in the absence of helper threads to synchronously execute
+    // and finish a PromiseTask.
+    bool executeAndFinish(JSContext* cx);
 };
 
 bool
 Promise_static_resolve(JSContext* cx, unsigned argc, Value* vp);
 bool
 Promise_reject(JSContext* cx, unsigned argc, Value* vp);
 bool
 Promise_then(JSContext* cx, unsigned argc, Value* vp);
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -1684,16 +1684,20 @@ js::StartOffThreadCompression(ExclusiveC
 
     HelperThreadState().notifyOne(GlobalHelperThreadState::PRODUCER, lock);
     return true;
 }
 
 bool
 js::StartPromiseTask(JSContext* cx, UniquePtr<PromiseTask> task)
 {
+    // Execute synchronously if there are no helper threads.
+    if (!CanUseExtraThreads())
+        return task->executeAndFinish(cx);
+
     // If we fail to start, by interface contract, it is because the JSContext
     // is in the process of shutting down. Since promise handlers are not
     // necessarily run while shutting down *anyway*, we simply ignore the error.
     // This is symmetric with the handling of errors in finishAsyncTaskCallback
     // which, since it is off the JSContext's owner thread, cannot report an
     // error anyway.
     if (!cx->startAsyncTaskCallback(cx, task.get())) {
         MOZ_ASSERT(!cx->isExceptionPending());
--- a/js/src/vm/HelperThreads.h
+++ b/js/src/vm/HelperThreads.h
@@ -395,18 +395,20 @@ SetFakeCPUCount(size_t count);
 void
 PauseCurrentHelperThread();
 
 /* Perform MIR optimization and LIR generation on a single function. */
 bool
 StartOffThreadWasmCompile(wasm::IonCompileTask* task);
 
 /*
- * Start executing the given PromiseTask on a helper thread, finishing back on
- * the originating JSContext's owner thread.
+ * If helper threads are available, start executing the given PromiseTask on a
+ * helper thread, finishing back on the originating JSContext's owner thread. If
+ * no helper threads are available, the PromiseTask is synchronously executed
+ * and finished.
  */
 bool
 StartPromiseTask(JSContext* cx, UniquePtr<PromiseTask> task);
 
 /*
  * Schedule an Ion compilation for a script, given a builder which has been
  * generated and read everything needed from the VM state.
  */
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -1709,23 +1709,18 @@ WebAssembly_compile(JSContext* cx, unsig
 
         if (!promise->reject(cx, rejectionValue))
             return false;
 
         callArgs.rval().setObject(*promise);
         return true;
     }
 
-    if (CanUseExtraThreads()) {
-        if (!StartPromiseTask(cx, Move(task)))
-            return false;
-    } else {
-        task->execute();
-        task->finishPromise(cx, promise);
-    }
+    if (!StartPromiseTask(cx, Move(task)))
+        return false;
 
     callArgs.rval().setObject(*promise);
     return true;
 }
 #endif
 
 static bool
 WebAssembly_validate(JSContext* cx, unsigned argc, Value* vp)