Bug 1382861 - 2. Don't use priority queue for GeckoView.Window and ThumbnailHelper; r=esawin
authorJim Chen <nchen@mozilla.com>
Tue, 25 Jul 2017 17:26:14 -0400
changeset 419695 9e9270da4f55d22a25e51a07d411d7216687fb77
parent 419694 9c322ac1b41d89d2f952db9fc49aa0af3c03a13b
child 419696 cb3966784befbe11354b79598926681cd4088072
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersesawin
bugs1382861
milestone56.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 1382861 - 2. Don't use priority queue for GeckoView.Window and ThumbnailHelper; r=esawin Use the regular XPCOM queue for those tasks because the priority queue should only be used for input and other timing-sensitive tasks. MozReview-Commit-ID: 5px0s0PJYrV
widget/android/fennec/ThumbnailHelper.h
widget/android/nsWindow.cpp
--- a/widget/android/fennec/ThumbnailHelper.h
+++ b/widget/android/fennec/ThumbnailHelper.h
@@ -189,34 +189,47 @@ public:
     static void Init()
     {
         java::ThumbnailHelper::Natives<ThumbnailHelper>::Init();
     }
 
     template<class Functor>
     static void OnNativeCall(Functor&& aCall)
     {
-        class IdleEvent : public nsAppShell::LambdaEvent<Functor>
+        class IdleEvent : public Runnable
         {
-            using Base = nsAppShell::LambdaEvent<Functor>;
+            Functor mLambda;
+            bool mIdlePass;
 
         public:
             IdleEvent(Functor&& aCall)
-                : Base(Forward<Functor>(aCall))
+                : Runnable("ThumbnailHelperIdle")
+                , mLambda(Move(aCall))
+                , mIdlePass(false)
             {}
 
-            void Run() override
+            NS_IMETHOD Run() override
             {
+                // Because we can only post to the idle queue from the main
+                // queue, we must first post to the main queue and then to the
+                // idle queue. However, we use the same runnable object for
+                // both queues, and use mIdlePass to track our progress.
+                if (mIdlePass) {
+                    mLambda();
+                    return NS_OK;
+                }
+
+                mIdlePass = true;
                 MessageLoop::current()->PostIdleTask(
-                    NS_NewRunnableFunction("OnNativeCall", Move(Base::lambda)));
+                        nsCOMPtr<nsIRunnable>(this).forget());
+                return NS_OK;
             }
         };
 
