Bug 519590. Don't interrupt reflow until some time has passed. r=roc

This commit is contained in:
Boris Zbarsky 2009-10-02 14:05:32 -04:00
Родитель e1ef46ba15
Коммит 628a6ad230
4 изменённых файлов: 58 добавлений и 9 удалений

Просмотреть файл

@ -4375,10 +4375,14 @@ nsDocShell::GetPositionAndSize(PRInt32 * x, PRInt32 * y, PRInt32 * cx,
{
// We should really consider just getting this information from
// our window instead of duplicating the storage and code...
nsCOMPtr<nsIDOMDocument> document(do_GetInterface(GetAsSupports(mParent)));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(document));
if (doc) {
doc->FlushPendingNotifications(Flush_Layout);
if (cx || cy) {
// Caller wants to know our size; make sure to give them up to
// date information.
nsCOMPtr<nsIDOMDocument> document(do_GetInterface(GetAsSupports(mParent)));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(document));
if (doc) {
doc->FlushPendingNotifications(Flush_Layout);
}
}
DoGetPositionAndSize(x, y, cx, cy);

Просмотреть файл

@ -112,6 +112,9 @@
//needed for resetting of image service color
#include "nsLayoutCID.h"
using mozilla::TimeDuration;
using mozilla::TimeStamp;
static nscolor
MakeColorPref(const char *colstr)
{
@ -2062,18 +2065,33 @@ nsPresContext::HasCachedStyleData()
return mShell && mShell->StyleSet()->HasCachedStyleData();
}
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
static PRBool sGotInterruptEnv = PR_FALSE;
static PRUint32 sInterruptSeed = 1;
static PRUint32 sInterruptChecksToSkip = 200;
enum InterruptMode {
ModeRandom,
ModeCounter,
ModeEvent
};
// Controlled by the GECKO_REFLOW_INTERRUPT_MODE env var; allowed values are
// "random" (except on Windows) or "counter". If neither is used, the mode is
// ModeEvent.
static InterruptMode sInterruptMode = ModeEvent;
static PRUint32 sInterruptCounter;
// Used for the "random" mode. Controlled by the GECKO_REFLOW_INTERRUPT_SEED
// env var.
static PRUint32 sInterruptSeed = 1;
// Used for the "counter" mode. This is the number of unskipped interrupt
// checks that have to happen before we interrupt. Controlled by the
// GECKO_REFLOW_INTERRUPT_FREQUENCY env var.
static PRUint32 sInterruptMaxCounter = 10;
// Used for the "counter" mode. This counts up to sInterruptMaxCounter and is
// then reset to 0.
static PRUint32 sInterruptCounter;
// Number of interrupt checks to skip before really trying to interrupt.
// Controlled by the GECKO_REFLOW_INTERRUPT_CHECKS_TO_SKIP env var.
static PRUint32 sInterruptChecksToSkip = 200;
// Number of milliseconds that a reflow should be allowed to run for before we
// actually allow interruption. Controlled by the
// GECKO_REFLOW_MIN_NOINTERRUPT_DURATION env var.
static TimeDuration sInterruptTimeout = TimeDuration::FromMilliseconds(100);
static void GetInterruptEnv()
{
@ -2102,6 +2120,11 @@ static void GetInterruptEnv()
if (ev) {
sInterruptChecksToSkip = atoi(ev);
}
ev = PR_GetEnv("GECKO_REFLOW_MIN_NOINTERRUPT_DURATION");
if (ev) {
sInterruptTimeout = TimeDuration::FromMilliseconds(atoi(ev));
}
}
PRBool
@ -2136,6 +2159,11 @@ nsPresContext::HavePendingInputEvent()
void
nsPresContext::ReflowStarted(PRBool aInterruptible)
{
#ifdef NOISY_INTERRUPTIBLE_REFLOW
if (!aInterruptible) {
printf("STARTING NONINTERRUPTIBLE REFLOW\n");
}
#endif
// We don't support interrupting in paginated contexts, since page
// sequences only handle initial reflow
mInterruptsEnabled = aInterruptible && !IsPaginated();
@ -2149,6 +2177,10 @@ nsPresContext::ReflowStarted(PRBool aInterruptible)
mHasPendingInterrupt = PR_FALSE;
mInterruptChecksToSkip = sInterruptChecksToSkip;
if (mInterruptsEnabled) {
mReflowStartTime = TimeStamp::Now();
}
}
PRBool
@ -2174,7 +2206,12 @@ nsPresContext::CheckForInterrupt(nsIFrame* aFrame)
}
mInterruptChecksToSkip = sInterruptChecksToSkip;
mHasPendingInterrupt = HavePendingInputEvent();
// Don't interrupt if it's been less than sInterruptTimeout since we started
// the reflow.
mHasPendingInterrupt =
TimeStamp::Now() - mReflowStartTime > sInterruptTimeout &&
HavePendingInputEvent() &&
!IsChrome();
if (mHasPendingInterrupt) {
#ifdef NOISY_INTERRUPTIBLE_REFLOW
printf("*** DETECTED pending interrupt (time=%lld)\n", PR_Now());

Просмотреть файл

@ -71,6 +71,7 @@
#include "nsThreadUtils.h"
#include "nsContentUtils.h"
#include "nsIWidget.h"
#include "mozilla/TimeStamp.h"
class nsImageLoader;
#ifdef IBMBIDI
@ -1015,6 +1016,8 @@ protected:
PRUint32 mInterruptChecksToSkip;
mozilla::TimeStamp mReflowStartTime;
unsigned mHasPendingInterrupt : 1;
unsigned mInterruptsEnabled : 1;
unsigned mUseDocumentFonts : 1;

Просмотреть файл

@ -7229,6 +7229,11 @@ PresShell::PostReflowEventOffTimer()
PRBool
PresShell::DoReflow(nsIFrame* target, PRBool aInterruptible)
{
if (mReflowContinueTimer) {
mReflowContinueTimer->Cancel();
mReflowContinueTimer = nsnull;
}
nsIFrame* rootFrame = FrameManager()->GetRootFrame();
nsCOMPtr<nsIRenderingContext> rcx;