Backed out changeset 347d5704cbe1 (bug 930793) for frequent Linux mochitest-bc orange.

CLOSED TREE
This commit is contained in:
Ryan VanderMeulen 2014-01-15 14:11:20 -05:00
parent ba2e827564
commit 3d4fa83a0c
20 changed files with 127 additions and 69 deletions

View File

@ -200,6 +200,7 @@ nsContentSink::Init(nsIDocument* aDoc,
if (sEnablePerfMode != 0) { if (sEnablePerfMode != 0) {
mDynamicLowerValue = sEnablePerfMode == 1; mDynamicLowerValue = sEnablePerfMode == 1;
FavorPerformanceHint(!mDynamicLowerValue, 0);
} }
return NS_OK; 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<nsIAppShell> appShell = do_GetService(kAppShellCID);
if (appShell)
appShell->FavorPerformanceHint(perfOverStarvation, starvationDelay);
}
void void
nsContentSink::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType) nsContentSink::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
{ {
@ -1452,6 +1462,12 @@ nsContentSink::DropParserAndPerfHint(void)
// reference. // reference.
nsRefPtr<nsParserBase> kungFuDeathGrip(mParser.forget()); nsRefPtr<nsParserBase> kungFuDeathGrip(mParser.forget());
if (mDynamicLowerValue) {
// Reset the performance hint which was set to FALSE
// when mDynamicLowerValue was set.
FavorPerformanceHint(true, 0);
}
if (!mRunsToCompletion) { if (!mRunsToCompletion) {
mDocument->UnblockOnload(true); mDocument->UnblockOnload(true);
} }
@ -1489,6 +1505,7 @@ nsContentSink::WillParseImpl(void)
(currentTime - lastEventTime) < uint32_t(sInteractiveTime)); (currentTime - lastEventTime) < uint32_t(sInteractiveTime));
if (mDynamicLowerValue != newDynLower) { if (mDynamicLowerValue != newDynLower) {
FavorPerformanceHint(!newDynLower, 0);
mDynamicLowerValue = newDynLower; mDynamicLowerValue = newDynLower;
} }
} }

View File

