From b0e12359c61f20c3f454dcfad9225b602bcb0dbf Mon Sep 17 00:00:00 2001 From: "jim_nance%yahoo.com" Date: Thu, 15 Jul 2004 17:50:34 +0000 Subject: [PATCH] Fix But #250105 - Add Arena for nsLineLayout buffers. r+sr=roc git-svn-id: svn://10.0.0.236/trunk@159260 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/generic/nsBlockFrame.cpp | 80 +++++------------ mozilla/layout/generic/nsBlockFrame.h | 14 --- mozilla/layout/generic/nsLineLayout.cpp | 87 ++++++++++--------- mozilla/layout/generic/nsLineLayout.h | 29 ++++--- mozilla/layout/html/base/src/nsBlockFrame.cpp | 80 +++++------------ mozilla/layout/html/base/src/nsBlockFrame.h | 14 --- mozilla/layout/html/base/src/nsLineLayout.cpp | 87 ++++++++++--------- mozilla/layout/html/base/src/nsLineLayout.h | 29 ++++--- 8 files changed, 166 insertions(+), 254 deletions(-) diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index 6265a3b1b7a..5697bb6ab23 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -3258,23 +3258,25 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState, PRInt32 spins = 0; #endif PRUint8 lineReflowStatus = LINE_REFLOW_REDO; - while (LINE_REFLOW_REDO == lineReflowStatus) { - // Prevent overflowing limited thread stacks by creating - // nsLineLayout from the heap when the frame tree depth gets - // large. - if (aState.mReflowState.mReflowDepth > 30) {//XXX layout-tune.h? - rv = DoReflowInlineFramesMalloc(aState, aLine, aKeepReflowGoing, - &lineReflowStatus, - aUpdateMaximumWidth, aDamageDirtyArea); - } - else { - rv = DoReflowInlineFramesAuto(aState, aLine, aKeepReflowGoing, - &lineReflowStatus, - aUpdateMaximumWidth, aDamageDirtyArea); - } - if (NS_FAILED(rv)) { - break; - } + do { + // Once upon a time we allocated the first 30 nsLineLayout objects + // on the stack, and then we switched to the heap. At that time + // these objects were large (1100 bytes on a 32 bit system). + // Then the nsLineLayout object was shrunk to 156 bytes by + // removing some internal buffers. Given that it is so much + // smaller, the complexity of 2 different ways of allocating + // no longer makes sense. Now we always allocate on the stack + + nsLineLayout lineLayout(aState.mPresContext, + aState.mReflowState.mSpaceManager, + &aState.mReflowState, + aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)); + lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber); + rv = DoReflowInlineFrames(aState, lineLayout, aLine, + aKeepReflowGoing, &lineReflowStatus, + aUpdateMaximumWidth, aDamageDirtyArea); + lineLayout.EndLineReflow(); + #ifdef DEBUG spins++; if (1000 == spins) { @@ -3283,51 +3285,9 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState, NS_ABORT(); } #endif - } - return rv; -} -nsresult -nsBlockFrame::DoReflowInlineFramesMalloc(nsBlockReflowState& aState, - line_iterator aLine, - PRBool* aKeepReflowGoing, - PRUint8* aLineReflowStatus, - PRBool aUpdateMaximumWidth, - PRBool aDamageDirtyArea) -{ - // XXXldb Using the PresShell arena here would be nice. - nsLineLayout* ll = new nsLineLayout(aState.mPresContext, - aState.mReflowState.mSpaceManager, - &aState.mReflowState, - aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)); - if (!ll) { - return NS_ERROR_OUT_OF_MEMORY; - } - ll->Init(&aState, aState.mMinLineHeight, aState.mLineNumber); - nsresult rv = DoReflowInlineFrames(aState, *ll, aLine, aKeepReflowGoing, - aLineReflowStatus, aUpdateMaximumWidth, aDamageDirtyArea); - ll->EndLineReflow(); - delete ll; - return rv; -} + } while (NS_SUCCEEDED(rv) && LINE_REFLOW_REDO == lineReflowStatus); -nsresult -nsBlockFrame::DoReflowInlineFramesAuto(nsBlockReflowState& aState, - line_iterator aLine, - PRBool* aKeepReflowGoing, - PRUint8* aLineReflowStatus, - PRBool aUpdateMaximumWidth, - PRBool aDamageDirtyArea) -{ - nsLineLayout lineLayout(aState.mPresContext, - aState.mReflowState.mSpaceManager, - &aState.mReflowState, - aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)); - lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber); - nsresult rv = DoReflowInlineFrames(aState, lineLayout, aLine, - aKeepReflowGoing, aLineReflowStatus, - aUpdateMaximumWidth, aDamageDirtyArea); - lineLayout.EndLineReflow(); return rv; } diff --git a/mozilla/layout/generic/nsBlockFrame.h b/mozilla/layout/generic/nsBlockFrame.h index 2337933ac52..223ac0351ba 100644 --- a/mozilla/layout/generic/nsBlockFrame.h +++ b/mozilla/layout/generic/nsBlockFrame.h @@ -443,20 +443,6 @@ protected: PRBool aUpdateMaximumWidth, PRBool aDamageDirtyArea); - nsresult DoReflowInlineFramesAuto(nsBlockReflowState& aState, - line_iterator aLine, - PRBool* aKeepReflowGoing, - PRUint8* aLineReflowStatus, - PRBool aUpdateMaximumWidth, - PRBool aDamageDirtyArea); - - nsresult DoReflowInlineFramesMalloc(nsBlockReflowState& aState, - line_iterator aLine, - PRBool* aKeepReflowGoing, - PRUint8* aLineReflowStatus, - PRBool aUpdateMaximumWidth, - PRBool aDamageDirtyArea); - nsresult ReflowInlineFrame(nsBlockReflowState& aState, nsLineLayout& aLineLayout, line_iterator aLine, diff --git a/mozilla/layout/generic/nsLineLayout.cpp b/mozilla/layout/generic/nsLineLayout.cpp index c11bfd3f31c..769dacc81d9 100644 --- a/mozilla/layout/generic/nsLineLayout.cpp +++ b/mozilla/layout/generic/nsLineLayout.cpp @@ -39,6 +39,9 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ +#define PL_ARENA_CONST_ALIGN_MASK (sizeof(void*)-1) +#include "plarena.h" + #include "nsCOMPtr.h" #include "nsLineLayout.h" #include "nsBlockFrame.h" @@ -174,7 +177,7 @@ nsLineLayout::nsLineLayout(nsIPresContext* aPresContext, // spans, we do it on demand so that situations that only use a few // frames and spans won't waste alot of time in unneeded // initialization. - mInitialFramesFreed = mInitialSpansFreed = 0; + PL_INIT_ARENA_POOL(&mArena, "nsLineLayout", 1024); mFrameFreeList = nsnull; mSpanFreeList = nsnull; @@ -190,27 +193,35 @@ nsLineLayout::~nsLineLayout() NS_ASSERTION(nsnull == mRootSpan, "bad line-layout user"); - // Free up all of the per-span-data items that were allocated on the heap - PerSpanData* psd = mSpanFreeList; - while (nsnull != psd) { - PerSpanData* nextSpan = psd->mNextFreeSpan; - if ((psd < &mSpanDataBuf[0]) || - (psd >= &mSpanDataBuf[NS_LINELAYOUT_NUM_SPANS])) { - delete psd; - } - psd = nextSpan; - } + delete mWordFrames; // operator delete for this class just returns - // Free up all of the per-frame-data items that were allocated on the heap - PerFrameData* pfd = mFrameFreeList; - while (nsnull != pfd) { - PerFrameData* nextFrame = pfd->mNext; - if ((pfd < &mFrameDataBuf[0]) || - (pfd >= &mFrameDataBuf[NS_LINELAYOUT_NUM_FRAMES])) { - delete pfd; - } - pfd = nextFrame; - } + // PL_FreeArenaPool takes our memory and puts in on a global free list so + // that the next time an arena makes an allocation it will not have to go + // all the way down to malloc. This is desirable as this class is created + // and destroyed in a tight loop. + // + // I looked at the code. It is not technically necessary to call + // PL_FinishArenaPool() after PL_FreeArenaPool(), but from an API + // standpoint, I think we are susposed to. It will be very fast anyway, + // since PL_FreeArenaPool() has done all the work. + PL_FreeArenaPool(&mArena); + PL_FinishArenaPool(&mArena); +} + +void* +nsLineLayout::ArenaDeque::operator new(size_t aSize, PLArenaPool &aPool) +{ + void *mem; + + PL_ARENA_ALLOCATE(mem, &aPool, aSize); + return mem; +} + +PRBool nsLineLayout::AllocateDeque() +{ + mWordFrames = new(mArena) ArenaDeque; + + return mWordFrames != nsnull; } // Find out if the frame has a non-null prev-in-flow, i.e., whether it @@ -477,16 +488,12 @@ nsLineLayout::NewPerSpanData(PerSpanData** aResult) { PerSpanData* psd = mSpanFreeList; if (nsnull == psd) { - if (mInitialSpansFreed < NS_LINELAYOUT_NUM_SPANS) { - // use one of the ones defined in our struct... - psd = &mSpanDataBuf[mInitialSpansFreed++]; - } - else { - psd = new PerSpanData; - if (nsnull == psd) { - return NS_ERROR_OUT_OF_MEMORY; - } + void *mem; + PL_ARENA_ALLOCATE(mem, &mArena, sizeof(PerSpanData)); + if (nsnull == mem) { + return NS_ERROR_OUT_OF_MEMORY; } + psd = NS_REINTERPRET_CAST(PerSpanData*, mem); } else { mSpanFreeList = psd->mNextFreeSpan; @@ -757,16 +764,12 @@ nsLineLayout::NewPerFrameData(PerFrameData** aResult) { PerFrameData* pfd = mFrameFreeList; if (nsnull == pfd) { - if (mInitialFramesFreed < NS_LINELAYOUT_NUM_FRAMES) { - // use one of the ones defined in our struct... - pfd = &mFrameDataBuf[mInitialFramesFreed++]; - } - else { - pfd = new PerFrameData; - if (nsnull == pfd) { - return NS_ERROR_OUT_OF_MEMORY; - } + void *mem; + PL_ARENA_ALLOCATE(mem, &mArena, sizeof(PerFrameData)); + if (nsnull == mem) { + return NS_ERROR_OUT_OF_MEMORY; } + pfd = NS_REINTERPRET_CAST(PerFrameData*, mem); } else { mFrameFreeList = pfd->mNext; @@ -3018,9 +3021,9 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea) void nsLineLayout::ForgetWordFrame(nsIFrame* aFrame) { - if (0 != mWordFrames.GetSize()) { - NS_ASSERTION((void*)aFrame == mWordFrames.PeekFront(), "forget-word-frame"); - mWordFrames.PopFront(); + if (mWordFrames && 0 != mWordFrames->GetSize()) { + NS_ASSERTION((void*)aFrame == mWordFrames->PeekFront(), "forget-word-frame"); + mWordFrames->PopFront(); } } diff --git a/mozilla/layout/generic/nsLineLayout.h b/mozilla/layout/generic/nsLineLayout.h index b07a4eabdfe..7471874dab5 100644 --- a/mozilla/layout/generic/nsLineLayout.h +++ b/mozilla/layout/generic/nsLineLayout.h @@ -51,14 +51,12 @@ #include "nsDeque.h" #include "nsLineBox.h" #include "nsBlockReflowState.h" +#include "plarena.h" class nsSpaceManager; class nsPlaceholderFrame; struct nsStyleText; -#define NS_LINELAYOUT_NUM_FRAMES 5 -#define NS_LINELAYOUT_NUM_SPANS 5 - class nsLineLayout { public: nsLineLayout(nsIPresContext* aPresContext, @@ -67,6 +65,14 @@ public: PRBool aComputeMaxElementWidth); ~nsLineLayout(); + class ArenaDeque : public nsDeque + { + public: + ArenaDeque() : nsDeque(nsnull) {} + void *operator new(size_t, PLArenaPool &pool); + void operator delete(void *) {} // Dont do anything. Its Arena memory + }; + void Init(nsBlockReflowState* aState, nscoord aMinLineHeight, PRInt32 aLineNumber) { mBlockRS = aState; @@ -201,17 +207,20 @@ public: } void RecordWordFrame(nsIFrame* aWordFrame) { - mWordFrames.Push(aWordFrame); + if(mWordFrames || AllocateDeque()) + mWordFrames->Push(aWordFrame); } PRBool InWord() const { - return 0 != mWordFrames.GetSize(); + return mWordFrames && 0 != mWordFrames->GetSize(); } void ForgetWordFrame(nsIFrame* aFrame); void ForgetWordFrames() { - mWordFrames.Empty(); + if(mWordFrames) { + mWordFrames->Empty(); + } } nsIFrame* FindNextText(nsIPresContext* aPresContext, nsIFrame* aFrame); @@ -311,7 +320,8 @@ protected: nsLineBox* mLineBox; PRInt32 mTotalPlacedFrames; - nsDeque mWordFrames; + ArenaDeque *mWordFrames; + PRBool AllocateDeque(); nscoord mTopEdge; nscoord mBottomEdge; @@ -403,9 +413,7 @@ protected: return pfd; } }; - PerFrameData mFrameDataBuf[NS_LINELAYOUT_NUM_FRAMES]; PerFrameData* mFrameFreeList; - PRInt32 mInitialFramesFreed; struct PerSpanData { union { @@ -442,9 +450,7 @@ protected: mLastFrame = pfd; } }; - PerSpanData mSpanDataBuf[NS_LINELAYOUT_NUM_SPANS]; PerSpanData* mSpanFreeList; - PRInt32 mInitialSpansFreed; PerSpanData* mRootSpan; PerSpanData* mCurrentSpan; PRInt32 mSpanDepth; @@ -452,6 +458,7 @@ protected: PRInt32 mSpansAllocated, mSpansFreed; PRInt32 mFramesAllocated, mFramesFreed; #endif + PLArenaPool mArena; // Per span and per frame data nsresult NewPerFrameData(PerFrameData** aResult); diff --git a/mozilla/layout/html/base/src/nsBlockFrame.cpp b/mozilla/layout/html/base/src/nsBlockFrame.cpp index 6265a3b1b7a..5697bb6ab23 100644 --- a/mozilla/layout/html/base/src/nsBlockFrame.cpp +++ b/mozilla/layout/html/base/src/nsBlockFrame.cpp @@ -3258,23 +3258,25 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState, PRInt32 spins = 0; #endif PRUint8 lineReflowStatus = LINE_REFLOW_REDO; - while (LINE_REFLOW_REDO == lineReflowStatus) { - // Prevent overflowing limited thread stacks by creating - // nsLineLayout from the heap when the frame tree depth gets - // large. - if (aState.mReflowState.mReflowDepth > 30) {//XXX layout-tune.h? - rv = DoReflowInlineFramesMalloc(aState, aLine, aKeepReflowGoing, - &lineReflowStatus, - aUpdateMaximumWidth, aDamageDirtyArea); - } - else { - rv = DoReflowInlineFramesAuto(aState, aLine, aKeepReflowGoing, - &lineReflowStatus, - aUpdateMaximumWidth, aDamageDirtyArea); - } - if (NS_FAILED(rv)) { - break; - } + do { + // Once upon a time we allocated the first 30 nsLineLayout objects + // on the stack, and then we switched to the heap. At that time + // these objects were large (1100 bytes on a 32 bit system). + // Then the nsLineLayout object was shrunk to 156 bytes by + // removing some internal buffers. Given that it is so much + // smaller, the complexity of 2 different ways of allocating + // no longer makes sense. Now we always allocate on the stack + + nsLineLayout lineLayout(aState.mPresContext, + aState.mReflowState.mSpaceManager, + &aState.mReflowState, + aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)); + lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber); + rv = DoReflowInlineFrames(aState, lineLayout, aLine, + aKeepReflowGoing, &lineReflowStatus, + aUpdateMaximumWidth, aDamageDirtyArea); + lineLayout.EndLineReflow(); + #ifdef DEBUG spins++; if (1000 == spins) { @@ -3283,51 +3285,9 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState, NS_ABORT(); } #endif - } - return rv; -} -nsresult -nsBlockFrame::DoReflowInlineFramesMalloc(nsBlockReflowState& aState, - line_iterator aLine, - PRBool* aKeepReflowGoing, - PRUint8* aLineReflowStatus, - PRBool aUpdateMaximumWidth, - PRBool aDamageDirtyArea) -{ - // XXXldb Using the PresShell arena here would be nice. - nsLineLayout* ll = new nsLineLayout(aState.mPresContext, - aState.mReflowState.mSpaceManager, - &aState.mReflowState, - aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)); - if (!ll) { - return NS_ERROR_OUT_OF_MEMORY; - } - ll->Init(&aState, aState.mMinLineHeight, aState.mLineNumber); - nsresult rv = DoReflowInlineFrames(aState, *ll, aLine, aKeepReflowGoing, - aLineReflowStatus, aUpdateMaximumWidth, aDamageDirtyArea); - ll->EndLineReflow(); - delete ll; - return rv; -} + } while (NS_SUCCEEDED(rv) && LINE_REFLOW_REDO == lineReflowStatus); -nsresult -nsBlockFrame::DoReflowInlineFramesAuto(nsBlockReflowState& aState, - line_iterator aLine, - PRBool* aKeepReflowGoing, - PRUint8* aLineReflowStatus, - PRBool aUpdateMaximumWidth, - PRBool aDamageDirtyArea) -{ - nsLineLayout lineLayout(aState.mPresContext, - aState.mReflowState.mSpaceManager, - &aState.mReflowState, - aState.GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)); - lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber); - nsresult rv = DoReflowInlineFrames(aState, lineLayout, aLine, - aKeepReflowGoing, aLineReflowStatus, - aUpdateMaximumWidth, aDamageDirtyArea); - lineLayout.EndLineReflow(); return rv; } diff --git a/mozilla/layout/html/base/src/nsBlockFrame.h b/mozilla/layout/html/base/src/nsBlockFrame.h index 2337933ac52..223ac0351ba 100644 --- a/mozilla/layout/html/base/src/nsBlockFrame.h +++ b/mozilla/layout/html/base/src/nsBlockFrame.h @@ -443,20 +443,6 @@ protected: PRBool aUpdateMaximumWidth, PRBool aDamageDirtyArea); - nsresult DoReflowInlineFramesAuto(nsBlockReflowState& aState, - line_iterator aLine, - PRBool* aKeepReflowGoing, - PRUint8* aLineReflowStatus, - PRBool aUpdateMaximumWidth, - PRBool aDamageDirtyArea); - - nsresult DoReflowInlineFramesMalloc(nsBlockReflowState& aState, - line_iterator aLine, - PRBool* aKeepReflowGoing, - PRUint8* aLineReflowStatus, - PRBool aUpdateMaximumWidth, - PRBool aDamageDirtyArea); - nsresult ReflowInlineFrame(nsBlockReflowState& aState, nsLineLayout& aLineLayout, line_iterator aLine, diff --git a/mozilla/layout/html/base/src/nsLineLayout.cpp b/mozilla/layout/html/base/src/nsLineLayout.cpp index c11bfd3f31c..769dacc81d9 100644 --- a/mozilla/layout/html/base/src/nsLineLayout.cpp +++ b/mozilla/layout/html/base/src/nsLineLayout.cpp @@ -39,6 +39,9 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ +#define PL_ARENA_CONST_ALIGN_MASK (sizeof(void*)-1) +#include "plarena.h" + #include "nsCOMPtr.h" #include "nsLineLayout.h" #include "nsBlockFrame.h" @@ -174,7 +177,7 @@ nsLineLayout::nsLineLayout(nsIPresContext* aPresContext, // spans, we do it on demand so that situations that only use a few // frames and spans won't waste alot of time in unneeded // initialization. - mInitialFramesFreed = mInitialSpansFreed = 0; + PL_INIT_ARENA_POOL(&mArena, "nsLineLayout", 1024); mFrameFreeList = nsnull; mSpanFreeList = nsnull; @@ -190,27 +193,35 @@ nsLineLayout::~nsLineLayout() NS_ASSERTION(nsnull == mRootSpan, "bad line-layout user"); - // Free up all of the per-span-data items that were allocated on the heap - PerSpanData* psd = mSpanFreeList; - while (nsnull != psd) { - PerSpanData* nextSpan = psd->mNextFreeSpan; - if ((psd < &mSpanDataBuf[0]) || - (psd >= &mSpanDataBuf[NS_LINELAYOUT_NUM_SPANS])) { - delete psd; - } - psd = nextSpan; - } + delete mWordFrames; // operator delete for this class just returns - // Free up all of the per-frame-data items that were allocated on the heap - PerFrameData* pfd = mFrameFreeList; - while (nsnull != pfd) { - PerFrameData* nextFrame = pfd->mNext; - if ((pfd < &mFrameDataBuf[0]) || - (pfd >= &mFrameDataBuf[NS_LINELAYOUT_NUM_FRAMES])) { - delete pfd; - } - pfd = nextFrame; - } + // PL_FreeArenaPool takes our memory and puts in on a global free list so + // that the next time an arena makes an allocation it will not have to go + // all the way down to malloc. This is desirable as this class is created + // and destroyed in a tight loop. + // + // I looked at the code. It is not technically necessary to call + // PL_FinishArenaPool() after PL_FreeArenaPool(), but from an API + // standpoint, I think we are susposed to. It will be very fast anyway, + // since PL_FreeArenaPool() has done all the work. + PL_FreeArenaPool(&mArena); + PL_FinishArenaPool(&mArena); +} + +void* +nsLineLayout::ArenaDeque::operator new(size_t aSize, PLArenaPool &aPool) +{ + void *mem; + + PL_ARENA_ALLOCATE(mem, &aPool, aSize); + return mem; +} + +PRBool nsLineLayout::AllocateDeque() +{ + mWordFrames = new(mArena) ArenaDeque; + + return mWordFrames != nsnull; } // Find out if the frame has a non-null prev-in-flow, i.e., whether it @@ -477,16 +488,12 @@ nsLineLayout::NewPerSpanData(PerSpanData** aResult) { PerSpanData* psd = mSpanFreeList; if (nsnull == psd) { - if (mInitialSpansFreed < NS_LINELAYOUT_NUM_SPANS) { - // use one of the ones defined in our struct... - psd = &mSpanDataBuf[mInitialSpansFreed++]; - } - else { - psd = new PerSpanData; - if (nsnull == psd) { - return NS_ERROR_OUT_OF_MEMORY; - } + void *mem; + PL_ARENA_ALLOCATE(mem, &mArena, sizeof(PerSpanData)); + if (nsnull == mem) { + return NS_ERROR_OUT_OF_MEMORY; } + psd = NS_REINTERPRET_CAST(PerSpanData*, mem); } else { mSpanFreeList = psd->mNextFreeSpan; @@ -757,16 +764,12 @@ nsLineLayout::NewPerFrameData(PerFrameData** aResult) { PerFrameData* pfd = mFrameFreeList; if (nsnull == pfd) { - if (mInitialFramesFreed < NS_LINELAYOUT_NUM_FRAMES) { - // use one of the ones defined in our struct... - pfd = &mFrameDataBuf[mInitialFramesFreed++]; - } - else { - pfd = new PerFrameData; - if (nsnull == pfd) { - return NS_ERROR_OUT_OF_MEMORY; - } + void *mem; + PL_ARENA_ALLOCATE(mem, &mArena, sizeof(PerFrameData)); + if (nsnull == mem) { + return NS_ERROR_OUT_OF_MEMORY; } + pfd = NS_REINTERPRET_CAST(PerFrameData*, mem); } else { mFrameFreeList = pfd->mNext; @@ -3018,9 +3021,9 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea) void nsLineLayout::ForgetWordFrame(nsIFrame* aFrame) { - if (0 != mWordFrames.GetSize()) { - NS_ASSERTION((void*)aFrame == mWordFrames.PeekFront(), "forget-word-frame"); - mWordFrames.PopFront(); + if (mWordFrames && 0 != mWordFrames->GetSize()) { + NS_ASSERTION((void*)aFrame == mWordFrames->PeekFront(), "forget-word-frame"); + mWordFrames->PopFront(); } } diff --git a/mozilla/layout/html/base/src/nsLineLayout.h b/mozilla/layout/html/base/src/nsLineLayout.h index b07a4eabdfe..7471874dab5 100644 --- a/mozilla/layout/html/base/src/nsLineLayout.h +++ b/mozilla/layout/html/base/src/nsLineLayout.h @@ -51,14 +51,12 @@ #include "nsDeque.h" #include "nsLineBox.h" #include "nsBlockReflowState.h" +#include "plarena.h" class nsSpaceManager; class nsPlaceholderFrame; struct nsStyleText; -#define NS_LINELAYOUT_NUM_FRAMES 5 -#define NS_LINELAYOUT_NUM_SPANS 5 - class nsLineLayout { public: nsLineLayout(nsIPresContext* aPresContext, @@ -67,6 +65,14 @@ public: PRBool aComputeMaxElementWidth); ~nsLineLayout(); + class ArenaDeque : public nsDeque + { + public: + ArenaDeque() : nsDeque(nsnull) {} + void *operator new(size_t, PLArenaPool &pool); + void operator delete(void *) {} // Dont do anything. Its Arena memory + }; + void Init(nsBlockReflowState* aState, nscoord aMinLineHeight, PRInt32 aLineNumber) { mBlockRS = aState; @@ -201,17 +207,20 @@ public: } void RecordWordFrame(nsIFrame* aWordFrame) { - mWordFrames.Push(aWordFrame); + if(mWordFrames || AllocateDeque()) + mWordFrames->Push(aWordFrame); } PRBool InWord() const { - return 0 != mWordFrames.GetSize(); + return mWordFrames && 0 != mWordFrames->GetSize(); } void ForgetWordFrame(nsIFrame* aFrame); void ForgetWordFrames() { - mWordFrames.Empty(); + if(mWordFrames) { + mWordFrames->Empty(); + } } nsIFrame* FindNextText(nsIPresContext* aPresContext, nsIFrame* aFrame); @@ -311,7 +320,8 @@ protected: nsLineBox* mLineBox; PRInt32 mTotalPlacedFrames; - nsDeque mWordFrames; + ArenaDeque *mWordFrames; + PRBool AllocateDeque(); nscoord mTopEdge; nscoord mBottomEdge; @@ -403,9 +413,7 @@ protected: return pfd; } }; - PerFrameData mFrameDataBuf[NS_LINELAYOUT_NUM_FRAMES]; PerFrameData* mFrameFreeList; - PRInt32 mInitialFramesFreed; struct PerSpanData { union { @@ -442,9 +450,7 @@ protected: mLastFrame = pfd; } }; - PerSpanData mSpanDataBuf[NS_LINELAYOUT_NUM_SPANS]; PerSpanData* mSpanFreeList; - PRInt32 mInitialSpansFreed; PerSpanData* mRootSpan; PerSpanData* mCurrentSpan; PRInt32 mSpanDepth; @@ -452,6 +458,7 @@ protected: PRInt32 mSpansAllocated, mSpansFreed; PRInt32 mFramesAllocated, mFramesFreed; #endif + PLArenaPool mArena; // Per span and per frame data nsresult NewPerFrameData(PerFrameData** aResult);