Back out most of patch for bug 154910 to fix crash, since nsLineLayout need not do all its allocation without other things lower on the stack. b=162516

This commit is contained in:
dbaron%fas.harvard.edu 2002-08-14 13:00:16 +00:00
parent 22351decd5
commit 815f207e63
4 changed files with 310 additions and 118 deletions

View File

@ -179,16 +179,18 @@ nsLineLayout::nsLineLayout(nsIPresContext* aPresContext,
mTotalPlacedFrames = 0;
mTopEdge = mBottomEdge = 0;
// Instead of always pre-initializing the free-lists for frames and
// 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;
mFrameFreeList = nsnull;
mSpanFreeList = nsnull;
mCurrentSpan = mRootSpan = nsnull;
mSpanDepth = 0;
mPresContext->GetCompatibilityMode(&mCompatMode);
// Mark the dynamic stack on which we will allocate |PerSpanData| and
// |PerFrameData| objects.
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
shell->PushStackMemory();
}
nsLineLayout::~nsLineLayout()
@ -197,11 +199,27 @@ nsLineLayout::~nsLineLayout()
NS_ASSERTION(nsnull == mRootSpan, "bad line-layout user");
// Free up the space in which we allocated |PerSpanData| and
// |PerFrameData| objects.
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
shell->PopStackMemory();
// 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;
}
// 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;
}
}
// Find out if the frame has a non-null prev-in-flow, i.e., whether it
@ -242,6 +260,9 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
aImpactedByFloaters?"true":"false",
aIsTopOfPage ? "top-of-page" : "");
#endif
#ifdef DEBUG
mSpansAllocated = mSpansFreed = mFramesAllocated = mFramesFreed = 0;
#endif
mColumn = 0;
@ -332,7 +353,24 @@ nsLineLayout::EndLineReflow()
printf(": EndLineReflow: width=%d\n", mRootSpan->mX - mRootSpan->mLeftEdge);
#endif
FreeSpan(mRootSpan);
mCurrentSpan = mRootSpan = nsnull;
NS_ASSERTION(mSpansAllocated == mSpansFreed, "leak");
NS_ASSERTION(mFramesAllocated == mFramesFreed, "leak");
#if 0
static PRInt32 maxSpansAllocated = NS_LINELAYOUT_NUM_SPANS;
static PRInt32 maxFramesAllocated = NS_LINELAYOUT_NUM_FRAMES;
if (mSpansAllocated > maxSpansAllocated) {
printf("XXX: saw a line with %d spans\n", mSpansAllocated);
maxSpansAllocated = mSpansAllocated;
}
if (mFramesAllocated > maxFramesAllocated) {
printf("XXX: saw a line with %d frames\n", mFramesAllocated);
maxFramesAllocated = mFramesAllocated;
}
#endif
}
// XXX swtich to a single mAvailLineWidth that we adjust as each frame
@ -455,12 +493,22 @@ nsLineLayout::UpdateFrames()
nsresult
nsLineLayout::NewPerSpanData(PerSpanData** aResult)
{
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
PerSpanData* psd = new (shell) PerSpanData;
if (!psd)
return NS_ERROR_OUT_OF_MEMORY;
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;
}
}
}
else {
mSpanFreeList = psd->mNextFreeSpan;
}
psd->mParent = nsnull;
psd->mFrame = nsnull;
psd->mFirstFrame = nsnull;
@ -468,6 +516,9 @@ nsLineLayout::NewPerSpanData(PerSpanData** aResult)
psd->mContainsFloater = PR_FALSE;
psd->mZeroEffectiveSpanBox = PR_FALSE;
#ifdef DEBUG
mSpansAllocated++;
#endif
*aResult = psd;
return NS_OK;
}
@ -618,10 +669,25 @@ nsLineLayout::SplitLineTo(PRInt32 aNewCount)
PerFrameData* pfd = psd->mFirstFrame;
while (nsnull != pfd) {
if (--aNewCount == 0) {
// Truncate list at pfd (we keep pfd; leak the rest in dynamic stack)
// Truncate list at pfd (we keep pfd, but anything following is freed)
PerFrameData* next = pfd->mNext;
pfd->mNext = nsnull;
psd->mLastFrame = pfd;
// Now release all of the frames following pfd
pfd = next;
while (nsnull != pfd) {
next = pfd->mNext;
pfd->mNext = mFrameFreeList;
mFrameFreeList = pfd;
#ifdef DEBUG
mFramesFreed++;
#endif
if (nsnull != pfd->mSpan) {
FreeSpan(pfd->mSpan);
}
pfd = next;
}
break;
}
pfd = pfd->mNext;
@ -658,6 +724,15 @@ nsLineLayout::PushFrame(nsIFrame* aFrame)
psd->mLastFrame = prevFrame;
}
// Now free it, and if it has a span, free that too
pfd->mNext = mFrameFreeList;
mFrameFreeList = pfd;
#ifdef DEBUG
mFramesFreed++;
#endif
if (nsnull != pfd->mSpan) {
FreeSpan(pfd->mSpan);
}
#ifdef NOISY_PUSHING
nsFrame::IndentBy(stdout, mSpanDepth);
printf("PushFrame: %p after:\n", psd);
@ -665,6 +740,32 @@ nsLineLayout::PushFrame(nsIFrame* aFrame)
#endif
}
void
nsLineLayout::FreeSpan(PerSpanData* psd)
{
// Free its frames
PerFrameData* pfd = psd->mFirstFrame;
while (nsnull != pfd) {
if (nsnull != pfd->mSpan) {
FreeSpan(pfd->mSpan);
}
PerFrameData* next = pfd->mNext;
pfd->mNext = mFrameFreeList;
mFrameFreeList = pfd;
#ifdef DEBUG
mFramesFreed++;
#endif
pfd = next;
}
// Now put the span on the free list since its free too
psd->mNextFreeSpan = mSpanFreeList;
mSpanFreeList = psd;
#ifdef DEBUG
mSpansFreed++;
#endif
}
PRBool
nsLineLayout::IsZeroHeight()
{
@ -682,12 +783,22 @@ nsLineLayout::IsZeroHeight()
nsresult
nsLineLayout::NewPerFrameData(PerFrameData** aResult)
{
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
PerFrameData* pfd = new (shell) PerFrameData;
if (!pfd)
return NS_ERROR_OUT_OF_MEMORY;
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;
}
}
}
else {
mFrameFreeList = pfd->mNext;
}
pfd->mSpan = nsnull;
pfd->mNext = nsnull;
pfd->mPrev = nsnull;
@ -696,6 +807,7 @@ nsLineLayout::NewPerFrameData(PerFrameData** aResult)
#ifdef DEBUG
pfd->mVerticalAlign = 0xFF;
mFramesAllocated++;
#endif
*aResult = pfd;
return NS_OK;