@ -237,6 +237,9 @@ public:
static void NotifyDocElementCreated(nsIDocument* aDoc); static void NotifyDocElementCreated(nsIDocument* aDoc);
protected: protected:
void
FavorPerformanceHint(bool perfOverStarvation, uint32_t starvationDelay);
inline int32_t GetNotificationInterval() inline int32_t GetNotificationInterval()
{ {
if (mDynamicLowerValue) { if (mDynamicLowerValue) {

View File

@ -211,6 +211,9 @@ static bool gAddedPreferencesVarCache = false;
bool nsDocShell::sUseErrorPages = false; bool nsDocShell::sUseErrorPages = false;
// Number of documents currently loading
static int32_t gNumberOfDocumentsLoading = 0;
// Global count of existing docshells. // Global count of existing docshells.
static int32_t gDocShellCount = 0; static int32_t gDocShellCount = 0;
@ -241,6 +244,17 @@ static PRLogModuleInfo* gDocShellLeakLog;
const char kBrandBundleURL[] = "chrome://branding/locale/brand.properties"; const char kBrandBundleURL[] = "chrome://branding/locale/brand.properties";
const char kAppstringsBundleURL[] = "chrome://global/locale/appstrings.properties"; const char kAppstringsBundleURL[] = "chrome://global/locale/appstrings.properties";
static void
FavorPerformanceHint(bool perfOverStarvation)
{
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
if (appShell) {
appShell->FavorPerformanceHint(perfOverStarvation,
Preferences::GetUint("docshell.event_starvation_delay_hint",
NS_EVENT_STARVATION_DELAY_HINT));
}
}
//***************************************************************************** //*****************************************************************************
// <a ping> support // <a ping> support
//***************************************************************************** //*****************************************************************************
@ -6851,6 +6865,14 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress,
mIsExecutingOnLoadHandler = false; mIsExecutingOnLoadHandler = false;
mEODForCurrentDocument = true; 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, /* Check if the httpChannel has any cache-control related response headers,
* like no-store, no-cache. If so, update SHEntry so that * like no-store, no-cache. If so, update SHEntry so that
@ -7854,6 +7876,12 @@ nsDocShell::RestoreFromHistory()
mSavingOldViewer = false; mSavingOldViewer = false;
mEODForCurrentDocument = 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) { if (oldMUDV && newMUDV) {
newMUDV->SetMinFontSize(minFontSize); newMUDV->SetMinFontSize(minFontSize);
newMUDV->SetTextZoom(textZoom); newMUDV->SetTextZoom(textZoom);
@ -8250,6 +8278,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) { if (onLocationChangeNeeded) {
FireOnLocationChange(this, request, mCurrentURI, 0); FireOnLocationChange(this, request, mCurrentURI, 0);
} }

View File

@ -57,7 +57,7 @@ function testSuccesses() {
expectSuccess([1000, 1000.1]); expectSuccess([1000, 1000.1]);
// The following loop shouldn't cause us to crash. See bug 701716. // 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]); navigator.vibrate([100, 100]);
} }
ok(true, "Didn't crash after issuing a lot of vibrate() calls."); ok(true, "Didn't crash after issuing a lot of vibrate() calls.");

View File

@ -51,9 +51,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=633602
var firstCall = !unLockedCoords; var firstCall = !unLockedCoords;
if (!firstCall) { if (!firstCall) {
todo(false, "mousemove is fired twice."); todo(false, "mousemove is fired twice.");
} else {
isUnlocked = !document.mozPointerLockElement;
} }
isUnlocked = !document.mozPointerLockElement;
unLockedCoords = { unLockedCoords = {
screenX: e.screenX, screenX: e.screenX,
screenY: e.screenY, screenY: e.screenY,

View File

@ -1204,7 +1204,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
mViewManagerFlushIsPending = false; mViewManagerFlushIsPending = false;
nsRefPtr<nsViewManager> vm = mPresContext->GetPresShell()->GetViewManager(); nsRefPtr<nsViewManager> vm = mPresContext->GetPresShell()->GetViewManager();
vm->ProcessPendingUpdates(nsViewManager::eTrySyncUpdate); vm->ProcessPendingUpdates();
#ifdef MOZ_DUMP_PAINTING #ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("Ending ProcessPendingUpdates\n"); printf_stderr("Ending ProcessPendingUpdates\n");

View File

@ -302,16 +302,11 @@ public:
*/ */
static nsView* GetDisplayRootFor(nsView* aView); static nsView* GetDisplayRootFor(nsView* aView);
enum UpdatingMode {
eNoSyncUpdate,
eTrySyncUpdate
};
/** /**
* Flush the accumulated dirty region to the widget and update widget * Flush the accumulated dirty region to the widget and update widget
* geometry. * geometry.
*/ */
void ProcessPendingUpdates(UpdatingMode aMode); void ProcessPendingUpdates();
/** /**
* Just update widget geometry without flushing the dirty region * Just update widget geometry without flushing the dirty region

View File

@ -654,7 +654,7 @@ void nsViewManager::WillPaintWindow(nsIWidget* aWidget)
LayerManager *manager = aWidget->GetLayerManager(); LayerManager *manager = aWidget->GetLayerManager();
if (view && if (view &&
(view->ForcedRepaint() || !manager->NeedsWidgetInvalidation())) { (view->ForcedRepaint() || !manager->NeedsWidgetInvalidation())) {
ProcessPendingUpdates(eNoSyncUpdate); ProcessPendingUpdates();
// Re-get the view pointer here since the ProcessPendingUpdates might have // Re-get the view pointer here since the ProcessPendingUpdates might have
// destroyed it during CallWillPaintOnObservers. // destroyed it during CallWillPaintOnObservers.
view = nsView::GetViewFor(aWidget); view = nsView::GetViewFor(aWidget);
@ -1037,10 +1037,10 @@ nsViewManager::IsPainting(bool& aIsPainting)
} }
void void
nsViewManager::ProcessPendingUpdates(UpdatingMode aMode) nsViewManager::ProcessPendingUpdates()
{ {
if (!IsRootVM()) { if (!IsRootVM()) {
RootViewManager()->ProcessPendingUpdates(aMode); RootViewManager()->ProcessPendingUpdates();
return; return;
} }
@ -1051,14 +1051,6 @@ nsViewManager::ProcessPendingUpdates(UpdatingMode aMode)
CallWillPaintOnObservers(); CallWillPaintOnObservers();
} }
ProcessPendingUpdatesForView(mRootView, true); ProcessPendingUpdatesForView(mRootView, true);
if (aMode == eTrySyncUpdate) {
nsCOMPtr<nsIWidget> w;
GetRootWidget(getter_AddRefs(w));
if (w) {
w->Update();
}
}
} }
void void

View File

@ -486,7 +486,6 @@ public:
virtual int32_t RoundsWidgetCoordinatesTo() MOZ_OVERRIDE; virtual int32_t RoundsWidgetCoordinatesTo() MOZ_OVERRIDE;
NS_IMETHOD Invalidate(const nsIntRect &aRect); NS_IMETHOD Invalidate(const nsIntRect &aRect);
virtual void Update() MOZ_OVERRIDE;
virtual void* GetNativeData(uint32_t aDataType); virtual void* GetNativeData(uint32_t aDataType);
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations); virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations);

View File

@ -1580,18 +1580,6 @@ NS_IMETHODIMP nsChildView::Invalidate(const nsIntRect &aRect)
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT; 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 bool
nsChildView::ComputeShouldAccelerate(bool aDefault) nsChildView::ComputeShouldAccelerate(bool aDefault)
{ {

View File

@ -1617,14 +1617,6 @@ nsWindow::Invalidate(const nsIntRect &aRect)
return NS_OK; return NS_OK;
} }
void
nsWindow::Update()
{
if (!ShouldUseOffMainThreadCompositing() && mGdkWindow) {
gdk_window_process_updates(mGdkWindow, true);
}
}
void* void*
nsWindow::GetNativeData(uint32_t aDataType) nsWindow::GetNativeData(uint32_t aDataType)
{ {

View File

@ -138,7 +138,6 @@ public:
NS_IMETHOD SetCursor(imgIContainer* aCursor, NS_IMETHOD SetCursor(imgIContainer* aCursor,
uint32_t aHotspotX, uint32_t aHotspotY); uint32_t aHotspotX, uint32_t aHotspotY);
NS_IMETHOD Invalidate(const nsIntRect &aRect); NS_IMETHOD Invalidate(const nsIntRect &aRect);
virtual void Update() MOZ_OVERRIDE;
virtual void* GetNativeData(uint32_t aDataType); virtual void* GetNativeData(uint32_t aDataType);
NS_IMETHOD SetTitle(const nsAString& aTitle); NS_IMETHOD SetTitle(const nsAString& aTitle);
NS_IMETHOD SetIcon(const nsAString& aIconSpec); NS_IMETHOD SetIcon(const nsAString& aIconSpec);

View File

@ -25,6 +25,24 @@ interface nsIAppShell : nsISupports
*/ */
void exit(); 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 * Suspends the use of additional platform-specific methods (besides the
* nsIAppShell->run() event loop) to run Gecko events on the main * nsIAppShell->run() event loop) to run Gecko events on the main

View File

@ -100,8 +100,8 @@ typedef void* nsNativeWidget;
#endif #endif
#define NS_IWIDGET_IID \ #define NS_IWIDGET_IID \
{ 0x7a4ece50, 0x5c52, 0x47c2, \ { 0x67da44c4, 0xe21b, 0x4742, \
{ 0x8c, 0x9e, 0x32, 0xd2, 0x5a, 0x27, 0x53, 0x34 } } { 0x9c, 0x2b, 0x26, 0xc7, 0x70, 0x21, 0xde, 0x87 } }
/* /*
* Window shadow styles * Window shadow styles
@ -1177,11 +1177,6 @@ class nsIWidget : public nsISupports {
*/ */
NS_IMETHOD Invalidate(const nsIntRect & aRect) = 0; NS_IMETHOD Invalidate(const nsIntRect & aRect) = 0;
/**
* Widget implementation may support synchronous painting.
*/
virtual void Update() { }
enum LayerManagerPersistence enum LayerManagerPersistence
{ {
LAYER_MANAGER_CURRENT = 0, LAYER_MANAGER_CURRENT = 0,

View File

@ -2775,14 +2775,6 @@ NS_METHOD nsWindow::Invalidate(const nsIntRect & aRect)
return NS_OK; return NS_OK;
} }
void
nsWindow::Update()
{
if (!ShouldUseOffMainThreadCompositing() && mWnd) {
::UpdateWindow(mWnd);
}
}
NS_IMETHODIMP NS_IMETHODIMP
nsWindow::MakeFullScreen(bool aFullScreen) nsWindow::MakeFullScreen(bool aFullScreen)
{ {

View File

@ -137,7 +137,6 @@ public:
bool aUpdateNCArea = false, bool aUpdateNCArea = false,
bool aIncludeChildren = false); bool aIncludeChildren = false);
NS_IMETHOD Invalidate(const nsIntRect & aRect); NS_IMETHOD Invalidate(const nsIntRect & aRect);
virtual void Update() MOZ_OVERRIDE;
virtual void* GetNativeData(uint32_t aDataType); virtual void* GetNativeData(uint32_t aDataType);
virtual void FreeNativeData(void * data, uint32_t aDataType); virtual void FreeNativeData(void * data, uint32_t aDataType);
NS_IMETHOD SetTitle(const nsAString& aTitle); NS_IMETHOD SetTitle(const nsAString& aTitle);

View File

@ -1220,14 +1220,6 @@ MetroWidget::Invalidate(const nsIntRect & aRect)
return NS_OK; return NS_OK;
} }
void
MetroWidget::Update()
{
if (!ShouldUseOffMainThreadCompositing() && mWnd) {
::UpdateWindow(mWnd);
}
}
nsTransparencyMode nsTransparencyMode
MetroWidget::GetTransparencyMode() MetroWidget::GetTransparencyMode()
{ {

View File

@ -109,7 +109,6 @@ public:
bool aUpdateNCArea = false, bool aUpdateNCArea = false,
bool aIncludeChildren = false); bool aIncludeChildren = false);
NS_IMETHOD Invalidate(const nsIntRect & aRect); NS_IMETHOD Invalidate(const nsIntRect & aRect);
virtual void Update() MOZ_OVERRIDE;
NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent, NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent,
nsEventStatus& aStatus); nsEventStatus& aStatus);
NS_IMETHOD ConstrainPosition(bool aAllowSlop, int32_t *aX, int32_t *aY); NS_IMETHOD ConstrainPosition(bool aAllowSlop, int32_t *aX, int32_t *aY);

