bug 1476514 use a distinct method to send runnables from parent to worklet thread r=baku
authorKarl Tomlinson <karlt+@karlt.net>
Wed, 28 Nov 2018 23:47:01 +0000
changeset 505124 ef4fa2ede44ceb17477001e90a1e0a833887782a
parent 505123 704371789faab7c03f3128976d8dc001608f35d5
child 505125 68b992118fd3dc3d5ef8b568c1a1449778e8c2f3
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1476514
milestone65.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 1476514 use a distinct method to send runnables from parent to worklet thread r=baku and create the worklet thread on demand from there. Differential Revision: https://phabricator.services.mozilla.com/D13213
dom/console/Console.cpp
dom/worklet/Worklet.cpp
dom/worklet/WorkletImpl.cpp
dom/worklet/WorkletImpl.h
--- a/dom/console/Console.cpp
+++ b/dom/console/Console.cpp
@@ -555,17 +555,17 @@ protected:
   NS_IMETHOD
   Run() override
   {
     // This runnable is dispatched to main-thread first, then it goes back to
     // worklet thread.
     if (NS_IsMainThread()) {
       RunOnMainThread();
       RefPtr<ConsoleWorkletRunnable> runnable(this);
-      return mWorkletImpl->DispatchRunnable(runnable.forget());
+      return mWorkletImpl->SendControlMessage(runnable.forget());
     }
 
     WorkletThread::AssertIsOnWorkletThread();
 
     ReleaseData();
     mConsole = nullptr;
     return NS_OK;
   }
--- a/dom/worklet/Worklet.cpp
+++ b/dom/worklet/Worklet.cpp
@@ -223,23 +223,17 @@ public:
       return NS_OK;
     }
 
     // Moving the ownership of the buffer
     nsCOMPtr<nsIRunnable> runnable =
       new ExecutionRunnable(this, mWorklet->mImpl, std::move(scriptTextBuf),
                             scriptTextLength);
 
-    RefPtr<WorkletThread> thread = mWorklet->mImpl->GetOrCreateThread();
-    if (!thread) {
-      RejectPromises(NS_ERROR_FAILURE);
-      return NS_OK;
-    }
-
-    if (NS_FAILED(thread->DispatchRunnable(runnable.forget()))) {
+    if (NS_FAILED(mWorklet->mImpl->SendControlMessage(runnable.forget()))) {
       RejectPromises(NS_ERROR_FAILURE);
       return NS_OK;
     }
 
     return NS_OK;
   }
 
   virtual void
--- a/dom/worklet/WorkletImpl.cpp
+++ b/dom/worklet/WorkletImpl.cpp
@@ -37,17 +37,18 @@ WorkletLoadInfo::~WorkletLoadInfo()
   MOZ_ASSERT(!mPrincipal || NS_IsMainThread());
 }
 
 // ---------------------------------------------------------------------------
 // WorkletImpl
 
 WorkletImpl::WorkletImpl(nsPIDOMWindowInner* aWindow,
                          nsIPrincipal* aPrincipal)
-  : mWorkletLoadInfo(aWindow, aPrincipal)
+  : mWorkletLoadInfo(aWindow, aPrincipal),
+    mTerminated(false)
 {
 }
 
 WorkletImpl::~WorkletImpl() = default;
 
 JSObject*
 WorkletImpl::WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet,
                          JS::Handle<JSObject*> aGivenProto)
@@ -73,42 +74,43 @@ WorkletImpl::CreateGlobalScope(JSContext
     return nullptr;
   }
 
   JS_FireOnNewGlobalObject(aCx, global);
 
   return scope.forget();
 }
 
-dom::WorkletThread*
-WorkletImpl::GetOrCreateThread()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (!mWorkletThread) {
-    // Thread creation. FIXME: this will change.
-    mWorkletThread = dom::WorkletThread::Create();
-  }
-
-  return mWorkletThread;
-}
-
 void
 WorkletImpl::NotifyWorkletFinished()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
+  mTerminated = true;
   if (mWorkletThread) {
     mWorkletThread->Terminate();
     mWorkletThread = nullptr;
   }
   mWorkletLoadInfo.mPrincipal = nullptr;
 }
 
 nsresult
-WorkletImpl::DispatchRunnable(already_AddRefed<nsIRunnable> aRunnable)
+WorkletImpl::SendControlMessage(already_AddRefed<nsIRunnable> aRunnable)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+
   // TODO: bug 1492011 re ConsoleWorkletRunnable.
-  MOZ_ASSERT(mWorkletThread);
+  if (mTerminated) {
+    return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
+  }
+
+  if (!mWorkletThread) {
+    // Thread creation. FIXME: this will change.
+    mWorkletThread = dom::WorkletThread::Create();
+    if (!mWorkletThread) {
+      return NS_ERROR_UNEXPECTED;
+    }
+  }
+
   return mWorkletThread->DispatchRunnable(std::move(aRunnable));
 }
 
 } // namespace mozilla
--- a/dom/worklet/WorkletImpl.h
+++ b/dom/worklet/WorkletImpl.h
@@ -69,38 +69,37 @@ public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WorkletImpl);
 
   // Methods for parent thread only:
 
   virtual JSObject*
   WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet,
               JS::Handle<JSObject*> aGivenProto);
 
-  dom::WorkletThread* GetOrCreateThread();
+  nsresult SendControlMessage(already_AddRefed<nsIRunnable> aRunnable);
+
   void NotifyWorkletFinished();
 
   // Execution thread only.
   already_AddRefed<dom::WorkletGlobalScope> CreateGlobalScope(JSContext* aCx);
 
   // Any thread.
 
   const WorkletLoadInfo& LoadInfo() const { return mWorkletLoadInfo; }
 
-  // Use DispatchRunnable only when the thread is known to already exist.
-  nsresult DispatchRunnable(already_AddRefed<nsIRunnable> aRunnable);
-
 protected:
   WorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal);
   virtual ~WorkletImpl();
 
   virtual already_AddRefed<dom::WorkletGlobalScope> ConstructGlobalScope() = 0;
 
   // The only WorkletLoadInfo member modified is mPrincipal which is accessed
   // on only the parent thread.
   WorkletLoadInfo mWorkletLoadInfo;
 
   // Parent thread only.
   RefPtr<dom::WorkletThread> mWorkletThread;
+  bool mTerminated;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_dom_worklet_WorkletImpl_h