Bug 1402596 - Init Promise job queue on cooperative threads (jsshell) r=till
authorTed Campbell <tcampbell@mozilla.com>
Wed, 11 Oct 2017 11:32:32 -0400
changeset 385918 7dd785b2c20165d6cebd92e244ec18e2417c86f7
parent 385917 6c50dc08aa42c958ce312c7273773e085381ac86
child 385919 892d9b753f1ab60973fd0aa84d18c89e8bf99a08
push id32672
push userarchaeopteryx@coole-files.de
push dateFri, 13 Oct 2017 09:00:05 +0000
treeherdermozilla-central@3efcb26e5f37 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill
bugs1402596
milestone58.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 1402596 - Init Promise job queue on cooperative threads (jsshell) r=till MozReview-Commit-ID: 6ikd7yZyIRk
js/src/jit-test/tests/promise/cooperative-thread.js
js/src/jscntxt.cpp
js/src/jsfriendapi.h
js/src/shell/js.cpp
js/src/vm/Runtime.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/promise/cooperative-thread.js
@@ -0,0 +1,8 @@
+if (helperThreadCount() === 0)
+    quit();
+
+evalInCooperativeThread(`
+    (new Promise(function(resolve, reject) { resolve(); })).then(() => {});
+
+    drainJobQueue();
+    `);
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -1135,29 +1135,32 @@ class MOZ_STACK_CLASS ReportExceptionClo
     }
 
   private:
     HandleValue exn_;
 };
 } // anonymous namespace
 
 JS_FRIEND_API(bool)
-js::UseInternalJobQueues(JSContext* cx)
+js::UseInternalJobQueues(JSContext* cx, bool cooperative)
 {
     // Internal job queue handling must be set up very early. Self-hosting
     // initialization is as good a marker for that as any.
-    MOZ_RELEASE_ASSERT(!cx->runtime()->hasInitializedSelfHosting(),
+    MOZ_RELEASE_ASSERT(cooperative || !cx->runtime()->hasInitializedSelfHosting(),
                        "js::UseInternalJobQueues must be called early during runtime startup.");
     MOZ_ASSERT(!cx->jobQueue);
     auto* queue = js_new<PersistentRooted<JobQueue>>(cx, JobQueue(SystemAllocPolicy()));
     if (!queue)
         return false;
 
     cx->jobQueue = queue;
-    cx->runtime()->offThreadPromiseState.ref().initInternalDispatchQueue();
+
+    if (!cooperative)
+        cx->runtime()->offThreadPromiseState.ref().initInternalDispatchQueue();
+    MOZ_ASSERT(cx->runtime()->offThreadPromiseState.ref().initialized());
 
     JS::SetEnqueuePromiseJobCallback(cx, InternalEnqueuePromiseJobCallback);
 
     return true;
 }
 
 JS_FRIEND_API(void)
 js::StopDrainingJobQueue(JSContext* cx)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -430,17 +430,17 @@ ForgetSourceHook(JSContext* cx);
  * will want to manage job queues themselves. For basic embeddings such as the
  * JS shell that don't have an event loop of their own, it's easier to have
  * SpiderMonkey handle job queues internally.
  *
  * Note that the embedding still has to trigger processing of job queues at
  * right time(s), such as after evaluation of a script has run to completion.
  */
 extern JS_FRIEND_API(bool)
-UseInternalJobQueues(JSContext* cx);
+UseInternalJobQueues(JSContext* cx, bool cooperative = false);
 
 /**
  * Instruct the runtime to stop draining the internal job queue.
  *
  * Useful if the embedding is in the process of quitting in reaction to a
  * builtin being called, or if it wants to resume executing jobs later on.
  */
 extern JS_FRIEND_API(void)
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3574,16 +3574,18 @@ WorkerMain(void* arg)
 
         if (!JS::InitSelfHostedCode(cx))
             return;
 
         environmentPreparer.emplace(cx);
     } else {
         JS_AddInterruptCallback(cx, ShellInterruptCallback);
 
+        js::UseInternalJobQueues(cx, /* cooperative = */true);
+
         // The Gecko Profiler requires that all cooperating contexts have
         // profiling stacks installed.
         MOZ_ALWAYS_TRUE(EnsureGeckoProfilingStackInstalled(cx, sc.get()));
     }
 
     do {
         JSAutoRequest ar(cx);
 
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -724,17 +724,17 @@ JSRuntime::getIncumbentGlobal(JSContext*
     return cx->getIncumbentGlobalCallback(cx);
 }
 
 bool
 JSRuntime::enqueuePromiseJob(JSContext* cx, HandleFunction job, HandleObject promise,
                              HandleObject incumbentGlobal)
 {
     MOZ_ASSERT(cx->enqueuePromiseJobCallback,
-               "Must set a callback using JS_SetEnqeueuPromiseJobCallback before using Promises");
+               "Must set a callback using JS::SetEnqueuePromiseJobCallback before using Promises");
     MOZ_ASSERT_IF(incumbentGlobal, !IsWrapper(incumbentGlobal) && !IsWindowProxy(incumbentGlobal));
 
     void* data = cx->enqueuePromiseJobCallbackData;
     RootedObject allocationSite(cx);
     if (promise) {
         RootedObject unwrappedPromise(cx, promise);
         // While the job object is guaranteed to be unwrapped, the promise
         // might be wrapped. See the comments in