Bug 751458. Don't let DOM workers confuse the slow-script time accounting and trigger slow script dialogs. r=bent
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 04 May 2012 03:22:18 -0400
changeset 93139 40a901a6e733adf1ac7d2869dc19fb6fe03e3b5e
parent 93138 72a7230e978e917e03793976ed49f07af0871dfc
child 93140 319f53d58da2afaf87a62a54fb96a0358f16ec7d
push id22611
push usereakhgari@mozilla.com
push dateFri, 04 May 2012 20:23:57 +0000
treeherdermozilla-central@dc93a3faa54e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbent
bugs751458
milestone15.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 751458. Don't let DOM workers confuse the slow-script time accounting and trigger slow script dialogs. r=bent
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerPrivate.h
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -50,16 +50,17 @@
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsITextToSubURI.h"
 #include "nsITimer.h"
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsIXPConnect.h"
+#include "nsIXPCScriptNotify.h"
 
 #include "jsfriendapi.h"
 #include "jsdbgapi.h"
 #include "jsfriendapi.h"
 #include "jsprf.h"
 #include "js/MemoryMetrics.h"
 #include "nsAlgorithm.h"
 #include "nsContentUtils.h"
@@ -961,16 +962,23 @@ public:
       CreateMessageEvent(aCx, buffer, mClonedObjects, mainRuntime);
     if (!event) {
       return false;
     }
 
     bool dummy;
     return DispatchEventToTarget(aCx, target, event, &dummy);
   }
+
+  void PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, bool aRunResult)
+  {
+    // Notify before WorkerRunnable::PostRun, since that can kill aWorkerPrivate
+    NotifyScriptExecutedIfNeeded();
+    WorkerRunnable::PostRun(aCx, aWorkerPrivate, aRunResult);
+  }
 };
 
 class NotifyRunnable : public WorkerControlRunnable
 {
   bool mFromJSObjectFinalizer;
   Status mStatus;
 
 public:
@@ -1106,16 +1114,23 @@ public:
     }
 
     return ReportErrorRunnable::ReportError(aCx, parent, true, target, mMessage,
                                             mFilename, mLine, mLineNumber,
                                             mColumnNumber, mFlags,
                                             mErrorNumber, innerWindowId);
   }
 
+  void PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, bool aRunResult)
+  {
+    // Notify before WorkerRunnable::PostRun, since that can kill aWorkerPrivate
+    NotifyScriptExecutedIfNeeded();
+    WorkerRunnable::PostRun(aCx, aWorkerPrivate, aRunResult);
+  }
+
   static bool
   ReportError(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
               bool aFireAtScope, JSObject* aTarget, const nsString& aMessage,
               const nsString& aFilename, const nsString& aLine,
               PRUint32 aLineNumber, PRUint32 aColumnNumber, PRUint32 aFlags,
               PRUint32 aErrorNumber, PRUint64 aInnerWindowId)
   {
     if (aWorkerPrivate) {
@@ -1811,16 +1826,28 @@ WorkerRunnable::PostRun(JSContext* aCx, 
     }
   }
 
   if (!aRunResult) {
     JS_ReportPendingException(aCx);
   }
 }
 
