From ab4411fee4cf2dae84dde7b739d19d118b078f6c Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Thu, 30 Jan 2014 21:35:44 -0800 Subject: [PATCH] Backout Bug 930793 - Remove favor performance mode (we have still racy b2g tests), a=backout --HG-- extra : rebase_source : 6f6de1cbf54670d63b74c44ca0134ed9c5354d2b --- content/base/src/nsContentSink.cpp | 17 +++++++++ content/base/src/nsContentSink.h | 3 ++ docshell/base/nsDocShell.cpp | 38 +++++++++++++++++++ .../mochitest/general/test_vibrator.html | 2 +- .../pointerlock/file_screenClientXYConst.html | 4 +- layout/base/nsRefreshDriver.cpp | 2 +- view/public/nsViewManager.h | 7 +--- view/src/nsViewManager.cpp | 14 ++----- widget/cocoa/nsChildView.h | 1 - widget/cocoa/nsChildView.mm | 12 ------ widget/gtk/nsWindow.cpp | 8 ---- widget/gtk/nsWindow.h | 1 - widget/nsIAppShell.idl | 18 +++++++++ widget/nsIWidget.h | 9 +---- widget/windows/nsWindow.cpp | 8 ---- widget/windows/nsWindow.h | 1 - widget/windows/winrt/MetroWidget.cpp | 8 ---- widget/windows/winrt/MetroWidget.h | 1 - widget/xpwidgets/nsBaseAppShell.cpp | 38 ++++++++++++++++++- widget/xpwidgets/nsBaseAppShell.h | 4 ++ 20 files changed, 127 insertions(+), 69 deletions(-) diff --git a/content/base/src/nsContentSink.cpp b/content/base/src/nsContentSink.cpp index 6600d488d0c8..77226000e573 100644 --- a/content/base/src/nsContentSink.cpp +++ b/content/base/src/nsContentSink.cpp @@ -200,6 +200,7 @@ nsContentSink::Init(nsIDocument* aDoc, if (sEnablePerfMode != 0) { mDynamicLowerValue = sEnablePerfMode == 1; + FavorPerformanceHint(!mDynamicLowerValue, 0); } return NS_OK; @@ -1375,6 +1376,15 @@ nsContentSink::DidProcessATokenImpl() //---------------------------------------------------------------------- +void +nsContentSink::FavorPerformanceHint(bool perfOverStarvation, uint32_t starvationDelay) +{ + static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); + nsCOMPtr appShell = do_GetService(kAppShellCID); + if (appShell) + appShell->FavorPerformanceHint(perfOverStarvation, starvationDelay); +} + void nsContentSink::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType) { @@ -1452,6 +1462,12 @@ nsContentSink::DropParserAndPerfHint(void) // reference. nsRefPtr kungFuDeathGrip(mParser.forget()); + if (mDynamicLowerValue) { + // Reset the performance hint which was set to FALSE + // when mDynamicLowerValue was set. + FavorPerformanceHint(true, 0); + } + if (!mRunsToCompletion) { mDocument->UnblockOnload(true); } @@ -1489,6 +1505,7 @@ nsContentSink::WillParseImpl(void) (currentTime - lastEventTime) < uint32_t(sInteractiveTime)); if (mDynamicLowerValue != newDynLower) { + FavorPerformanceHint(!newDynLower, 0); mDynamicLowerValue = newDynLower; } } diff --git a/content/base/src/nsContentSink.h b/content/base/src/nsContentSink.h index febacd3abe83..305f828c9c44 100644 --- a/content/base/src/nsContentSink.h +++ b/content/base/src/nsContentSink.h @@ -237,6 +237,9 @@ public: static void NotifyDocElementCreated(nsIDocument* aDoc); protected: + void + FavorPerformanceHint(bool perfOverStarvation, uint32_t starvationDelay); + inline int32_t GetNotificationInterval() { if (mDynamicLowerValue) { diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index c1262e6bdaeb..d85991a42b4e 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -211,6 +211,9 @@ static bool gAddedPreferencesVarCache = false; bool nsDocShell::sUseErrorPages = false; +// Number of documents currently loading +static int32_t gNumberOfDocumentsLoading = 0; + // Global count of existing docshells. static int32_t gDocShellCount = 0; @@ -241,6 +244,17 @@ static PRLogModuleInfo* gDocShellLeakLog; const char kBrandBundleURL[] = "chrome://branding/locale/brand.properties"; const char kAppstringsBundleURL[] = "chrome://global/locale/appstrings.properties"; +static void +FavorPerformanceHint(bool perfOverStarvation) +{ + nsCOMPtr appShell = do_GetService(kAppShellCID); + if (appShell) { + appShell->FavorPerformanceHint(perfOverStarvation, + Preferences::GetUint("docshell.event_starvation_delay_hint", + NS_EVENT_STARVATION_DELAY_HINT)); + } +} + //***************************************************************************** // support //***************************************************************************** @@ -6852,6 +6866,14 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress, mIsExecutingOnLoadHandler = false; mEODForCurrentDocument = true; + + // If all documents have completed their loading + // favor native event dispatch priorities + // over performance + if (--gNumberOfDocumentsLoading == 0) { + // Hint to use normal native event dispatch priorities + FavorPerformanceHint(false); + } } /* Check if the httpChannel has any cache-control related response headers, * like no-store, no-cache. If so, update SHEntry so that @@ -7855,6 +7877,12 @@ nsDocShell::RestoreFromHistory() mSavingOldViewer = false; mEODForCurrentDocument = false; + // Tell the event loop to favor plevents over user events, see comments + // in CreateContentViewer. + if (++gNumberOfDocumentsLoading == 1) + FavorPerformanceHint(true); + + if (oldMUDV && newMUDV) { newMUDV->SetMinFontSize(minFontSize); newMUDV->SetTextZoom(textZoom); @@ -8251,6 +8279,16 @@ nsDocShell::CreateContentViewer(const char *aContentType, } } + // Give hint to native plevent dispatch mechanism. If a document + // is loading the native plevent dispatch mechanism should favor + // performance over normal native event dispatch priorities. + if (++gNumberOfDocumentsLoading == 1) { + // Hint to favor performance for the plevent notification mechanism. + // We want the pages to load as fast as possible even if its means + // native messages might be starved. + FavorPerformanceHint(true); + } + if (onLocationChangeNeeded) { FireOnLocationChange(this, request, mCurrentURI, 0); } diff --git a/dom/tests/mochitest/general/test_vibrator.html b/dom/tests/mochitest/general/test_vibrator.html index 92990c7f61e3..fea819af939a 100644 --- a/dom/tests/mochitest/general/test_vibrator.html +++ b/dom/tests/mochitest/general/test_vibrator.html @@ -57,7 +57,7 @@ function testSuccesses() { expectSuccess([1000, 1000.1]); // The following loop shouldn't cause us to crash. See bug 701716. - for (var i = 0; i < 1000; i++) { + for (var i = 0; i < 10000; i++) { navigator.vibrate([100, 100]); } ok(true, "Didn't crash after issuing a lot of vibrate() calls."); diff --git a/dom/tests/mochitest/pointerlock/file_screenClientXYConst.html b/dom/tests/mochitest/pointerlock/file_screenClientXYConst.html index 9378855e76b3..97f49e085f78 100644 --- a/dom/tests/mochitest/pointerlock/file_screenClientXYConst.html +++ b/dom/tests/mochitest/pointerlock/file_screenClientXYConst.html @@ -51,9 +51,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=633602 var firstCall = !unLockedCoords; if (!firstCall) { todo(false, "mousemove is fired twice."); - } else { - isUnlocked = !document.mozPointerLockElement; } + + isUnlocked = !document.mozPointerLockElement; unLockedCoords = { screenX: e.screenX, screenY: e.screenY, diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index 26b84f9920ee..82419d1ecf01 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -1204,7 +1204,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime) mViewManagerFlushIsPending = false; nsRefPtr vm = mPresContext->GetPresShell()->GetViewManager(); - vm->ProcessPendingUpdates(nsViewManager::eTrySyncUpdate); + vm->ProcessPendingUpdates(); #ifdef MOZ_DUMP_PAINTING if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { printf_stderr("Ending ProcessPendingUpdates\n"); diff --git a/view/public/nsViewManager.h b/view/public/nsViewManager.h index e55a0aeea98e..6885827c6dbb 100644 --- a/view/public/nsViewManager.h +++ b/view/public/nsViewManager.h @@ -302,16 +302,11 @@ public: */ static nsView* GetDisplayRootFor(nsView* aView); - enum UpdatingMode { - eNoSyncUpdate, - eTrySyncUpdate - }; - /** * Flush the accumulated dirty region to the widget and update widget * geometry. */ - void ProcessPendingUpdates(UpdatingMode aMode); + void ProcessPendingUpdates(); /** * Just update widget geometry without flushing the dirty region diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index c784b1de84bb..75fd3e669955 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -654,7 +654,7 @@ void nsViewManager::WillPaintWindow(nsIWidget* aWidget) LayerManager *manager = aWidget->GetLayerManager(); if (view && (view->ForcedRepaint() || !manager->NeedsWidgetInvalidation())) { - ProcessPendingUpdates(eNoSyncUpdate); + ProcessPendingUpdates(); // Re-get the view pointer here since the ProcessPendingUpdates might have // destroyed it during CallWillPaintOnObservers. view = nsView::GetViewFor(aWidget); @@ -1037,10 +1037,10 @@ nsViewManager::IsPainting(bool& aIsPainting) } void -nsViewManager::ProcessPendingUpdates(UpdatingMode aMode) +nsViewManager::ProcessPendingUpdates() { if (!IsRootVM()) { - RootViewManager()->ProcessPendingUpdates(aMode); + RootViewManager()->ProcessPendingUpdates(); return; } @@ -1051,14 +1051,6 @@ nsViewManager::ProcessPendingUpdates(UpdatingMode aMode) CallWillPaintOnObservers(); } ProcessPendingUpdatesForView(mRootView, true); - - if (aMode == eTrySyncUpdate) { - nsCOMPtr w; - GetRootWidget(getter_AddRefs(w)); - if (w) { - w->Update(); - } - } } void diff --git a/widget/cocoa/nsChildView.h b/widget/cocoa/nsChildView.h index 3f4f6ab623a9..80542401f0a3 100644 --- a/widget/cocoa/nsChildView.h +++ b/widget/cocoa/nsChildView.h @@ -490,7 +490,6 @@ public: virtual int32_t RoundsWidgetCoordinatesTo() MOZ_OVERRIDE; NS_IMETHOD Invalidate(const nsIntRect &aRect); - virtual void Update() MOZ_OVERRIDE; virtual void* GetNativeData(uint32_t aDataType); virtual nsresult ConfigureChildren(const nsTArray& aConfigurations); diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index 8b2a1e358aaf..23b2b6299744 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -1581,18 +1581,6 @@ NS_IMETHODIMP nsChildView::Invalidate(const nsIntRect &aRect) NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; } -void -nsChildView::Update() -{ - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; - - if (!ShouldUseOffMainThreadCompositing() && mView) { - [mView displayIfNeeded]; - } - - NS_OBJC_END_TRY_ABORT_BLOCK; -} - bool nsChildView::ComputeShouldAccelerate(bool aDefault) { diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp index 5e7a4223b323..d2dada1ef4d9 100644 --- a/widget/gtk/nsWindow.cpp +++ b/widget/gtk/nsWindow.cpp @@ -1617,14 +1617,6 @@ nsWindow::Invalidate(const nsIntRect &aRect) return NS_OK; } -void -nsWindow::Update() -{ - if (!ShouldUseOffMainThreadCompositing() && mGdkWindow) { - gdk_window_process_updates(mGdkWindow, true); - } -} - void* nsWindow::GetNativeData(uint32_t aDataType) { diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h index 80ba6143a300..1248faa08899 100644 --- a/widget/gtk/nsWindow.h +++ b/widget/gtk/nsWindow.h @@ -138,7 +138,6 @@ public: NS_IMETHOD SetCursor(imgIContainer* aCursor, uint32_t aHotspotX, uint32_t aHotspotY); NS_IMETHOD Invalidate(const nsIntRect &aRect); - virtual void Update() MOZ_OVERRIDE; virtual void* GetNativeData(uint32_t aDataType); NS_IMETHOD SetTitle(const nsAString& aTitle); NS_IMETHOD SetIcon(const nsAString& aIconSpec); diff --git a/widget/nsIAppShell.idl b/widget/nsIAppShell.idl index be4e6eac5283..3c0af793c633 100644 --- a/widget/nsIAppShell.idl +++ b/widget/nsIAppShell.idl @@ -25,6 +25,24 @@ interface nsIAppShell : nsISupports */ void exit(); + /** + * Give hint to native event queue notification mechanism. If the native + * platform needs to tradeoff performance vs. native event starvation this + * hint tells the native dispatch code which to favor. The default is to + * prevent native event starvation. + * + * Calls to this function may be nested. When the number of calls that pass + * PR_TRUE is subtracted from the number of calls that pass PR_FALSE is + * greater than 0, performance is given precedence over preventing event + * starvation. + * + * The starvationDelay arg is only used when favorPerfOverStarvation is + * PR_FALSE. It is the amount of time in milliseconds to wait before the + * PR_FALSE actually takes effect. + */ + void favorPerformanceHint(in boolean favorPerfOverStarvation, + in unsigned long starvationDelay); + /** * Suspends the use of additional platform-specific methods (besides the * nsIAppShell->run() event loop) to run Gecko events on the main diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index 387a3ca5201d..f6cae0a15e7c 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -100,8 +100,8 @@ typedef void* nsNativeWidget; #endif #define NS_IWIDGET_IID \ -{ 0x0a157edd, 0xd70b, 0x4242, \ - { 0xad, 0xd5, 0xcb, 0xce, 0x4c, 0xf3, 0x4b, 0x47 } } +{ 0x67da44c4, 0xe21b, 0x4742, \ + { 0x9c, 0x2b, 0x26, 0xc7, 0x70, 0x21, 0xde, 0x87 } } /* * Window shadow styles @@ -1197,11 +1197,6 @@ class nsIWidget : public nsISupports { */ NS_IMETHOD Invalidate(const nsIntRect & aRect) = 0; - /** - * Widget implementation may support synchronous painting. - */ - virtual void Update() { } - enum LayerManagerPersistence { LAYER_MANAGER_CURRENT = 0, diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 6c6d68a9877a..a5f250e0207e 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -2775,14 +2775,6 @@ NS_METHOD nsWindow::Invalidate(const nsIntRect & aRect) return NS_OK; } -void -nsWindow::Update() -{ - if (!ShouldUseOffMainThreadCompositing() && mWnd) { - ::UpdateWindow(mWnd); - } -} - NS_IMETHODIMP nsWindow::MakeFullScreen(bool aFullScreen) { diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h index 44d859df8938..9919c435e30e 100644 --- a/widget/windows/nsWindow.h +++ b/widget/windows/nsWindow.h @@ -137,7 +137,6 @@ public: bool aUpdateNCArea = false, bool aIncludeChildren = false); NS_IMETHOD Invalidate(const nsIntRect & aRect); - virtual void Update() MOZ_OVERRIDE; virtual void* GetNativeData(uint32_t aDataType); virtual void FreeNativeData(void * data, uint32_t aDataType); NS_IMETHOD SetTitle(const nsAString& aTitle); diff --git a/widget/windows/winrt/MetroWidget.cpp b/widget/windows/winrt/MetroWidget.cpp index 366cf4a9bd3b..4f1edc8498c5 100644 --- a/widget/windows/winrt/MetroWidget.cpp +++ b/widget/windows/winrt/MetroWidget.cpp @@ -1268,14 +1268,6 @@ MetroWidget::Invalidate(const nsIntRect & aRect) return NS_OK; } -void -MetroWidget::Update() -{ - if (!ShouldUseOffMainThreadCompositing() && mWnd) { - ::UpdateWindow(mWnd); - } -} - nsTransparencyMode MetroWidget::GetTransparencyMode() { diff --git a/widget/windows/winrt/MetroWidget.h b/widget/windows/winrt/MetroWidget.h index 263bb0f451ee..1c8308dbbad0 100644 --- a/widget/windows/winrt/MetroWidget.h +++ b/widget/windows/winrt/MetroWidget.h @@ -109,7 +109,6 @@ public: bool aUpdateNCArea = false, bool aIncludeChildren = false); NS_IMETHOD Invalidate(const nsIntRect & aRect); - virtual void Update() MOZ_OVERRIDE; NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent, nsEventStatus& aStatus); NS_IMETHOD ConstrainPosition(bool aAllowSlop, int32_t *aX, int32_t *aY); diff --git a/widget/xpwidgets/nsBaseAppShell.cpp b/widget/xpwidgets/nsBaseAppShell.cpp index 946ee0f35bf8..1193a2a9e501 100644 --- a/widget/xpwidgets/nsBaseAppShell.cpp +++ b/widget/xpwidgets/nsBaseAppShell.cpp @@ -22,7 +22,11 @@ nsBaseAppShell::nsBaseAppShell() : mSuspendNativeCount(0) , mEventloopNestingLevel(0) , mBlockedWait(nullptr) + , mFavorPerf(0) , mNativeEventPending(0) + , mStarvationDelay(0) + , mSwitchTime(0) + , mLastNativeEventTime(0) , mEventloopNestingState(eEventloopNone) , mRunning(false) , mExiting(false) @@ -172,6 +176,20 @@ nsBaseAppShell::Exit(void) return NS_OK; } +NS_IMETHODIMP +nsBaseAppShell::FavorPerformanceHint(bool favorPerfOverStarvation, + uint32_t starvationDelay) +{ + mStarvationDelay = PR_MillisecondsToInterval(starvationDelay); + if (favorPerfOverStarvation) { + ++mFavorPerf; + } else { + --mFavorPerf; + mSwitchTime = PR_IntervalNow(); + } + return NS_OK; +} + NS_IMETHODIMP nsBaseAppShell::SuspendNative() { @@ -232,6 +250,9 @@ nsBaseAppShell::OnProcessNextEvent(nsIThreadInternal *thr, bool mayWait, OnDispatchedEvent(thr); // in case we blocked it earlier } + PRIntervalTime start = PR_IntervalNow(); + PRIntervalTime limit = THREAD_EVENT_STARVATION_LIMIT; + // Unblock outer nested wait loop (below). if (mBlockedWait) *mBlockedWait = false; @@ -247,7 +268,21 @@ nsBaseAppShell::OnProcessNextEvent(nsIThreadInternal *thr, bool mayWait, // NativeEventCallback to process gecko events. mProcessedGeckoEvents = false; - DoProcessNextNativeEvent(false, recursionDepth); + if (mFavorPerf <= 0 && start > mSwitchTime + mStarvationDelay) { + // Favor pending native events + PRIntervalTime now = start; + bool keepGoing; + do { + mLastNativeEventTime = now; + keepGoing = DoProcessNextNativeEvent(false, recursionDepth); + } while (keepGoing && ((now = PR_IntervalNow()) - start) < limit); + } else { + // Avoid starving native events completely when in performance mode + if (start - mLastNativeEventTime > limit) { + mLastNativeEventTime = start; + DoProcessNextNativeEvent(false, recursionDepth); + } + } while (!NS_HasPendingEvents(thr) && !mProcessedGeckoEvents) { // If we have been asked to exit from Run, then we should not wait for @@ -256,6 +291,7 @@ nsBaseAppShell::OnProcessNextEvent(nsIThreadInternal *thr, bool mayWait, if (mExiting) mayWait = false; + mLastNativeEventTime = PR_IntervalNow(); if (!DoProcessNextNativeEvent(mayWait, recursionDepth) || !mayWait) break; } diff --git a/widget/xpwidgets/nsBaseAppShell.h b/widget/xpwidgets/nsBaseAppShell.h index d67dd9786ec5..c976a2286eea 100644 --- a/widget/xpwidgets/nsBaseAppShell.h +++ b/widget/xpwidgets/nsBaseAppShell.h @@ -119,7 +119,11 @@ private: * have been consumed by the inner event loop(s). */ bool *mBlockedWait; + int32_t mFavorPerf; mozilla::Atomic mNativeEventPending; + PRIntervalTime mStarvationDelay; + PRIntervalTime mSwitchTime; + PRIntervalTime mLastNativeEventTime; enum EventloopNestingState { eEventloopNone, // top level thread execution eEventloopXPCOM, // innermost native event loop is ProcessNextNativeEvent