diff --git a/config/config.mak b/config/config.mak index 9484f71724a..68560fd38c5 100644 --- a/config/config.mak +++ b/config/config.mak @@ -263,6 +263,10 @@ CFLAGS=$(CFLAGS) -DMOZ_MATHML CFLAGS=$(CFLAGS) -DMOZ_SVG !endif +!ifdef MOZ_REFLOW_PERF +CFLAGS=$(CFLAGS) -DMOZ_REFLOW_PERF +!endif + #//----------------------------------------------------------------------- #// diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index b117977d20c..2d380e2a4bd 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -85,7 +85,6 @@ typedef enum SelectionRegion{SELECTION_ANCHOR_REGION = 0, #define VERIFY_REFLOW_INCLUDE_SPACE_MANAGER 0x40 #define VERIFY_REFLOW_DURING_RESIZE_REFLOW 0x80 - /** * Presentation shell interface. Presentation shells are the * controlling point for managing the presentation of a document. The @@ -435,6 +434,12 @@ public: * Get the flags associated with the VerifyReflow debug tool */ static NS_LAYOUT PRInt32 GetVerifyReflowFlags(); + + +#ifdef MOZ_REFLOW_PERF + NS_IMETHOD CountReflows(const char * aName, PRUint32 aType) = 0; +#endif + }; /** diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 5bdc56b68df..82c8a5beabb 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -1060,3 +1060,14 @@ nsPresContext::SetDefaultDirection(PRUint8 aDirection) mDefaultDirection = aDirection; return NS_OK; } + +#ifdef MOZ_REFLOW_PERF +NS_IMETHODIMP +nsPresContext::CountReflows(const char * aName, PRUint32 aType) +{ + if (mShell) { + mShell->CountReflows(aName, aType); + } + return NS_OK; +} +#endif diff --git a/layout/base/nsPresContext.h b/layout/base/nsPresContext.h index 908b4f591e4..934f40a1072 100644 --- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -312,6 +312,10 @@ public: NS_IMETHOD GetEventStateManager(nsIEventStateManager** aManager) = 0; NS_IMETHOD GetDefaultDirection(PRUint8* aDirection) = 0; NS_IMETHOD SetDefaultDirection(PRUint8 aDirection) = 0; + +#ifdef MOZ_REFLOW_PERF + NS_IMETHOD CountReflows(const char * aName, PRUint32 aType) = 0; +#endif }; // Bit values for StartLoadImage's aImageStatus @@ -334,4 +338,12 @@ extern NS_LAYOUT nsresult extern NS_LAYOUT nsresult NS_NewPrintContext(nsIPresContext** aInstancePtrResult); + +#ifdef MOZ_REFLOW_PERF +#define DO_GLOBAL_REFLOW_COUNT(_name, _type) \ + aPresContext->CountReflows((_name), (_type)); +#else +#define DO_GLOBAL_REFLOW_COUNT(_name, _type) +#endif // MOZ_REFLOW_PERF + #endif /* nsIPresContext_h___ */ diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 99c420660a7..6362642b858 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -136,6 +136,76 @@ static NS_DEFINE_CID(kCXIFConverterCID, NS_XIFFORMATCONVERTER_CID); #undef NOISY +//======================================================================== +#ifdef MOZ_REFLOW_PERF +class ReflowCountMgr; + +static const char * kGrandTotalsStr = "Grand Totals"; +#define NUM_REFLOW_TYPES 5 + +// Counting Class +class ReflowCounter { +public: + ReflowCounter(ReflowCountMgr * aMgr); + ~ReflowCounter(); + + void ClearTotals(); + void DisplayTotals(const char * aStr); + void DisplayHTMLTotals(const char * aStr); + + void Add(nsReflowReason aType) { mTotals[aType]++; mTotal++; } + void Add(nsReflowReason aType, PRUint32 aTotal) { mTotals[aType] += aTotal; mTotal += aTotal; } + +protected: + void DisplayTotals(PRUint32 * aArray, const char * aTitle); + void DisplayHTMLTotals(PRUint32 * aArray, const char * aTitle); + + PRUint32 mTotals[NUM_REFLOW_TYPES]; + PRUint32 mTotal; + ReflowCountMgr * mMgr; +}; + +// Manager Class +class ReflowCountMgr { +public: + ReflowCountMgr(); + //static ReflowCountMgr * GetInstance() { return &gReflowCountMgr; } + + ~ReflowCountMgr(); + + void ClearTotals(); + void DisplayTotals(const char * aStr); + void DisplayHTMLTotals(const char * aStr); + + void Add(const char * aName, nsReflowReason aType); + ReflowCounter * LookUp(const char * aName); + + FILE * GetOutFile() { return mFD; } + +protected: + void DisplayTotals(PRUint32 * aArray, PRUint32 * aDupArray, char * aTitle); + void DisplayHTMLTotals(PRUint32 * aArray, PRUint32 * aDupArray, char * aTitle); + + static PRIntn RemoveItems(PLHashEntry *he, PRIntn i, void *arg); + void CleanUp(); + + // stdout Output Methods + static PRIntn DoSingleTotal(PLHashEntry *he, PRIntn i, void *arg); + void DoGrandTotals(); + + // HTML Output Methods + static PRIntn DoSingleHTMLTotal(PLHashEntry *he, PRIntn i, void *arg); + void DoGrandHTMLTotals(); + + PLHashTable * mCounts; + FILE * mFD; + + // ReflowCountMgr gReflowCountMgr; +}; +#endif +//======================================================================== + + // comment out to hide caret #define SHOW_CARET @@ -632,6 +702,10 @@ public: nsIStyleRule* aStyleRule); NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument); +#ifdef MOZ_REFLOW_PERF + NS_IMETHOD CountReflows(const char * aName, PRUint32 aType); +#endif + protected: virtual ~PresShell(); @@ -696,6 +770,10 @@ protected: MOZ_TIMER_DECLARE(mReflowWatch) // Used for measuring time spent in reflow MOZ_TIMER_DECLARE(mFrameCreationWatch) // Used for measuring time spent in frame creation +#ifdef MOZ_REFLOW_PERF + ReflowCountMgr * mReflowCountMgr; +#endif + private: void FreeDynamicStack(); @@ -820,6 +898,10 @@ PresShell::PresShell():mStackArena(nsnull) mPendingReflowEvent = PR_FALSE; mBatchReflows = PR_FALSE; mSubShellMap = nsnull; + +#ifdef MOZ_REFLOW_PERF + mReflowCountMgr = new ReflowCountMgr(); +#endif } NS_IMPL_ADDREF(PresShell) @@ -867,6 +949,23 @@ PresShell::QueryInterface(const nsIID& aIID, void** aInstancePtr) PresShell::~PresShell() { +#ifdef MOZ_REFLOW_PERF + char * uriStr = nsnull; + if (mDocument) { + nsIURI * uri = mDocument->GetDocumentURL(); + if (uri) { + uri->GetPath(&uriStr); + NS_RELEASE(uri); + } + } + mReflowCountMgr->DisplayTotals(uriStr); + mReflowCountMgr->DisplayHTMLTotals(uriStr); + + delete mReflowCountMgr; + mReflowCountMgr = nsnull; + if (uriStr) delete [] uriStr; +#endif + // if we allocated any stack memory free it. FreeDynamicStack(); @@ -917,6 +1016,7 @@ PresShell::~PresShell() mPendingReflowEvent = PR_FALSE; mEventQueue->RevokeEvents(this); } + } /** @@ -4160,3 +4260,282 @@ nsresult CtlStyleWatch(PRUint32 aCtlValue, nsIStyleSet *aStyleSet) return rv; } + +//------------------------------------------------------------- +//-- Reflow counts +//------------------------------------------------------------- +#ifdef MOZ_REFLOW_PERF +//------------------------------------------------------------- +NS_IMETHODIMP +PresShell::CountReflows(const char * aName, PRUint32 aType) +{ + if (mReflowCountMgr) { + mReflowCountMgr->Add(aName, (nsReflowReason)aType); + } + return NS_OK; +} + +//------------------------------------------------------------------ +//-- Reflow Counter Classes Impls +//------------------------------------------------------------------ +//ReflowCountMgr ReflowCountMgr::gReflowCountMgr; + +//------------------------------------------------------------------ +ReflowCounter::ReflowCounter(ReflowCountMgr * aMgr) : + mMgr(aMgr) +{ + ClearTotals(); +} + +//------------------------------------------------------------------ +ReflowCounter::~ReflowCounter() +{ + //DisplayTotals(mTotals, "Grand Totals"); +} + +//------------------------------------------------------------------ +void ReflowCounter::ClearTotals() +{ + mTotal = 0; + for (PRUint32 i=0;iLookUp(kGrandTotalsStr); + + printf("%25s\t", aTitle); + PRUint32 i; + for (i=0;i 0) { + gTots->Add((nsReflowReason)i, aArray[i]); + //ReflowCountMgr * staticMgr = ReflowCountMgr::GetInstance(); + //if (staticMgr != mMgr) { + // staticMgr->Add(aTitle, (nsReflowReason)aArray[i]); + //} + } + } + printf("%d\n", mTotal); +} + +//------------------------------------------------------------------ +void ReflowCounter::DisplayHTMLTotals(PRUint32 * aArray, const char * aTitle) +{ + if (mTotal == 0) { + return; + } + ReflowCounter * gTots = (ReflowCounter *)mMgr->LookUp(kGrandTotalsStr); + FILE * fd = mMgr->GetOutFile(); + if (!fd) { + return; + } + PRUint32 i; + + fprintf(fd, "
%s
", aTitle); + for (i=0;i
"); + if (aArray[i]) { + fprintf(fd, "%d", aArray[i]); + } else { + fprintf(fd, " "); + } + fprintf(fd, "
"); + if (gTots != this && aArray[i] > 0) { + gTots->Add((nsReflowReason)i, aArray[i]); + } + } + fprintf(fd, "
%d
\n", mTotal); +} + +//------------------------------------------------------------------ +ReflowCountMgr::ReflowCountMgr() +{ + mCounts = PL_NewHashTable(10, PL_HashString, PL_CompareStrings, + PL_CompareValues, nsnull, nsnull); +} + +//------------------------------------------------------------------ +ReflowCountMgr::~ReflowCountMgr() +{ + //if (GetInstance() == this) { + // DoGrandTotals(); + //} + CleanUp(); +} + +//------------------------------------------------------------------ +ReflowCounter * ReflowCountMgr::LookUp(const char * aName) +{ + if (nsnull != mCounts) { + ReflowCounter * counter = (ReflowCounter *)PL_HashTableLookup(mCounts, aName); + return counter; + } + return nsnull; + +} + +//------------------------------------------------------------------ +void ReflowCountMgr::Add(const char * aName, nsReflowReason aType) +{ + if (nsnull != mCounts) { + ReflowCounter * counter = (ReflowCounter *)PL_HashTableLookup(mCounts, aName); + if (counter == nsnull) { + counter = new ReflowCounter(this); + NS_ASSERTION(counter != nsnull, "null ptr"); + char * name = nsCRT::strdup(aName); + NS_ASSERTION(name != nsnull, "null ptr"); + PL_HashTableAdd(mCounts, name, counter); + } + counter->Add(aType); + } +} + +//------------------------------------------------------------------ +PRIntn ReflowCountMgr::RemoveItems(PLHashEntry *he, PRIntn i, void *arg) +{ + char *str = (char *)he->key; + ReflowCounter * counter = (ReflowCounter *)he->value; + delete counter; + delete [] str; + + return HT_ENUMERATE_REMOVE; +} + +//------------------------------------------------------------------ +void ReflowCountMgr::CleanUp() +{ + if (nsnull != mCounts) { + PL_HashTableEnumerateEntries(mCounts, RemoveItems, nsnull); + PL_HashTableDestroy(mCounts); + mCounts = nsnull; + } +} + +//------------------------------------------------------------------ +PRIntn ReflowCountMgr::DoSingleTotal(PLHashEntry *he, PRIntn i, void *arg) +{ + char *str = (char *)he->key; + ReflowCounter * counter = (ReflowCounter *)he->value; + + counter->DisplayTotals(str); + + return HT_ENUMERATE_NEXT; +} + +//------------------------------------------------------------------ +void ReflowCountMgr::DoGrandTotals() +{ + if (nsnull != mCounts) { + ReflowCounter * gTots = (ReflowCounter *)PL_HashTableLookup(mCounts, kGrandTotalsStr); + if (gTots == nsnull) { + gTots = new ReflowCounter(this); + PL_HashTableAdd(mCounts, nsCRT::strdup(kGrandTotalsStr), gTots); + } else { + gTots->ClearTotals(); + } + + static const char * title[] = {"Init", "Incrm", "Resze", "Style", "Dirty", "Total"}; + printf("\t\t\t"); + PRUint32 i; + for (i=0;ikey; + ReflowCounter * counter = (ReflowCounter *)he->value; + + counter->DisplayHTMLTotals(str); + + return HT_ENUMERATE_NEXT; +} + +//------------------------------------------------------------------ +void ReflowCountMgr::DoGrandHTMLTotals() +{ + if (nsnull != mCounts) { + ReflowCounter * gTots = (ReflowCounter *)PL_HashTableLookup(mCounts, kGrandTotalsStr); + if (gTots == nsnull) { + gTots = new ReflowCounter(this); + PL_HashTableAdd(mCounts, nsCRT::strdup(kGrandTotalsStr), gTots); + } else { + gTots->ClearTotals(); + } + + static const char * title[] = {"Class", "Init", "Incrm", "Resze", "Style", "Dirty", "Total"}; + fprintf(mFD, ""); + PRUint32 i; + for (i=0;i
%s
", title[i]); + } + fprintf(mFD, "\n"); + PL_HashTableEnumerateEntries(mCounts, DoSingleHTMLTotal, this); + } +} + +//------------------------------------ +void ReflowCountMgr::DisplayTotals(const char * aStr) +{ + printf("%s\n", aStr?aStr:"No name"); + DoGrandTotals(); + +} +//------------------------------------ +void ReflowCountMgr::DisplayHTMLTotals(const char * aStr) +{ +#ifdef WIN32 // XXX NOT XP! + char name[1024]; + + char * sptr = strrchr(aStr, '/'); + if (sptr) { + sptr++; + strcpy(name, sptr); + char * eptr = strrchr(name, '.'); + if (eptr) { + *eptr = 0; + } + strcat(name, "_stats.html"); + } + mFD = fopen(name, "w"); + if (mFD) { + fprintf(mFD, "Reflow Stats\n"); + const char * title = aStr?aStr:"No name"; + fprintf(mFD, "
%s
", title); + DoGrandHTMLTotals(); + fprintf(mFD, "
\n"); + fprintf(mFD, "\n"); + fclose(mFD); + mFD = nsnull; + } +#endif // not XP! +} +#endif // MOZ_REFLOW_PERF diff --git a/layout/base/public/nsIPresContext.h b/layout/base/public/nsIPresContext.h index 908b4f591e4..934f40a1072 100644 --- a/layout/base/public/nsIPresContext.h +++ b/layout/base/public/nsIPresContext.h @@ -312,6 +312,10 @@ public: NS_IMETHOD GetEventStateManager(nsIEventStateManager** aManager) = 0; NS_IMETHOD GetDefaultDirection(PRUint8* aDirection) = 0; NS_IMETHOD SetDefaultDirection(PRUint8 aDirection) = 0; + +#ifdef MOZ_REFLOW_PERF + NS_IMETHOD CountReflows(const char * aName, PRUint32 aType) = 0; +#endif }; // Bit values for StartLoadImage's aImageStatus @@ -334,4 +338,12 @@ extern NS_LAYOUT nsresult extern NS_LAYOUT nsresult NS_NewPrintContext(nsIPresContext** aInstancePtrResult); + +#ifdef MOZ_REFLOW_PERF +#define DO_GLOBAL_REFLOW_COUNT(_name, _type) \ + aPresContext->CountReflows((_name), (_type)); +#else +#define DO_GLOBAL_REFLOW_COUNT(_name, _type) +#endif // MOZ_REFLOW_PERF + #endif /* nsIPresContext_h___ */ diff --git a/layout/base/public/nsIPresShell.h b/layout/base/public/nsIPresShell.h index b117977d20c..2d380e2a4bd 100644 --- a/layout/base/public/nsIPresShell.h +++ b/layout/base/public/nsIPresShell.h @@ -85,7 +85,6 @@ typedef enum SelectionRegion{SELECTION_ANCHOR_REGION = 0, #define VERIFY_REFLOW_INCLUDE_SPACE_MANAGER 0x40 #define VERIFY_REFLOW_DURING_RESIZE_REFLOW 0x80 - /** * Presentation shell interface. Presentation shells are the * controlling point for managing the presentation of a document. The @@ -435,6 +434,12 @@ public: * Get the flags associated with the VerifyReflow debug tool */ static NS_LAYOUT PRInt32 GetVerifyReflowFlags(); + + +#ifdef MOZ_REFLOW_PERF + NS_IMETHOD CountReflows(const char * aName, PRUint32 aType) = 0; +#endif + }; /** diff --git a/layout/base/public/nsPresContext.h b/layout/base/public/nsPresContext.h index 908b4f591e4..934f40a1072 100644 --- a/layout/base/public/nsPresContext.h +++ b/layout/base/public/nsPresContext.h @@ -312,6 +312,10 @@ public: NS_IMETHOD GetEventStateManager(nsIEventStateManager** aManager) = 0; NS_IMETHOD GetDefaultDirection(PRUint8* aDirection) = 0; NS_IMETHOD SetDefaultDirection(PRUint8 aDirection) = 0; + +#ifdef MOZ_REFLOW_PERF + NS_IMETHOD CountReflows(const char * aName, PRUint32 aType) = 0; +#endif }; // Bit values for StartLoadImage's aImageStatus @@ -334,4 +338,12 @@ extern NS_LAYOUT nsresult extern NS_LAYOUT nsresult NS_NewPrintContext(nsIPresContext** aInstancePtrResult); + +#ifdef MOZ_REFLOW_PERF +#define DO_GLOBAL_REFLOW_COUNT(_name, _type) \ + aPresContext->CountReflows((_name), (_type)); +#else +#define DO_GLOBAL_REFLOW_COUNT(_name, _type) +#endif // MOZ_REFLOW_PERF + #endif /* nsIPresContext_h___ */ diff --git a/layout/base/src/nsFrameImageLoader.cpp b/layout/base/src/nsFrameImageLoader.cpp index 684b04f63d1..885d3f6b782 100644 --- a/layout/base/src/nsFrameImageLoader.cpp +++ b/layout/base/src/nsFrameImageLoader.cpp @@ -474,6 +474,7 @@ nsFrameImageLoader::Notify(nsIImageRequest *aImageRequest, mImageLoadStatus |= NS_IMAGE_LOAD_STATUS_IMAGE_READY; DamageRepairFrames(nsnull); } + NotifyFrames(PR_FALSE); break; case nsImageNotification_kFrameComplete: diff --git a/layout/base/src/nsPresContext.cpp b/layout/base/src/nsPresContext.cpp index 5bdc56b68df..82c8a5beabb 100644 --- a/layout/base/src/nsPresContext.cpp +++ b/layout/base/src/nsPresContext.cpp @@ -1060,3 +1060,14 @@ nsPresContext::SetDefaultDirection(PRUint8 aDirection) mDefaultDirection = aDirection; return NS_OK; } + +#ifdef MOZ_REFLOW_PERF +NS_IMETHODIMP +nsPresContext::CountReflows(const char * aName, PRUint32 aType) +{ + if (mShell) { + mShell->CountReflows(aName, aType); + } + return NS_OK; +} +#endif diff --git a/layout/base/src/nsPresContext.h b/layout/base/src/nsPresContext.h index ffdb471986e..3d39df9e7c2 100644 --- a/layout/base/src/nsPresContext.h +++ b/layout/base/src/nsPresContext.h @@ -133,7 +133,9 @@ public: NS_IMETHOD GetEventStateManager(nsIEventStateManager** aManager); NS_IMETHOD GetDefaultDirection(PRUint8* aDirection); NS_IMETHOD SetDefaultDirection(PRUint8 aDirection); - +#ifdef MOZ_REFLOW_PERF + NS_IMETHOD CountReflows(const char * aName, PRUint32 aType); +#endif protected: nsPresContext(); virtual ~nsPresContext(); diff --git a/layout/generic/nsAbsoluteContainingBlock.cpp b/layout/generic/nsAbsoluteContainingBlock.cpp index 45f261040cf..db41a6e57d0 100644 --- a/layout/generic/nsAbsoluteContainingBlock.cpp +++ b/layout/generic/nsAbsoluteContainingBlock.cpp @@ -180,6 +180,7 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame, nscoord aContainingBlockHeight, nsRect& aChildBounds) { + DO_GLOBAL_REFLOW_COUNT("nsAbsoluteContainingBlock", aReflowState.reason); // Initialize OUT parameter aChildBounds.SetRect(0, 0, 0, 0); diff --git a/layout/generic/nsAreaFrame.cpp b/layout/generic/nsAreaFrame.cpp index 560b4406af7..4492e65f0f1 100644 --- a/layout/generic/nsAreaFrame.cpp +++ b/layout/generic/nsAreaFrame.cpp @@ -207,6 +207,7 @@ nsAreaFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsAreaFrame", aReflowState.reason); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("enter nsAreaFrame::Reflow: maxSize=%d,%d reason=%d", aReflowState.availableWidth, diff --git a/layout/generic/nsBRFrame.cpp b/layout/generic/nsBRFrame.cpp index 6cde1c1d12c..af65d51fef3 100644 --- a/layout/generic/nsBRFrame.cpp +++ b/layout/generic/nsBRFrame.cpp @@ -108,6 +108,7 @@ BRFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("BRFrame", aReflowState.reason); if (aMetrics.maxElementSize) { aMetrics.maxElementSize->width = 0; aMetrics.maxElementSize->height = 0; diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index c2ae755dc0d..dfca9ab439e 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -1420,6 +1420,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsBlockFrame", aReflowState.reason); #ifdef DEBUG if (gNoisyReflow) { IndentBy(stdout, gNoiseIndent); diff --git a/layout/generic/nsBlockReflowState.cpp b/layout/generic/nsBlockReflowState.cpp index c2ae755dc0d..dfca9ab439e 100644 --- a/layout/generic/nsBlockReflowState.cpp +++ b/layout/generic/nsBlockReflowState.cpp @@ -1420,6 +1420,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsBlockFrame", aReflowState.reason); #ifdef DEBUG if (gNoisyReflow) { IndentBy(stdout, gNoiseIndent); diff --git a/layout/generic/nsBlockReflowState.h b/layout/generic/nsBlockReflowState.h index c2ae755dc0d..dfca9ab439e 100644 --- a/layout/generic/nsBlockReflowState.h +++ b/layout/generic/nsBlockReflowState.h @@ -1420,6 +1420,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsBlockFrame", aReflowState.reason); #ifdef DEBUG if (gNoisyReflow) { IndentBy(stdout, gNoiseIndent); diff --git a/layout/generic/nsBulletFrame.cpp b/layout/generic/nsBulletFrame.cpp index 0aefde1e86f..56d2aff8615 100644 --- a/layout/generic/nsBulletFrame.cpp +++ b/layout/generic/nsBulletFrame.cpp @@ -1063,6 +1063,7 @@ nsBulletFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsBulletFrame", aReflowState.reason); if (eReflowReason_Incremental == aReflowState.reason) { nsIReflowCommand::ReflowType type; aReflowState.reflowCommand->GetType(type); diff --git a/layout/generic/nsFirstLetterFrame.cpp b/layout/generic/nsFirstLetterFrame.cpp index daf1cf4e7e8..db0e4c02682 100644 --- a/layout/generic/nsFirstLetterFrame.cpp +++ b/layout/generic/nsFirstLetterFrame.cpp @@ -214,6 +214,7 @@ nsFirstLetterFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aReflowStatus) { + DO_GLOBAL_REFLOW_COUNT("nsFirstLetterFrame", aReflowState.reason); nsresult rv = NS_OK; // Grab overflow list diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 9ed6a5961a1..80e42cd76cf 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1412,6 +1412,7 @@ nsFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsFrame", aReflowState.reason); aDesiredSize.width = 0; aDesiredSize.height = 0; aDesiredSize.ascent = 0; diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index a2b7d6d2b00..8613a226b0d 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -527,6 +527,7 @@ nsGfxScrollFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsGfxScrollFrame", aReflowState.reason); nsresult rv = nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); /* diff --git a/layout/generic/nsHTMLFrame.cpp b/layout/generic/nsHTMLFrame.cpp index d16b29f0532..5233574ed72 100644 --- a/layout/generic/nsHTMLFrame.cpp +++ b/layout/generic/nsHTMLFrame.cpp @@ -222,6 +222,7 @@ CanvasFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("CanvasFrame", aReflowState.reason); NS_FRAME_TRACE_REFLOW_IN("CanvasFrame::Reflow"); NS_PRECONDITION(nsnull == aDesiredSize.maxElementSize, "unexpected request"); diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 45351862f58..85ee628c48d 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -319,6 +319,7 @@ nsImageFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsImageFrame", aReflowState.reason); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("enter nsImageFrame::Reflow: aMaxSize=%d,%d", aReflowState.availableWidth, aReflowState.availableHeight)); diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index 79614a0d7e3..cbf5b9d3895 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -219,6 +219,7 @@ nsInlineFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsInlineFrame", aReflowState.reason); if (nsnull == aReflowState.mLineLayout) { return NS_ERROR_INVALID_ARG; } diff --git a/layout/generic/nsLeafFrame.cpp b/layout/generic/nsLeafFrame.cpp index 7d3944a73fd..e6b21197498 100644 --- a/layout/generic/nsLeafFrame.cpp +++ b/layout/generic/nsLeafFrame.cpp @@ -67,6 +67,7 @@ nsLeafFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsLeafFrame", aReflowState.reason); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("enter nsLeafFrame::Reflow: aMaxSize=%d,%d", aReflowState.availableWidth, aReflowState.availableHeight)); diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index 5a728aa58cb..f03aa601d13 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -510,6 +510,7 @@ nsObjectFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsObjectFrame", aReflowState.reason); nsresult rv = NS_OK; char* mimeType = nsnull; PRUint32 buflen; diff --git a/layout/generic/nsPageFrame.cpp b/layout/generic/nsPageFrame.cpp index 39f58d4cd51..22f87955a3f 100644 --- a/layout/generic/nsPageFrame.cpp +++ b/layout/generic/nsPageFrame.cpp @@ -56,6 +56,7 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsPageFrame", aReflowState.reason); aStatus = NS_FRAME_COMPLETE; // initialize out parameter if (eReflowReason_Incremental == aReflowState.reason) { diff --git a/layout/generic/nsPlaceholderFrame.cpp b/layout/generic/nsPlaceholderFrame.cpp index 1be5fe1d162..e3be5a1fad4 100644 --- a/layout/generic/nsPlaceholderFrame.cpp +++ b/layout/generic/nsPlaceholderFrame.cpp @@ -49,6 +49,7 @@ nsPlaceholderFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsPlaceholderFrame", aReflowState.reason); aDesiredSize.width = 0; aDesiredSize.height = 0; aDesiredSize.ascent = 0; diff --git a/layout/generic/nsSimplePageSequence.cpp b/layout/generic/nsSimplePageSequence.cpp index 6f164b9e13c..e6d9bbfc664 100644 --- a/layout/generic/nsSimplePageSequence.cpp +++ b/layout/generic/nsSimplePageSequence.cpp @@ -206,6 +206,7 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsSimplePageSequenceFrame", aReflowState.reason); NS_FRAME_TRACE_REFLOW_IN("nsSimplePageSequenceFrame::Reflow"); aStatus = NS_FRAME_COMPLETE; // we're always complete diff --git a/layout/generic/nsSpacerFrame.cpp b/layout/generic/nsSpacerFrame.cpp index 05f64a7b885..f29dac908b9 100644 --- a/layout/generic/nsSpacerFrame.cpp +++ b/layout/generic/nsSpacerFrame.cpp @@ -82,6 +82,7 @@ SpacerFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("SpacerFrame", aReflowState.reason); aStatus = NS_FRAME_COMPLETE; // By default, we have no area diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index a536703fd6e..5c15d80e62c 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -4054,6 +4054,7 @@ nsTextFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsTextFrame", aReflowState.reason); #ifdef NOISY_REFLOW ListTag(stdout); printf(": BeginReflow: availableSize=%d,%d\n", diff --git a/layout/generic/nsViewportFrame.cpp b/layout/generic/nsViewportFrame.cpp index 9acbe204605..9ba9aa28396 100644 --- a/layout/generic/nsViewportFrame.cpp +++ b/layout/generic/nsViewportFrame.cpp @@ -482,6 +482,7 @@ ViewportFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("ViewportFrame", aReflowState.reason); NS_FRAME_TRACE_REFLOW_IN("ViewportFrame::Reflow"); NS_PRECONDITION(nsnull == aDesiredSize.maxElementSize, "unexpected request"); diff --git a/layout/html/base/src/nsAbsoluteContainingBlock.cpp b/layout/html/base/src/nsAbsoluteContainingBlock.cpp index 45f261040cf..db41a6e57d0 100644 --- a/layout/html/base/src/nsAbsoluteContainingBlock.cpp +++ b/layout/html/base/src/nsAbsoluteContainingBlock.cpp @@ -180,6 +180,7 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame, nscoord aContainingBlockHeight, nsRect& aChildBounds) { + DO_GLOBAL_REFLOW_COUNT("nsAbsoluteContainingBlock", aReflowState.reason); // Initialize OUT parameter aChildBounds.SetRect(0, 0, 0, 0); diff --git a/layout/html/base/src/nsAreaFrame.cpp b/layout/html/base/src/nsAreaFrame.cpp index 560b4406af7..4492e65f0f1 100644 --- a/layout/html/base/src/nsAreaFrame.cpp +++ b/layout/html/base/src/nsAreaFrame.cpp @@ -207,6 +207,7 @@ nsAreaFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsAreaFrame", aReflowState.reason); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("enter nsAreaFrame::Reflow: maxSize=%d,%d reason=%d", aReflowState.availableWidth, diff --git a/layout/html/base/src/nsBRFrame.cpp b/layout/html/base/src/nsBRFrame.cpp index 6cde1c1d12c..af65d51fef3 100644 --- a/layout/html/base/src/nsBRFrame.cpp +++ b/layout/html/base/src/nsBRFrame.cpp @@ -108,6 +108,7 @@ BRFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("BRFrame", aReflowState.reason); if (aMetrics.maxElementSize) { aMetrics.maxElementSize->width = 0; aMetrics.maxElementSize->height = 0; diff --git a/layout/html/base/src/nsBlockFrame.cpp b/layout/html/base/src/nsBlockFrame.cpp index c2ae755dc0d..dfca9ab439e 100644 --- a/layout/html/base/src/nsBlockFrame.cpp +++ b/layout/html/base/src/nsBlockFrame.cpp @@ -1420,6 +1420,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsBlockFrame", aReflowState.reason); #ifdef DEBUG if (gNoisyReflow) { IndentBy(stdout, gNoiseIndent); diff --git a/layout/html/base/src/nsBlockReflowState.cpp b/layout/html/base/src/nsBlockReflowState.cpp index c2ae755dc0d..dfca9ab439e 100644 --- a/layout/html/base/src/nsBlockReflowState.cpp +++ b/layout/html/base/src/nsBlockReflowState.cpp @@ -1420,6 +1420,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsBlockFrame", aReflowState.reason); #ifdef DEBUG if (gNoisyReflow) { IndentBy(stdout, gNoiseIndent); diff --git a/layout/html/base/src/nsBlockReflowState.h b/layout/html/base/src/nsBlockReflowState.h index c2ae755dc0d..dfca9ab439e 100644 --- a/layout/html/base/src/nsBlockReflowState.h +++ b/layout/html/base/src/nsBlockReflowState.h @@ -1420,6 +1420,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsBlockFrame", aReflowState.reason); #ifdef DEBUG if (gNoisyReflow) { IndentBy(stdout, gNoiseIndent); diff --git a/layout/html/base/src/nsBulletFrame.cpp b/layout/html/base/src/nsBulletFrame.cpp index 0aefde1e86f..56d2aff8615 100644 --- a/layout/html/base/src/nsBulletFrame.cpp +++ b/layout/html/base/src/nsBulletFrame.cpp @@ -1063,6 +1063,7 @@ nsBulletFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsBulletFrame", aReflowState.reason); if (eReflowReason_Incremental == aReflowState.reason) { nsIReflowCommand::ReflowType type; aReflowState.reflowCommand->GetType(type); diff --git a/layout/html/base/src/nsFirstLetterFrame.cpp b/layout/html/base/src/nsFirstLetterFrame.cpp index daf1cf4e7e8..db0e4c02682 100644 --- a/layout/html/base/src/nsFirstLetterFrame.cpp +++ b/layout/html/base/src/nsFirstLetterFrame.cpp @@ -214,6 +214,7 @@ nsFirstLetterFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aReflowStatus) { + DO_GLOBAL_REFLOW_COUNT("nsFirstLetterFrame", aReflowState.reason); nsresult rv = NS_OK; // Grab overflow list diff --git a/layout/html/base/src/nsFrame.cpp b/layout/html/base/src/nsFrame.cpp index 9ed6a5961a1..80e42cd76cf 100644 --- a/layout/html/base/src/nsFrame.cpp +++ b/layout/html/base/src/nsFrame.cpp @@ -1412,6 +1412,7 @@ nsFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsFrame", aReflowState.reason); aDesiredSize.width = 0; aDesiredSize.height = 0; aDesiredSize.ascent = 0; diff --git a/layout/html/base/src/nsGfxScrollFrame.cpp b/layout/html/base/src/nsGfxScrollFrame.cpp index a2b7d6d2b00..8613a226b0d 100644 --- a/layout/html/base/src/nsGfxScrollFrame.cpp +++ b/layout/html/base/src/nsGfxScrollFrame.cpp @@ -527,6 +527,7 @@ nsGfxScrollFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsGfxScrollFrame", aReflowState.reason); nsresult rv = nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); /* diff --git a/layout/html/base/src/nsHRFrame.cpp b/layout/html/base/src/nsHRFrame.cpp index 54d3d3ad939..0fa5de6cad2 100644 --- a/layout/html/base/src/nsHRFrame.cpp +++ b/layout/html/base/src/nsHRFrame.cpp @@ -176,6 +176,7 @@ HRuleFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("HRuleFrame", aReflowState.reason); NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow"); // Compute the width diff --git a/layout/html/base/src/nsHTMLFrame.cpp b/layout/html/base/src/nsHTMLFrame.cpp index d16b29f0532..5233574ed72 100644 --- a/layout/html/base/src/nsHTMLFrame.cpp +++ b/layout/html/base/src/nsHTMLFrame.cpp @@ -222,6 +222,7 @@ CanvasFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("CanvasFrame", aReflowState.reason); NS_FRAME_TRACE_REFLOW_IN("CanvasFrame::Reflow"); NS_PRECONDITION(nsnull == aDesiredSize.maxElementSize, "unexpected request"); diff --git a/layout/html/base/src/nsImageFrame.cpp b/layout/html/base/src/nsImageFrame.cpp index 45351862f58..85ee628c48d 100644 --- a/layout/html/base/src/nsImageFrame.cpp +++ b/layout/html/base/src/nsImageFrame.cpp @@ -319,6 +319,7 @@ nsImageFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsImageFrame", aReflowState.reason); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("enter nsImageFrame::Reflow: aMaxSize=%d,%d", aReflowState.availableWidth, aReflowState.availableHeight)); diff --git a/layout/html/base/src/nsInlineFrame.cpp b/layout/html/base/src/nsInlineFrame.cpp index 79614a0d7e3..cbf5b9d3895 100644 --- a/layout/html/base/src/nsInlineFrame.cpp +++ b/layout/html/base/src/nsInlineFrame.cpp @@ -219,6 +219,7 @@ nsInlineFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsInlineFrame", aReflowState.reason); if (nsnull == aReflowState.mLineLayout) { return NS_ERROR_INVALID_ARG; } diff --git a/layout/html/base/src/nsLeafFrame.cpp b/layout/html/base/src/nsLeafFrame.cpp index 7d3944a73fd..e6b21197498 100644 --- a/layout/html/base/src/nsLeafFrame.cpp +++ b/layout/html/base/src/nsLeafFrame.cpp @@ -67,6 +67,7 @@ nsLeafFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsLeafFrame", aReflowState.reason); NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("enter nsLeafFrame::Reflow: aMaxSize=%d,%d", aReflowState.availableWidth, aReflowState.availableHeight)); diff --git a/layout/html/base/src/nsObjectFrame.cpp b/layout/html/base/src/nsObjectFrame.cpp index 5a728aa58cb..f03aa601d13 100644 --- a/layout/html/base/src/nsObjectFrame.cpp +++ b/layout/html/base/src/nsObjectFrame.cpp @@ -510,6 +510,7 @@ nsObjectFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsObjectFrame", aReflowState.reason); nsresult rv = NS_OK; char* mimeType = nsnull; PRUint32 buflen; diff --git a/layout/html/base/src/nsPageFrame.cpp b/layout/html/base/src/nsPageFrame.cpp index 39f58d4cd51..22f87955a3f 100644 --- a/layout/html/base/src/nsPageFrame.cpp +++ b/layout/html/base/src/nsPageFrame.cpp @@ -56,6 +56,7 @@ NS_METHOD nsPageFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsPageFrame", aReflowState.reason); aStatus = NS_FRAME_COMPLETE; // initialize out parameter if (eReflowReason_Incremental == aReflowState.reason) { diff --git a/layout/html/base/src/nsPlaceholderFrame.cpp b/layout/html/base/src/nsPlaceholderFrame.cpp index 1be5fe1d162..e3be5a1fad4 100644 --- a/layout/html/base/src/nsPlaceholderFrame.cpp +++ b/layout/html/base/src/nsPlaceholderFrame.cpp @@ -49,6 +49,7 @@ nsPlaceholderFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsPlaceholderFrame", aReflowState.reason); aDesiredSize.width = 0; aDesiredSize.height = 0; aDesiredSize.ascent = 0; diff --git a/layout/html/base/src/nsPresShell.cpp b/layout/html/base/src/nsPresShell.cpp index 99c420660a7..6362642b858 100644 --- a/layout/html/base/src/nsPresShell.cpp +++ b/layout/html/base/src/nsPresShell.cpp @@ -136,6 +136,76 @@ static NS_DEFINE_CID(kCXIFConverterCID, NS_XIFFORMATCONVERTER_CID); #undef NOISY +//======================================================================== +#ifdef MOZ_REFLOW_PERF +class ReflowCountMgr; + +static const char * kGrandTotalsStr = "Grand Totals"; +#define NUM_REFLOW_TYPES 5 + +// Counting Class +class ReflowCounter { +public: + ReflowCounter(ReflowCountMgr * aMgr); + ~ReflowCounter(); + + void ClearTotals(); + void DisplayTotals(const char * aStr); + void DisplayHTMLTotals(const char * aStr); + + void Add(nsReflowReason aType) { mTotals[aType]++; mTotal++; } + void Add(nsReflowReason aType, PRUint32 aTotal) { mTotals[aType] += aTotal; mTotal += aTotal; } + +protected: + void DisplayTotals(PRUint32 * aArray, const char * aTitle); + void DisplayHTMLTotals(PRUint32 * aArray, const char * aTitle); + + PRUint32 mTotals[NUM_REFLOW_TYPES]; + PRUint32 mTotal; + ReflowCountMgr * mMgr; +}; + +// Manager Class +class ReflowCountMgr { +public: + ReflowCountMgr(); + //static ReflowCountMgr * GetInstance() { return &gReflowCountMgr; } + + ~ReflowCountMgr(); + + void ClearTotals(); + void DisplayTotals(const char * aStr); + void DisplayHTMLTotals(const char * aStr); + + void Add(const char * aName, nsReflowReason aType); + ReflowCounter * LookUp(const char * aName); + + FILE * GetOutFile() { return mFD; } + +protected: + void DisplayTotals(PRUint32 * aArray, PRUint32 * aDupArray, char * aTitle); + void DisplayHTMLTotals(PRUint32 * aArray, PRUint32 * aDupArray, char * aTitle); + + static PRIntn RemoveItems(PLHashEntry *he, PRIntn i, void *arg); + void CleanUp(); + + // stdout Output Methods + static PRIntn DoSingleTotal(PLHashEntry *he, PRIntn i, void *arg); + void DoGrandTotals(); + + // HTML Output Methods + static PRIntn DoSingleHTMLTotal(PLHashEntry *he, PRIntn i, void *arg); + void DoGrandHTMLTotals(); + + PLHashTable * mCounts; + FILE * mFD; + + // ReflowCountMgr gReflowCountMgr; +}; +#endif +//======================================================================== + + // comment out to hide caret #define SHOW_CARET @@ -632,6 +702,10 @@ public: nsIStyleRule* aStyleRule); NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument); +#ifdef MOZ_REFLOW_PERF + NS_IMETHOD CountReflows(const char * aName, PRUint32 aType); +#endif + protected: virtual ~PresShell(); @@ -696,6 +770,10 @@ protected: MOZ_TIMER_DECLARE(mReflowWatch) // Used for measuring time spent in reflow MOZ_TIMER_DECLARE(mFrameCreationWatch) // Used for measuring time spent in frame creation +#ifdef MOZ_REFLOW_PERF + ReflowCountMgr * mReflowCountMgr; +#endif + private: void FreeDynamicStack(); @@ -820,6 +898,10 @@ PresShell::PresShell():mStackArena(nsnull) mPendingReflowEvent = PR_FALSE; mBatchReflows = PR_FALSE; mSubShellMap = nsnull; + +#ifdef MOZ_REFLOW_PERF + mReflowCountMgr = new ReflowCountMgr(); +#endif } NS_IMPL_ADDREF(PresShell) @@ -867,6 +949,23 @@ PresShell::QueryInterface(const nsIID& aIID, void** aInstancePtr) PresShell::~PresShell() { +#ifdef MOZ_REFLOW_PERF + char * uriStr = nsnull; + if (mDocument) { + nsIURI * uri = mDocument->GetDocumentURL(); + if (uri) { + uri->GetPath(&uriStr); + NS_RELEASE(uri); + } + } + mReflowCountMgr->DisplayTotals(uriStr); + mReflowCountMgr->DisplayHTMLTotals(uriStr); + + delete mReflowCountMgr; + mReflowCountMgr = nsnull; + if (uriStr) delete [] uriStr; +#endif + // if we allocated any stack memory free it. FreeDynamicStack(); @@ -917,6 +1016,7 @@ PresShell::~PresShell() mPendingReflowEvent = PR_FALSE; mEventQueue->RevokeEvents(this); } + } /** @@ -4160,3 +4260,282 @@ nsresult CtlStyleWatch(PRUint32 aCtlValue, nsIStyleSet *aStyleSet) return rv; } + +//------------------------------------------------------------- +//-- Reflow counts +//------------------------------------------------------------- +#ifdef MOZ_REFLOW_PERF +//------------------------------------------------------------- +NS_IMETHODIMP +PresShell::CountReflows(const char * aName, PRUint32 aType) +{ + if (mReflowCountMgr) { + mReflowCountMgr->Add(aName, (nsReflowReason)aType); + } + return NS_OK; +} + +//------------------------------------------------------------------ +//-- Reflow Counter Classes Impls +//------------------------------------------------------------------ +//ReflowCountMgr ReflowCountMgr::gReflowCountMgr; + +//------------------------------------------------------------------ +ReflowCounter::ReflowCounter(ReflowCountMgr * aMgr) : + mMgr(aMgr) +{ + ClearTotals(); +} + +//------------------------------------------------------------------ +ReflowCounter::~ReflowCounter() +{ + //DisplayTotals(mTotals, "Grand Totals"); +} + +//------------------------------------------------------------------ +void ReflowCounter::ClearTotals() +{ + mTotal = 0; + for (PRUint32 i=0;iLookUp(kGrandTotalsStr); + + printf("%25s\t", aTitle); + PRUint32 i; + for (i=0;i 0) { + gTots->Add((nsReflowReason)i, aArray[i]); + //ReflowCountMgr * staticMgr = ReflowCountMgr::GetInstance(); + //if (staticMgr != mMgr) { + // staticMgr->Add(aTitle, (nsReflowReason)aArray[i]); + //} + } + } + printf("%d\n", mTotal); +} + +//------------------------------------------------------------------ +void ReflowCounter::DisplayHTMLTotals(PRUint32 * aArray, const char * aTitle) +{ + if (mTotal == 0) { + return; + } + ReflowCounter * gTots = (ReflowCounter *)mMgr->LookUp(kGrandTotalsStr); + FILE * fd = mMgr->GetOutFile(); + if (!fd) { + return; + } + PRUint32 i; + + fprintf(fd, "
%s
", aTitle); + for (i=0;i
"); + if (aArray[i]) { + fprintf(fd, "%d", aArray[i]); + } else { + fprintf(fd, " "); + } + fprintf(fd, "
"); + if (gTots != this && aArray[i] > 0) { + gTots->Add((nsReflowReason)i, aArray[i]); + } + } + fprintf(fd, "
%d
\n", mTotal); +} + +//------------------------------------------------------------------ +ReflowCountMgr::ReflowCountMgr() +{ + mCounts = PL_NewHashTable(10, PL_HashString, PL_CompareStrings, + PL_CompareValues, nsnull, nsnull); +} + +//------------------------------------------------------------------ +ReflowCountMgr::~ReflowCountMgr() +{ + //if (GetInstance() == this) { + // DoGrandTotals(); + //} + CleanUp(); +} + +//------------------------------------------------------------------ +ReflowCounter * ReflowCountMgr::LookUp(const char * aName) +{ + if (nsnull != mCounts) { + ReflowCounter * counter = (ReflowCounter *)PL_HashTableLookup(mCounts, aName); + return counter; + } + return nsnull; + +} + +//------------------------------------------------------------------ +void ReflowCountMgr::Add(const char * aName, nsReflowReason aType) +{ + if (nsnull != mCounts) { + ReflowCounter * counter = (ReflowCounter *)PL_HashTableLookup(mCounts, aName); + if (counter == nsnull) { + counter = new ReflowCounter(this); + NS_ASSERTION(counter != nsnull, "null ptr"); + char * name = nsCRT::strdup(aName); + NS_ASSERTION(name != nsnull, "null ptr"); + PL_HashTableAdd(mCounts, name, counter); + } + counter->Add(aType); + } +} + +//------------------------------------------------------------------ +PRIntn ReflowCountMgr::RemoveItems(PLHashEntry *he, PRIntn i, void *arg) +{ + char *str = (char *)he->key; + ReflowCounter * counter = (ReflowCounter *)he->value; + delete counter; + delete [] str; + + return HT_ENUMERATE_REMOVE; +} + +//------------------------------------------------------------------ +void ReflowCountMgr::CleanUp() +{ + if (nsnull != mCounts) { + PL_HashTableEnumerateEntries(mCounts, RemoveItems, nsnull); + PL_HashTableDestroy(mCounts); + mCounts = nsnull; + } +} + +//------------------------------------------------------------------ +PRIntn ReflowCountMgr::DoSingleTotal(PLHashEntry *he, PRIntn i, void *arg) +{ + char *str = (char *)he->key; + ReflowCounter * counter = (ReflowCounter *)he->value; + + counter->DisplayTotals(str); + + return HT_ENUMERATE_NEXT; +} + +//------------------------------------------------------------------ +void ReflowCountMgr::DoGrandTotals() +{ + if (nsnull != mCounts) { + ReflowCounter * gTots = (ReflowCounter *)PL_HashTableLookup(mCounts, kGrandTotalsStr); + if (gTots == nsnull) { + gTots = new ReflowCounter(this); + PL_HashTableAdd(mCounts, nsCRT::strdup(kGrandTotalsStr), gTots); + } else { + gTots->ClearTotals(); + } + + static const char * title[] = {"Init", "Incrm", "Resze", "Style", "Dirty", "Total"}; + printf("\t\t\t"); + PRUint32 i; + for (i=0;ikey; + ReflowCounter * counter = (ReflowCounter *)he->value; + + counter->DisplayHTMLTotals(str); + + return HT_ENUMERATE_NEXT; +} + +//------------------------------------------------------------------ +void ReflowCountMgr::DoGrandHTMLTotals() +{ + if (nsnull != mCounts) { + ReflowCounter * gTots = (ReflowCounter *)PL_HashTableLookup(mCounts, kGrandTotalsStr); + if (gTots == nsnull) { + gTots = new ReflowCounter(this); + PL_HashTableAdd(mCounts, nsCRT::strdup(kGrandTotalsStr), gTots); + } else { + gTots->ClearTotals(); + } + + static const char * title[] = {"Class", "Init", "Incrm", "Resze", "Style", "Dirty", "Total"}; + fprintf(mFD, ""); + PRUint32 i; + for (i=0;i
%s
", title[i]); + } + fprintf(mFD, "\n"); + PL_HashTableEnumerateEntries(mCounts, DoSingleHTMLTotal, this); + } +} + +//------------------------------------ +void ReflowCountMgr::DisplayTotals(const char * aStr) +{ + printf("%s\n", aStr?aStr:"No name"); + DoGrandTotals(); + +} +//------------------------------------ +void ReflowCountMgr::DisplayHTMLTotals(const char * aStr) +{ +#ifdef WIN32 // XXX NOT XP! + char name[1024]; + + char * sptr = strrchr(aStr, '/'); + if (sptr) { + sptr++; + strcpy(name, sptr); + char * eptr = strrchr(name, '.'); + if (eptr) { + *eptr = 0; + } + strcat(name, "_stats.html"); + } + mFD = fopen(name, "w"); + if (mFD) { + fprintf(mFD, "Reflow Stats\n"); + const char * title = aStr?aStr:"No name"; + fprintf(mFD, "
%s
", title); + DoGrandHTMLTotals(); + fprintf(mFD, "
\n"); + fprintf(mFD, "\n"); + fclose(mFD); + mFD = nsnull; + } +#endif // not XP! +} +#endif // MOZ_REFLOW_PERF diff --git a/layout/html/base/src/nsScrollFrame.cpp b/layout/html/base/src/nsScrollFrame.cpp index f1e3bb86732..4e01367bb1b 100644 --- a/layout/html/base/src/nsScrollFrame.cpp +++ b/layout/html/base/src/nsScrollFrame.cpp @@ -540,6 +540,7 @@ nsScrollFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsScrollFrame", aReflowState.reason); NS_FRAME_TRACE_MSG(NS_FRAME_TRACE_CALLS, ("enter nsScrollFrame::Reflow: maxSize=%d,%d", aReflowState.availableWidth, diff --git a/layout/html/base/src/nsSimplePageSequence.cpp b/layout/html/base/src/nsSimplePageSequence.cpp index 6f164b9e13c..e6d9bbfc664 100644 --- a/layout/html/base/src/nsSimplePageSequence.cpp +++ b/layout/html/base/src/nsSimplePageSequence.cpp @@ -206,6 +206,7 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsSimplePageSequenceFrame", aReflowState.reason); NS_FRAME_TRACE_REFLOW_IN("nsSimplePageSequenceFrame::Reflow"); aStatus = NS_FRAME_COMPLETE; // we're always complete diff --git a/layout/html/base/src/nsSpacerFrame.cpp b/layout/html/base/src/nsSpacerFrame.cpp index 05f64a7b885..f29dac908b9 100644 --- a/layout/html/base/src/nsSpacerFrame.cpp +++ b/layout/html/base/src/nsSpacerFrame.cpp @@ -82,6 +82,7 @@ SpacerFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("SpacerFrame", aReflowState.reason); aStatus = NS_FRAME_COMPLETE; // By default, we have no area diff --git a/layout/html/base/src/nsTextFrame.cpp b/layout/html/base/src/nsTextFrame.cpp index a536703fd6e..5c15d80e62c 100644 --- a/layout/html/base/src/nsTextFrame.cpp +++ b/layout/html/base/src/nsTextFrame.cpp @@ -4054,6 +4054,7 @@ nsTextFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsTextFrame", aReflowState.reason); #ifdef NOISY_REFLOW ListTag(stdout); printf(": BeginReflow: availableSize=%d,%d\n", diff --git a/layout/html/base/src/nsViewportFrame.cpp b/layout/html/base/src/nsViewportFrame.cpp index 9acbe204605..9ba9aa28396 100644 --- a/layout/html/base/src/nsViewportFrame.cpp +++ b/layout/html/base/src/nsViewportFrame.cpp @@ -482,6 +482,7 @@ ViewportFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("ViewportFrame", aReflowState.reason); NS_FRAME_TRACE_REFLOW_IN("ViewportFrame::Reflow"); NS_PRECONDITION(nsnull == aDesiredSize.maxElementSize, "unexpected request"); diff --git a/layout/xul/base/src/nsBoxFrame.cpp b/layout/xul/base/src/nsBoxFrame.cpp index 33abaf8522b..e2b7e4eec99 100644 --- a/layout/xul/base/src/nsBoxFrame.cpp +++ b/layout/xul/base/src/nsBoxFrame.cpp @@ -610,6 +610,7 @@ nsBoxFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsBoxFrame", aReflowState.reason); #ifdef DEBUG_REFLOW gIndent++; #endif diff --git a/layout/xul/base/src/nsBoxToBlockAdaptor.cpp b/layout/xul/base/src/nsBoxToBlockAdaptor.cpp index 5dd52c596ed..8d0b3201de6 100644 --- a/layout/xul/base/src/nsBoxToBlockAdaptor.cpp +++ b/layout/xul/base/src/nsBoxToBlockAdaptor.cpp @@ -344,6 +344,7 @@ nsBoxToBlockAdaptor::Reflow(nsIPresContext* aPresContext, nscoord aHeight, PRBool aMoveFrame) { + DO_GLOBAL_REFLOW_COUNT("nsBoxToBlockAdaptor", aReflowState.reason); //printf("width=%d, height=%d\n", aWidth, aHeight); diff --git a/layout/xul/base/src/nsLeafBoxFrame.cpp b/layout/xul/base/src/nsLeafBoxFrame.cpp index 83a00aaaccb..17a6c0dabcd 100644 --- a/layout/xul/base/src/nsLeafBoxFrame.cpp +++ b/layout/xul/base/src/nsLeafBoxFrame.cpp @@ -139,6 +139,7 @@ nsLeafBoxFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsLeafBoxFrame", aReflowState.reason); NS_ASSERTION(aReflowState.mComputedWidth >=0 && aReflowState.mComputedHeight >= 0, "Computed Size < 0"); aStatus = NS_FRAME_COMPLETE; diff --git a/layout/xul/base/src/nsRootBoxFrame.cpp b/layout/xul/base/src/nsRootBoxFrame.cpp index bd82794ec73..cb3f5ac6400 100644 --- a/layout/xul/base/src/nsRootBoxFrame.cpp +++ b/layout/xul/base/src/nsRootBoxFrame.cpp @@ -202,6 +202,7 @@ nsRootBoxFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsRootBoxFrame", aReflowState.reason); return nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); } diff --git a/layout/xul/base/src/nsTreeCellFrame.cpp b/layout/xul/base/src/nsTreeCellFrame.cpp index 8ab549b0654..fb03a5494af 100644 --- a/layout/xul/base/src/nsTreeCellFrame.cpp +++ b/layout/xul/base/src/nsTreeCellFrame.cpp @@ -140,6 +140,7 @@ NS_IMETHODIMP nsTreeCellFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsTreeCellFrame", aReflowState.reason); //printf("Tree Cell Width: %d, Tree Cell Height: %d\n", aReflowState.mComputedWidth, aReflowState.mComputedHeight); nsresult rv = nsTableCellFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); diff --git a/layout/xul/base/src/nsTreeFrame.cpp b/layout/xul/base/src/nsTreeFrame.cpp index cf79fabb0fd..41764bf58a1 100644 --- a/layout/xul/base/src/nsTreeFrame.cpp +++ b/layout/xul/base/src/nsTreeFrame.cpp @@ -391,6 +391,7 @@ nsTreeFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsTreeFrame", aReflowState.reason); NS_ASSERTION(aReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE, "Reflowing tree with unconstrained width!!!!"); diff --git a/layout/xul/base/src/nsTreeIndentationFrame.cpp b/layout/xul/base/src/nsTreeIndentationFrame.cpp index 509add828ce..b99d1a3ecc1 100644 --- a/layout/xul/base/src/nsTreeIndentationFrame.cpp +++ b/layout/xul/base/src/nsTreeIndentationFrame.cpp @@ -68,6 +68,7 @@ nsTreeIndentationFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsTreeIndentationFrame", aReflowState.reason); aStatus = NS_FRAME_COMPLETE; // By default, we have no area diff --git a/layout/xul/base/src/nsTreeOuterFrame.cpp b/layout/xul/base/src/nsTreeOuterFrame.cpp index 2319c8d24f5..13d7db22820 100644 --- a/layout/xul/base/src/nsTreeOuterFrame.cpp +++ b/layout/xul/base/src/nsTreeOuterFrame.cpp @@ -35,6 +35,7 @@ #include "nsXULAtoms.h" #include "nsBoxFrame.h" #include "nsTreeFrame.h" +#include "nsIPresContext.h" // // NS_NewTreeOuterFrame @@ -110,6 +111,7 @@ nsTreeOuterFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsTreeOuterFrame", aReflowState.reason); // XXX at the moment we don't handle non incremental dirty reflow commands. So just convert them // to style changes for now. diff --git a/layout/xul/base/src/nsTreeRowFrame.cpp b/layout/xul/base/src/nsTreeRowFrame.cpp index ad3cb489a5d..3332f1d2715 100644 --- a/layout/xul/base/src/nsTreeRowFrame.cpp +++ b/layout/xul/base/src/nsTreeRowFrame.cpp @@ -180,6 +180,7 @@ nsTreeRowFrame::Reflow(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { + DO_GLOBAL_REFLOW_COUNT("nsTreeRowFrame", aReflowState.reason); /* if (aReflowState.reason != eReflowReason_Incremental) { // Determine the row's generation.