View File

@ -22,7 +22,11 @@ nsBaseAppShell::nsBaseAppShell()
: mSuspendNativeCount(0) : mSuspendNativeCount(0)
, mEventloopNestingLevel(0) , mEventloopNestingLevel(0)
, mBlockedWait(nullptr) , mBlockedWait(nullptr)
, mFavorPerf(0)
, mNativeEventPending(0) , mNativeEventPending(0)
, mStarvationDelay(0)
, mSwitchTime(0)
, mLastNativeEventTime(0)
, mEventloopNestingState(eEventloopNone) , mEventloopNestingState(eEventloopNone)
, mRunning(false) , mRunning(false)
, mExiting(false) , mExiting(false)
@ -172,6 +176,20 @@ nsBaseAppShell::Exit(void)
return NS_OK; 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 NS_IMETHODIMP
nsBaseAppShell::SuspendNative() nsBaseAppShell::SuspendNative()
{ {
@ -232,6 +250,9 @@ nsBaseAppShell::OnProcessNextEvent(nsIThreadInternal *thr, bool mayWait,
OnDispatchedEvent(thr); // in case we blocked it earlier OnDispatchedEvent(thr); // in case we blocked it earlier
} }
PRIntervalTime start = PR_IntervalNow();
PRIntervalTime limit = THREAD_EVENT_STARVATION_LIMIT;
// Unblock outer nested wait loop (below). // Unblock outer nested wait loop (below).
if (mBlockedWait) if (mBlockedWait)
*mBlockedWait = false; *mBlockedWait = false;
@ -247,7 +268,21 @@ nsBaseAppShell::OnProcessNextEvent(nsIThreadInternal *thr, bool mayWait,
// NativeEventCallback to process gecko events. // NativeEventCallback to process gecko events.
mProcessedGeckoEvents = false; 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) { while (!NS_HasPendingEvents(thr) && !mProcessedGeckoEvents) {
// If we have been asked to exit from Run, then we should not wait for // 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) if (mExiting)
mayWait = false; mayWait = false;
mLastNativeEventTime = PR_IntervalNow();
if (!DoProcessNextNativeEvent(mayWait, recursionDepth) || !mayWait) if (!DoProcessNextNativeEvent(mayWait, recursionDepth) || !mayWait)
break; break;
} }

View File

@ -119,7 +119,11 @@ private:
* have been consumed by the inner event loop(s). * have been consumed by the inner event loop(s).
*/ */
bool *mBlockedWait; bool *mBlockedWait;
int32_t mFavorPerf;
mozilla::Atomic<uint32_t> mNativeEventPending; mozilla::Atomic<uint32_t> mNativeEventPending;
PRIntervalTime mStarvationDelay;
PRIntervalTime mSwitchTime;
PRIntervalTime mLastNativeEventTime;
enum EventloopNestingState { enum EventloopNestingState {
eEventloopNone, // top level thread execution eEventloopNone, // top level thread execution
eEventloopXPCOM, // innermost native event loop is ProcessNextNativeEvent eEventloopXPCOM, // innermost native event loop is ProcessNextNativeEvent