+void
+WorkerRunnable::NotifyScriptExecutedIfNeeded() const
+{
+  // if we're on the main thread notify about the end of our script execution.
+  if (mTarget == ParentThread && !mWorkerPrivate->GetParent()) {
+    AssertIsOnMainThread();
+    if (mWorkerPrivate->GetScriptNotify()) {
+      mWorkerPrivate->GetScriptNotify()->ScriptExecuted();
+    }
+  }
+}
+
 struct WorkerPrivate::TimeoutInfo
 {
   TimeoutInfo()
   : mTimeoutVal(JSVAL_VOID), mLineNumber(0), mId(0), mIsInterval(false),
     mCanceled(false)
   {
     MOZ_COUNT_CTOR(mozilla::dom::workers::WorkerPrivate::TimeoutInfo);
   }
@@ -1876,16 +1903,17 @@ WorkerPrivateParent<Derived>::WorkerPriv
   MOZ_COUNT_CTOR(mozilla::dom::workers::WorkerPrivateParent);
 
   if (aWindow) {
     NS_ASSERTION(aWindow->IsInnerWindow(), "Should have inner window here!");
   }
 
   mWindow.swap(aWindow);
   mScriptContext.swap(aScriptContext);
+  mScriptNotify = do_QueryInterface(mScriptContext);
   mBaseURI.swap(aBaseURI);
   mPrincipal.swap(aPrincipal);
   mDocument.swap(aDocument);
 
   if (aParent) {
     aParent->AssertIsOnWorkerThread();
 
     NS_ASSERTION(JS_GetOptions(aCx) == aParent->GetJSContextOptions(),
@@ -2176,20 +2204,21 @@ WorkerPrivateParent<Derived>::RootJSObje
 template <class Derived>
 void
 WorkerPrivateParent<Derived>::ForgetMainThreadObjects(
                                       nsTArray<nsCOMPtr<nsISupports> >& aDoomed)
 {
   AssertIsOnParentThread();
   MOZ_ASSERT(!mMainThreadObjectsForgotten);
 
-  aDoomed.SetCapacity(6);
+  aDoomed.SetCapacity(7);
 
   SwapToISupportsArray(mWindow, aDoomed);
   SwapToISupportsArray(mScriptContext, aDoomed);
+  SwapToISupportsArray(mScriptNotify, aDoomed);
   SwapToISupportsArray(mBaseURI, aDoomed);
   SwapToISupportsArray(mScriptURI, aDoomed);
   SwapToISupportsArray(mPrincipal, aDoomed);
   SwapToISupportsArray(mDocument, aDoomed);
 
   mMainThreadObjectsForgotten = true;
 }
 
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -64,16 +64,17 @@
 class JSAutoStructuredCloneBuffer;
 class nsIDocument;
 class nsIPrincipal;
 class nsIMemoryMultiReporter;
 class nsIScriptContext;
 class nsIURI;
 class nsPIDOMWindow;
 class nsITimer;
+class nsIXPCScriptNotify;
 
 BEGIN_WORKERS_NAMESPACE
 
 class WorkerPrivate;
 
 class WorkerRunnable : public nsIRunnable
 {
 public:
@@ -128,16 +129,18 @@ protected:
   DispatchInternal();
 
   virtual bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) = 0;
 
   virtual void
   PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, bool aRunResult);
 
+  void NotifyScriptExecutedIfNeeded() const;
+
 private:
   NS_DECL_NSIRUNNABLE
 };
 
 class WorkerSyncRunnable : public WorkerRunnable
 {
 protected:
   PRUint32 mSyncQueueKey;
@@ -202,16 +205,17 @@ private:
   JSContext* mParentJSContext;
   nsString mScriptURL;
   nsCString mDomain;
   LocationInfo mLocationInfo;
 
   // Main-thread things.
   nsCOMPtr<nsPIDOMWindow> mWindow;
   nsCOMPtr<nsIScriptContext> mScriptContext;
+  nsCOMPtr<nsIXPCScriptNotify> mScriptNotify;
   nsCOMPtr<nsIURI> mBaseURI;
   nsCOMPtr<nsIURI> mScriptURI;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsIDocument> mDocument;
 
   // Only used for top level workers.
   nsTArray<nsRefPtr<WorkerRunnable> > mQueuedRunnables;
 
@@ -381,16 +385,23 @@ public:
 
   nsIScriptContext*
   GetScriptContext() const
   {
     AssertIsOnMainThread();
     return mScriptContext;
   }
 
+  nsIXPCScriptNotify*
+  GetScriptNotify() const
+  {
+    AssertIsOnMainThread();
+    return mScriptNotify;
+  }
+
   JSObject*
   GetJSObject() const
   {
     return mJSObject;
   }
 
   const nsString&
   ScriptURL() const