-        // Invoke RequestThumbnail on the main thread when the thread is idle.
-        nsAppShell::PostEvent(MakeUnique<IdleEvent>(Forward<Functor>(aCall)));
+        NS_DispatchToMainThread(new IdleEvent(Move(aCall)));
     }
 
     static void
     RequestThumbnail(jni::ByteBuffer::Param aData, jni::Object::Param aTab,
                      int32_t aTabId, int32_t aWidth, int32_t aHeight)
     {
         nsCOMPtr<mozIDOMWindowProxy> window = GetWindowForTab(aTabId);
         if (!window || !aData) {
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -111,21 +111,18 @@ static nsTArray<nsWindow*> gTopLevelWind
 
 static bool sFailedToCreateGLContext = false;
 
 // Multitouch swipe thresholds in inches
 static const double SWIPE_MAX_PINCH_DELTA_INCHES = 0.4;
 static const double SWIPE_MIN_DISTANCE_INCHES = 0.6;
 
 template<typename Lambda, bool IsStatic, typename InstanceType, class Impl>
-class nsWindow::WindowEvent : public nsAppShell::LambdaEvent<Lambda>
+class nsWindow::WindowEvent : public Runnable
 {
-    typedef nsAppShell::Event Event;
-    typedef nsAppShell::LambdaEvent<Lambda> Base;
-
     bool IsStaleCall()
     {
         if (IsStatic) {
             // Static calls are never stale.
             return false;
         }
 
         JNIEnv* const env = mozilla::jni::GetEnvForThread();
@@ -137,45 +134,39 @@ class nsWindow::WindowEvent : public nsA
         // The call is stale if the nsWindow has been destroyed on the
         // Gecko side, but the Java object is still attached to it through
         // a weak pointer. Stale calls should be discarded. Note that it's
         // an error if natives is nullptr here; we return false but the
         // native call will throw an error.
         return natives && !natives->get();
     }
 
+    Lambda mLambda;
     const InstanceType mInstance;
-    const Event::Type mEventType;
 
 public:
     WindowEvent(Lambda&& aLambda,
-                InstanceType&& aInstance,
-                Event::Type aEventType = Event::Type::kGeneralActivity)
-        : Base(mozilla::Move(aLambda))
-        , mInstance(mozilla::Move(aInstance))
-        , mEventType(aEventType)
+                InstanceType&& aInstance)
+        : Runnable("nsWindowEvent")
+        , mLambda(mozilla::Move(aLambda))
+        , mInstance(Forward<InstanceType>(aInstance))
     {}
 
-    WindowEvent(Lambda&& aLambda,
-                Event::Type aEventType = Event::Type::kGeneralActivity)
-        : Base(mozilla::Move(aLambda))
-        , mInstance(Base::lambda.GetThisArg())
-        , mEventType(aEventType)
+    WindowEvent(Lambda&& aLambda)
+        : Runnable("nsWindowEvent")
+        , mLambda(mozilla::Move(aLambda))
+        , mInstance(mLambda.GetThisArg())
     {}
 
-    void Run() override
+    NS_IMETHOD Run() override
     {
         if (!IsStaleCall()) {
-            return Base::Run();
+            mLambda();
         }
-    }
-
-    Event::Type ActivityType() const override
-    {
-        return mEventType;
+        return NS_OK;
     }
 };
 
 namespace {
     template<class Instance, class Impl> typename EnableIf<
         jni::detail::NativePtrPicker<Impl>::value ==
         jni::detail::REFPTR, void>::Type
     CallAttachNative(Instance aInstance, Impl* aImpl)
@@ -259,18 +250,17 @@ public:
     {
         if (aCall.IsTarget(&Open) && NS_IsMainThread()) {
             // Gecko state probably just switched to PROFILE_READY, and the
             // event loop is not running yet. Skip the event loop here so we
             // can get a head start on opening our window.
             return aCall();
         }
 
-        nsAppShell::PostEvent(mozilla::MakeUnique<WindowEvent<Functor>>(
-                mozilla::Move(aCall)));
+        NS_DispatchToMainThread(new WindowEvent<Functor>(mozilla::Move(aCall)));
     }
 
     GeckoViewSupport(nsWindow* aWindow,
                      const GeckoView::Window::LocalRef& aInstance)
         : window(*aWindow)
         , mGeckoViewWindow(aInstance)
     {
         Base::AttachNative(aInstance, static_cast<SupportsWeakPtr*>(this));
@@ -358,16 +348,17 @@ class nsWindow::NPZCSupport final
         {
             return nsAppShell::Event::Type::kUIActivity;
         }
     };
 
     template<typename Lambda>
     void PostInputEvent(Lambda&& aLambda)
     {
+        // Use priority queue for input events.
         nsAppShell::PostEvent(MakeUnique<InputEvent<Lambda>>(
                 this, mozilla::Move(aLambda)));
     }
 
 public:
     typedef NativePanZoomController::Natives<NPZCSupport> Base;
 
     NPZCSupport(NativePtr<NPZCSupport>* aPtr, nsWindow* aWindow,
@@ -992,16 +983,17 @@ public:
                         LayerView::Compositor::LocalRef(env, mCompositor))) {
                     MOZ_CATCH_JNI_EXCEPTION(env);
 
                     lvs->OnResumedCompositor();
                 }
             }
         };
 
+        // Use priority queue for timing-sensitive event.
         nsAppShell::PostEvent(MakeUnique<LayerViewEvent>(
                 MakeUnique<OnResumedEvent>(aObj)));
     }
 
     void SyncInvalidateAndScheduleComposite()
     {
         RefPtr<UiCompositorControllerChild> child = GetUiCompositorControllerChild();
         if (!child) {