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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user