View File

@ -40,6 +40,9 @@ class nsSpaceManager;
class nsPlaceholderFrame;
struct nsStyleText;
#define NS_LINELAYOUT_NUM_FRAMES 5
#define NS_LINELAYOUT_NUM_SPANS 5
class nsLineLayout {
public:
nsLineLayout(nsIPresContext* aPresContext,
@ -382,30 +385,19 @@ protected:
}
return pfd;
}
// PerFrameData objects are allocated in the pres shell's dynamic
// stack arena.
void* operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW {
void *ptr;
aPresShell->AllocateStackMemory(sz, &ptr);
return ptr;
}
void operator delete(void* aPtr, size_t sz) {
NS_NOTREACHED("PerFrameData destructors are not called");
}
private:
// The normal operator new is disallowed.
void* operator new(size_t sz) CPP_THROW_NEW { return nsnull; };
};
PerFrameData mFrameDataBuf[NS_LINELAYOUT_NUM_FRAMES];
PerFrameData* mFrameFreeList;
PRInt32 mInitialFramesFreed;
#if defined(AIX_XLC_364) || defined(XP_OS2_VACPP)
public:
#endif
struct PerSpanData {
PerSpanData* mParent;
union {
PerSpanData* mParent;
PerSpanData* mNextFreeSpan;
};
PerFrameData* mFrame;
PerFrameData* mFirstFrame;
PerFrameData* mLastFrame;
@ -435,35 +427,27 @@ public:
}
mLastFrame = pfd;
}
// PerSpanData objects are allocated in the pres shell's dynamic
// stack arena.
void* operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW {
void *ptr;
aPresShell->AllocateStackMemory(sz, &ptr);
return ptr;
}
void operator delete(void* aPtr, size_t sz) {
NS_NOTREACHED("PerSpanData destructors are not called");
}
private:
// The normal operator new is disallowed.
void* operator new(size_t sz) CPP_THROW_NEW { return nsnull; };
};
#if defined(AIX_XLC_364) || defined(XP_OS2_VACPP)
protected:
#endif
PerSpanData mSpanDataBuf[NS_LINELAYOUT_NUM_SPANS];
PerSpanData* mSpanFreeList;
PRInt32 mInitialSpansFreed;
PerSpanData* mRootSpan;
PerSpanData* mCurrentSpan;
PRInt32 mSpanDepth;
#ifdef DEBUG
PRInt32 mSpansAllocated, mSpansFreed;
PRInt32 mFramesAllocated, mFramesFreed;
#endif
nsresult NewPerFrameData(PerFrameData** aResult);
nsresult NewPerSpanData(PerSpanData** aResult);
void FreeSpan(PerSpanData* psd);
PRBool InBlockContext() const {
return mSpanDepth == 0;
}

