Bug 1539039 keep WorkletGlobalScope as long as its Worklet is usable r=baku
authorKarl Tomlinson <karlt+@karlt.net>
Mon, 01 Apr 2019 16:54:58 +0000
changeset 467513 80bda5c60103e2aafbbe08e965b5653872f39326
parent 467512 62a25408f9eaacd585cc921e3d6c25b0898b559b
child 467514 661bafa045c4206511058bc760343318df4a751b
push id35799
push usercbrindusan@mozilla.com
push dateTue, 02 Apr 2019 08:35:12 +0000
treeherdermozilla-central@ea0977445697 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1539039
milestone68.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 1539039 keep WorkletGlobalScope as long as its Worklet is usable r=baku Depends on D25353 Differential Revision: https://phabricator.services.mozilla.com/D25354
dom/worklet/Worklet.cpp
dom/worklet/WorkletImpl.cpp
dom/worklet/WorkletImpl.h
--- a/dom/worklet/Worklet.cpp
+++ b/dom/worklet/Worklet.cpp
@@ -321,34 +321,31 @@ class WorkletFetchHandler final : public
 };
 
 NS_IMPL_ISUPPORTS(WorkletFetchHandler, nsIStreamLoaderObserver)
 
 NS_IMETHODIMP
 ExecutionRunnable::Run() {
   // WorkletThread::IsOnWorkletThread() cannot be used here because it depends
   // on a WorkletJSContext having been created for this thread.  That does not
-  // happen until the first time RunOnWorkletThread() is called.
+  // happen until the global scope is created the first time
+  // RunOnWorkletThread() is called.
   if (!NS_IsMainThread()) {
     RunOnWorkletThread();
     return NS_DispatchToMainThread(this);
   }
 
   RunOnMainThread();
   return NS_OK;
 }
 
 void ExecutionRunnable::RunOnWorkletThread() {
   WorkletThread::EnsureCycleCollectedJSContext(mParentRuntime);
 
-  AutoJSAPI jsapi;
-  jsapi.Init();
-
-  RefPtr<WorkletGlobalScope> globalScope =
-      mWorkletImpl->CreateGlobalScope(jsapi.cx());
+  WorkletGlobalScope* globalScope = mWorkletImpl->GetGlobalScope();
   MOZ_ASSERT(globalScope);
 
   AutoEntryScript aes(globalScope, "Worklet");
   JSContext* cx = aes.cx();
 
   JS::Rooted<JSObject*> globalObj(cx, globalScope->GetGlobalJSObject());
 
   NS_ConvertUTF16toUTF8 url(mHandler->URL());
--- a/dom/worklet/WorkletImpl.cpp
+++ b/dom/worklet/WorkletImpl.cpp
@@ -6,16 +6,17 @@
 
 #include "WorkletImpl.h"
 
 #include "Worklet.h"
 #include "WorkletThread.h"
 
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/dom/RegisterWorkletBindings.h"
+#include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/dom/WorkletBinding.h"
 
 namespace mozilla {
 
 // ---------------------------------------------------------------------------
 // WorkletLoadInfo
 
 WorkletLoadInfo::WorkletLoadInfo(nsPIDOMWindowInner* aWindow,
@@ -37,48 +38,64 @@ WorkletLoadInfo::~WorkletLoadInfo() {
 }
 
 // ---------------------------------------------------------------------------
 // WorkletImpl
 
 WorkletImpl::WorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal)
     : mWorkletLoadInfo(aWindow, aPrincipal), mTerminated(false) {}
 
-WorkletImpl::~WorkletImpl() = default;
+WorkletImpl::~WorkletImpl() { MOZ_ASSERT(!mGlobalScope); }
 
 JSObject* WorkletImpl::WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet,
                                    JS::Handle<JSObject*> aGivenProto) {
   MOZ_ASSERT(NS_IsMainThread());
   return dom::Worklet_Binding::Wrap(aCx, aWorklet, aGivenProto);
 }
 
-already_AddRefed<dom::WorkletGlobalScope> WorkletImpl::CreateGlobalScope(
-    JSContext* aCx) {
+dom::WorkletGlobalScope* WorkletImpl::GetGlobalScope() {
   dom::WorkletThread::AssertIsOnWorkletThread();
 
-  RefPtr<dom::WorkletGlobalScope> scope = ConstructGlobalScope();
+  if (mGlobalScope) {
+    return mGlobalScope;
+  }
 
-  JS::Rooted<JSObject*> global(aCx);
-  NS_ENSURE_TRUE(scope->WrapGlobalObject(aCx, &global), nullptr);
+  dom::AutoJSAPI jsapi;
+  jsapi.Init();
+  JSContext* cx = jsapi.cx();
 
-  JSAutoRealm ar(aCx, global);
+  mGlobalScope = ConstructGlobalScope();
+
+  JS::Rooted<JSObject*> global(cx);
+  NS_ENSURE_TRUE(mGlobalScope->WrapGlobalObject(cx, &global), nullptr);
+
+  JSAutoRealm ar(cx, global);
 
   // Init Web IDL bindings
-  if (!dom::RegisterWorkletBindings(aCx, global)) {
+  if (!dom::RegisterWorkletBindings(cx, global)) {
     return nullptr;
   }
 
-  JS_FireOnNewGlobalObject(aCx, global);
+  JS_FireOnNewGlobalObject(cx, global);
 
-  return scope.forget();
+  return mGlobalScope;
 }
 
 void WorkletImpl::NotifyWorkletFinished() {
   MOZ_ASSERT(NS_IsMainThread());
 
+  if (mTerminated) {
+    return;
+  }
+
+  // Release global scope on its thread.
+  SendControlMessage(NS_NewRunnableFunction(
+      "WorkletImpl::NotifyWorkletFinished",
+      [self = RefPtr<WorkletImpl>(this)]() { self->mGlobalScope = nullptr; }));
+
   mTerminated = true;
   if (mWorkletThread) {
     mWorkletThread->Terminate();
     mWorkletThread = nullptr;
   }
   mWorkletLoadInfo.mPrincipal = nullptr;
 }
 
--- a/dom/worklet/WorkletImpl.h
+++ b/dom/worklet/WorkletImpl.h
@@ -69,17 +69,17 @@ class WorkletImpl {
   virtual JSObject* WrapWorklet(JSContext* aCx, dom::Worklet* aWorklet,
                                 JS::Handle<JSObject*> aGivenProto);
 
   virtual nsresult SendControlMessage(already_AddRefed<nsIRunnable> aRunnable);
 
   void NotifyWorkletFinished();
 
   // Execution thread only.
-  already_AddRefed<dom::WorkletGlobalScope> CreateGlobalScope(JSContext* aCx);
+  dom::WorkletGlobalScope* GetGlobalScope();
 
   // Any thread.
 
   const WorkletLoadInfo& LoadInfo() const { return mWorkletLoadInfo; }
 
  protected:
   WorkletImpl(nsPIDOMWindowInner* aWindow, nsIPrincipal* aPrincipal);
   virtual ~WorkletImpl();
@@ -88,13 +88,16 @@ class WorkletImpl {
 
   // 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;
+
+  // Execution thread only.
+  RefPtr<dom::WorkletGlobalScope> mGlobalScope;
 };
 
 }  // namespace mozilla
 
 #endif  // mozilla_dom_worklet_WorkletImpl_h