View File

@ -179,16 +179,18 @@ nsLineLayout::nsLineLayout(nsIPresContext* aPresContext,
mTotalPlacedFrames = 0;
mTopEdge = mBottomEdge = 0;
// Instead of always pre-initializing the free-lists for frames and
// 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;
mFrameFreeList = nsnull;
mSpanFreeList = nsnull;
mCurrentSpan = mRootSpan = nsnull;
mSpanDepth = 0;
mPresContext->GetCompatibilityMode(&mCompatMode);
// Mark the dynamic stack on which we will allocate |PerSpanData| and
// |PerFrameData| objects.
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
shell->PushStackMemory();
}
nsLineLayout::~nsLineLayout()
@ -197,11 +199,27 @@ nsLineLayout::~nsLineLayout()
NS_ASSERTION(nsnull == mRootSpan, "bad line-layout user");
// Free up the space in which we allocated |PerSpanData| and
// |PerFrameData| objects.
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
shell->PopStackMemory();
// 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;
}
// 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;
}
}
// Find out if the frame has a non-null prev-in-flow, i.e., whether it
@ -242,6 +260,9 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
aImpactedByFloaters?"true":"false",
aIsTopOfPage ? "top-of-page" : "");
#endif
#ifdef DEBUG
mSpansAllocated = mSpansFreed = mFramesAllocated = mFramesFreed = 0;
#endif
mColumn = 0;
@ -332,7 +353,24 @@ nsLineLayout::EndLineReflow()
printf(": EndLineReflow: width=%d\n", mRootSpan->mX - mRootSpan->mLeftEdge);
#endif
FreeSpan(mRootSpan);
mCurrentSpan = mRootSpan = nsnull;
NS_ASSERTION(mSpansAllocated == mSpansFreed, "leak");
NS_ASSERTION(mFramesAllocated == mFramesFreed, "leak");
#if 0
static PRInt32 maxSpansAllocated = NS_LINELAYOUT_NUM_SPANS;
static PRInt32 maxFramesAllocated = NS_LINELAYOUT_NUM_FRAMES;
if (mSpansAllocated > maxSpansAllocated) {
printf("XXX: saw a line with %d spans\n", mSpansAllocated);
maxSpansAllocated = mSpansAllocated;
}
if (mFramesAllocated > maxFramesAllocated) {
printf("XXX: saw a line with %d frames\n", mFramesAllocated);
maxFramesAllocated = mFramesAllocated;
}
#endif
}
// XXX swtich to a single mAvailLineWidth that we adjust as each frame
@ -455,12 +493,22 @@ nsLineLayout::UpdateFrames()
nsresult
nsLineLayout::NewPerSpanData(PerSpanData** aResult)
{
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
PerSpanData* psd = new (shell) PerSpanData;
if (!psd)
return NS_ERROR_OUT_OF_MEMORY;
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;
}
}
}
else {
mSpanFreeList = psd->mNextFreeSpan;
}
psd->mParent = nsnull;
psd->mFrame = nsnull;
psd->mFirstFrame = nsnull;
@ -468,6 +516,9 @@ nsLineLayout::NewPerSpanData(PerSpanData** aResult)
psd->mContainsFloater = PR_FALSE;
psd->mZeroEffectiveSpanBox = PR_FALSE;
#ifdef DEBUG
mSpansAllocated++;
#endif
*aResult = psd;
return NS_OK;
}
@ -618,10 +669,25 @@ nsLineLayout::SplitLineTo(PRInt32 aNewCount)
PerFrameData* pfd = psd->mFirstFrame;
while (nsnull != pfd) {
if (--aNewCount == 0) {
// Truncate list at pfd (we keep pfd; leak the rest in dynamic stack)
// Truncate list at pfd (we keep pfd, but anything following is freed)
PerFrameData* next = pfd->mNext;
pfd->mNext = nsnull;
psd->mLastFrame = pfd;
// Now release all of the frames following pfd
pfd = next;
while (nsnull != pfd) {
next = pfd->mNext;
pfd->mNext = mFrameFreeList;
mFrameFreeList = pfd;
#ifdef DEBUG
mFramesFreed++;
#endif
if (nsnull != pfd->mSpan) {
FreeSpan(pfd->mSpan);
}
pfd = next;
}
break;
}
pfd = pfd->mNext;
@ -658,6 +724,15 @@ nsLineLayout::PushFrame(nsIFrame* aFrame)
psd->mLastFrame = prevFrame;
}
// Now free it, and if it has a span, free that too
pfd->mNext = mFrameFreeList;
mFrameFreeList = pfd;
#ifdef DEBUG
mFramesFreed++;
#endif
if (nsnull != pfd->mSpan) {
FreeSpan(pfd->mSpan);
}
#ifdef NOISY_PUSHING
nsFrame::IndentBy(stdout, mSpanDepth);
printf("PushFrame: %p after:\n", psd);
@ -665,6 +740,32 @@ nsLineLayout::PushFrame(nsIFrame* aFrame)
#endif
}
void
nsLineLayout::FreeSpan(PerSpanData* psd)
{
// Free its frames
PerFrameData* pfd = psd->mFirstFrame;
while (nsnull != pfd) {
if (nsnull != pfd->mSpan) {
FreeSpan(pfd->mSpan);
}
PerFrameData* next = pfd->mNext;
pfd->mNext = mFrameFreeList;
mFrameFreeList = pfd;
#ifdef DEBUG
mFramesFreed++;
#endif
pfd = next;
}
// Now put the span on the free list since its free too
psd->mNextFreeSpan = mSpanFreeList;
mSpanFreeList = psd;
#ifdef DEBUG
mSpansFreed++;
#endif
}
PRBool
nsLineLayout::IsZeroHeight()
{
@ -682,12 +783,22 @@ nsLineLayout::IsZeroHeight()
nsresult
nsLineLayout::NewPerFrameData(PerFrameData** aResult)
{
nsCOMPtr<nsIPresShell> shell;
mPresContext->GetShell(getter_AddRefs(shell));
PerFrameData* pfd = new (shell) PerFrameData;
if (!pfd)
return NS_ERROR_OUT_OF_MEMORY;
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;
}
}
}
else {
mFrameFreeList = pfd->mNext;
}
pfd->mSpan = nsnull;
pfd->mNext = nsnull;
pfd->mPrev = nsnull;
@ -696,6 +807,7 @@ nsLineLayout::NewPerFrameData(PerFrameData** aResult)
#ifdef DEBUG
pfd->mVerticalAlign = 0xFF;
mFramesAllocated++;
#endif
*aResult = pfd;
return NS_OK;

View File

@ -40,6 +40,9 @@ class nsSpaceManager;
class nsPlaceholderFrame;
struct nsStyleText;
#define NS_LINELAYOUT_NUM_FRAMES 5
#define NS_LINELAYOUT_NUM_SPANS 5
class nsLineLayout {
public:
nsLineLayout(nsIPresContext* aPresContext,
@ -382,30 +385,19 @@ protected:
}
return pfd;
}
// PerFrameData objects are allocated in the pres shell's dynamic
// stack arena.
void* operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW {
void *ptr;
aPresShell->AllocateStackMemory(sz, &ptr);
return ptr;
}
void operator delete(void* aPtr, size_t sz) {
NS_NOTREACHED("PerFrameData destructors are not called");
}
private:
// The normal operator new is disallowed.
void* operator new(size_t sz) CPP_THROW_NEW { return nsnull; };
};
PerFrameData mFrameDataBuf[NS_LINELAYOUT_NUM_FRAMES];
PerFrameData* mFrameFreeList;
PRInt32 mInitialFramesFreed;
#if defined(AIX_XLC_364) || defined(XP_OS2_VACPP)
public:
#endif
struct PerSpanData {
PerSpanData* mParent;
union {
PerSpanData* mParent;
PerSpanData* mNextFreeSpan;
};
PerFrameData* mFrame;
PerFrameData* mFirstFrame;
PerFrameData* mLastFrame;
@ -435,35 +427,27 @@ public:
}
mLastFrame = pfd;
}
// PerSpanData objects are allocated in the pres shell's dynamic
// stack arena.
void* operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW {
void *ptr;
aPresShell->AllocateStackMemory(sz, &ptr);
return ptr;
}
void operator delete(void* aPtr, size_t sz) {
NS_NOTREACHED("PerSpanData destructors are not called");
}
private:
// The normal operator new is disallowed.
void* operator new(size_t sz) CPP_THROW_NEW { return nsnull; };
};
#if defined(AIX_XLC_364) || defined(XP_OS2_VACPP)
protected:
#endif
PerSpanData mSpanDataBuf[NS_LINELAYOUT_NUM_SPANS];
PerSpanData* mSpanFreeList;
PRInt32 mInitialSpansFreed;
PerSpanData* mRootSpan;
PerSpanData* mCurrentSpan;
PRInt32 mSpanDepth;
#ifdef DEBUG
PRInt32 mSpansAllocated, mSpansFreed;
PRInt32 mFramesAllocated, mFramesFreed;
#endif
nsresult NewPerFrameData(PerFrameData** aResult);
nsresult NewPerSpanData(PerSpanData** aResult);
void FreeSpan(PerSpanData* psd);
PRBool InBlockContext() const {
return mSpanDepth == 0;
}