Backing out patch for 317278 due to Tp regression

This commit is contained in:
roc+%cs.cmu.edu 2006-06-19 01:29:07 +00:00
Родитель 5053e9f8ff
Коммит 5f461b2af4
6 изменённых файлов: 76 добавлений и 210 удалений

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

@ -3756,6 +3756,12 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
return rv;
}
#define LINE_REFLOW_OK 0
#define LINE_REFLOW_STOP 1
#define LINE_REFLOW_REDO 2
// a frame was complete, but truncated and not at the top of a page
#define LINE_REFLOW_TRUNCATED 3
nsresult
nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
line_iterator aLine,
@ -3769,64 +3775,45 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
#ifdef DEBUG
PRInt32 spins = 0;
#endif
LineReflowStatus lineReflowStatus = LINE_REFLOW_REDO_NEXT_BAND;
PRBool movedPastFloat = PR_FALSE;
PRUint8 lineReflowStatus = LINE_REFLOW_REDO;
PRBool didRedo = PR_FALSE;
do {
PRBool allowPullUp = PR_TRUE;
do {
aState.mReflowState.mSpaceManager->PushState();
// 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();
if (LINE_REFLOW_REDO == lineReflowStatus) {
didRedo = PR_TRUE;
}
// 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,
allowPullUp);
lineLayout.EndLineReflow();
if (LINE_REFLOW_REDO_NO_PULL == lineReflowStatus ||
LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus) {
// restore the space manager state
aState.mReflowState.mSpaceManager->PopState();
// Clear out below-current-line-floats
aState.mBelowCurrentLineFloats.DeleteAll();
} else {
// We succeeded, so pop the saved state off the space manager
// without restoring it
aState.mReflowState.mSpaceManager->DiscardState();
}
#ifdef DEBUG
spins++;
if (1000 == spins) {
ListTag(stdout);
printf(": yikes! spinning on a line over 1000 times!\n");
NS_ABORT();
}
spins++;
if (1000 == spins) {
ListTag(stdout);
printf(": yikes! spinning on a line over 1000 times!\n");
NS_ABORT();
}
#endif
// Don't allow pullup on a subsequent LINE_REFLOW_REDO_NO_PULL pass
allowPullUp = PR_FALSE;
} while (NS_SUCCEEDED(rv) && LINE_REFLOW_REDO_NO_PULL == lineReflowStatus);
} while (NS_SUCCEEDED(rv) && LINE_REFLOW_REDO == lineReflowStatus);
if (LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus) {
movedPastFloat = PR_TRUE;
}
} while (NS_SUCCEEDED(rv) && LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus);
// If we did at least one REDO_FOR_FLOAT, then the line did not fit next to some float.
// If we did at least one REDO, then the line did not fit next to some float.
// Mark it as impacted by a float, even if it no longer is next to a float.
if (movedPastFloat) {
if (didRedo) {
aLine->SetLineIsImpactedByFloat(PR_TRUE);
}
@ -3857,10 +3844,9 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
line_iterator aLine,
PRBool* aKeepReflowGoing,
LineReflowStatus* aLineReflowStatus,
PRUint8* aLineReflowStatus,
PRBool aUpdateMaximumWidth,
PRBool aDamageDirtyArea,
PRBool aAllowPullUp)
PRBool aDamageDirtyArea)
{
// Forget all of the floats on the line
aLine->FreeFloats(aState.mFloatCacheFreeList);
@ -3910,7 +3896,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// Reflow the frames that are already on the line first
nsresult rv = NS_OK;
LineReflowStatus lineReflowStatus = LINE_REFLOW_OK;
PRUint8 lineReflowStatus = LINE_REFLOW_OK;
PRInt32 i;
nsIFrame* frame = aLine->mFirstChild;
aLine->SetHasPercentageChild(PR_FALSE); // To be set by ReflowInlineFrame below
@ -3957,7 +3943,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
}
// Don't pull up new frames into lines with continuation placeholders
if (!isContinuingPlaceholders && aAllowPullUp) {
if (!isContinuingPlaceholders) {
// Pull frames and reflow them until we can't
while (LINE_REFLOW_OK == lineReflowStatus) {
rv = PullFrame(aState, aLine, aDamageDirtyArea, frame);
@ -3989,7 +3975,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
}
}
if (LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus) {
if (LINE_REFLOW_REDO == lineReflowStatus) {
// This happens only when we have a line that is impacted by
// floats and the first element in the line doesn't fit with
// the floats.
@ -4001,6 +3987,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aState.mAvailSpaceRect.height,
"unconstrained height on totally empty line");
if (aState.mAvailSpaceRect.height > 0) {
aState.mY += aState.mAvailSpaceRect.height;
} else {
@ -4033,13 +4020,6 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// push the line and return now instead of later on after we are
// past the float.
}
else if (LINE_REFLOW_REDO_NO_PULL == lineReflowStatus) {
// We don't want to advance by the bottom margin anymore (we did it
// once at the beginning of this function, which will just be called
// again), and we certainly don't want to go back if it's negative
// (infinite loop, bug 153429).
aState.mPrevBottomMargin.Zero();
}
else if (LINE_REFLOW_TRUNCATED != lineReflowStatus) {
// If we are propagating out a break-before status then there is
// no point in placing the line.
@ -4067,9 +4047,9 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
line_iterator aLine,
nsIFrame* aFrame,
LineReflowStatus* aLineReflowStatus)
PRUint8* aLineReflowStatus)
{
NS_ENSURE_ARG_POINTER(aFrame);
NS_ENSURE_ARG_POINTER(aFrame);
*aLineReflowStatus = LINE_REFLOW_OK;
@ -4162,12 +4142,12 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
// be trying to place content where there's no room (e.g. on a
// line with wide floats). Inform the caller to reflow the
// line after skipping past a float.
*aLineReflowStatus = LINE_REFLOW_REDO_NEXT_BAND;
*aLineReflowStatus = LINE_REFLOW_REDO;
}
else {
// It's not the first child on this line so go ahead and split
// the line. We will see the frame again on the next-line.
rv = SplitLine(aState, aLineLayout, aLine, aFrame, aLineReflowStatus);
rv = SplitLine(aState, aLineLayout, aLine, aFrame);
if (NS_FAILED(rv)) {
return rv;
}
@ -4210,7 +4190,7 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
}
// Split line, but after the frame just reflowed
rv = SplitLine(aState, aLineLayout, aLine, aFrame->GetNextSibling(), aLineReflowStatus);
rv = SplitLine(aState, aLineLayout, aLine, aFrame->GetNextSibling());
if (NS_FAILED(rv)) {
return rv;
}
@ -4260,7 +4240,7 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
if (splitLine) {
// Split line after the current frame
*aLineReflowStatus = LINE_REFLOW_STOP;
rv = SplitLine(aState, aLineLayout, aLine, aFrame->GetNextSibling(), aLineReflowStatus);
rv = SplitLine(aState, aLineLayout, aLine, aFrame->GetNextSibling());
if (NS_FAILED(rv)) {
return rv;
}
@ -4342,35 +4322,11 @@ nsBlockFrame::SplitPlaceholder(nsBlockReflowState& aState,
return NS_OK;
}
static nsFloatCache*
GetLastFloat(nsLineBox* aLine)
{
nsFloatCache* fc = aLine->GetFirstFloat();
while (fc && fc->Next()) {
fc = fc->Next();
}
return fc;
}
static PRBool
CheckPlaceholderInLine(nsIFrame* aBlock, nsLineBox* aLine, nsFloatCache* aFC)
{
if (!aFC)
return PR_TRUE;
for (nsIFrame* f = aFC->mPlaceholder; f; f = f->GetParent()) {
if (f->GetParent() == aBlock)
return aLine->Contains(f);
}
NS_ASSERTION(PR_FALSE, "aBlock is not an ancestor of aFrame!");
return PR_TRUE;
}
nsresult
nsBlockFrame::SplitLine(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
line_iterator aLine,
nsIFrame* aFrame,
LineReflowStatus* aLineReflowStatus)
nsIFrame* aFrame)
{
NS_ABORT_IF_FALSE(aLine->IsInline(), "illegal SplitLine on block line");
@ -4417,17 +4373,6 @@ nsBlockFrame::SplitLine(nsBlockReflowState& aState,
// Let line layout know that some frames are no longer part of its
// state.
aLineLayout.SplitLineTo(aLine->GetChildCount());
// If floats have been placed whose placeholders have been pushed to the new
// line, we need to reflow the old line again. We don't want to look at the
// frames in the new line, because as a large paragraph is laid out the
// we'd get O(N^2) performance. So instead we just check that the last
// float and the last below-current-line float are still in aLine.
if (!CheckPlaceholderInLine(this, aLine, GetLastFloat(aLine)) ||
!CheckPlaceholderInLine(this, aLine, aState.mBelowCurrentLineFloats.Tail())) {
*aLineReflowStatus = LINE_REFLOW_REDO_NO_PULL;
}
#ifdef DEBUG
VerifyLines(PR_TRUE);
#endif

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

@ -52,24 +52,6 @@
#include "nsCSSPseudoElements.h"
#include "nsStyleSet.h"
enum LineReflowStatus {
// The line was completely reflowed and fit in available width, and we should
// try to pull up content from the next line if possible.
LINE_REFLOW_OK,
// The line was completely reflowed and fit in available width, but we should
// not try to pull up content from the next line.
LINE_REFLOW_STOP,
// We need to reflow the line again at its current vertical position. The
// new reflow should not try to pull up any frames from the next line.
LINE_REFLOW_REDO_NO_PULL,
// We need to reflow the line again at a lower vertical postion where there
// may be more horizontal space due to different float configuration.
LINE_REFLOW_REDO_NEXT_BAND,
// The line did not fit in the available vertical space. Try pushing it to
// the next page or column if it's not the first line on the current page/column.
LINE_REFLOW_TRUNCATED
};
class nsBlockReflowState;
class nsBulletFrame;
class nsLineBox;
@ -484,16 +466,15 @@ protected:
nsLineLayout& aLineLayout,
line_iterator aLine,
PRBool* aKeepReflowGoing,
LineReflowStatus* aLineReflowStatus,
PRUint8* aLineReflowStatus,
PRBool aUpdateMaximumWidth,
PRBool aDamageDirtyArea,
PRBool aAllowPullUp);
PRBool aDamageDirtyArea);
nsresult ReflowInlineFrame(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
line_iterator aLine,
nsIFrame* aFrame,
LineReflowStatus* aLineReflowStatus);
PRUint8* aLineReflowStatus);
// An incomplete aReflowStatus indicates the float should be split
// but only if the available height is constrained.
@ -520,8 +501,7 @@ protected:
nsresult SplitLine(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
line_iterator aLine,
nsIFrame* aFrame,
LineReflowStatus* aLineReflowStatus);
nsIFrame* aFrame);
nsresult PullFrame(nsBlockReflowState& aState,
line_iterator aLine,

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

@ -1102,7 +1102,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
* Place below-current-line floats.
*/
PRBool
nsBlockReflowState::PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aList, PRBool aForceFit)
nsBlockReflowState::PlaceBelowCurrentLineFloats(nsFloatCacheList& aList, PRBool aForceFit)
{
nsFloatCache* fc = aList.Head();
while (fc) {

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

@ -99,7 +99,7 @@ public:
PRBool* aIsLeftFloat,
nsReflowStatus& aReflowStatus,
PRBool aForceFit);
PRBool PlaceBelowCurrentLineFloats(nsFloatCacheFreeList& aFloats, PRBool aForceFit);
PRBool PlaceBelowCurrentLineFloats(nsFloatCacheList& aFloats, PRBool aForceFit);
// Returns the first coordinate >= aY that clears the
// indicated floats.

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

@ -875,20 +875,14 @@ nsFloatCacheList::nsFloatCacheList() :
nsFloatCacheList::~nsFloatCacheList()
{
DeleteAll();
MOZ_COUNT_DTOR(nsFloatCacheList);
}
void
nsFloatCacheList::DeleteAll()
{
nsFloatCache* c = mHead;
while (c) {
nsFloatCache* next = c->Next();
delete c;
c = next;
nsFloatCache* fc = mHead;
while (fc) {
nsFloatCache* next = fc->mNext;
delete fc;
fc = next;
}
mHead = nsnull;
MOZ_COUNT_DTOR(nsFloatCacheList);
}
nsFloatCache*
@ -935,24 +929,17 @@ nsFloatCacheList::Find(nsIFrame* aOutOfFlowFrame)
return fc;
}
nsFloatCache*
nsFloatCacheList::RemoveAndReturnPrev(nsFloatCache* aElement)
void
nsFloatCacheList::Remove(nsFloatCache* aElement)
{
NS_ASSERTION(!aElement->mNext, "Can only remove a singleton element");
nsFloatCache* fc = mHead;
nsFloatCache* prev = nsnull;
while (fc) {
nsFloatCache** fcp = &mHead;
nsFloatCache* fc;
while (nsnull != (fc = *fcp)) {
if (fc == aElement) {
if (prev) {
prev->mNext = fc->mNext;
} else {
mHead = fc->mNext;
}
return prev;
*fcp = fc->mNext;
break;
}
prev = fc;
fc = fc->mNext;
fcp = &fc->mNext;
}
}
@ -988,22 +975,6 @@ nsFloatCacheFreeList::Append(nsFloatCacheList& aList)
aList.mHead = nsnull;
}
void
nsFloatCacheFreeList::Remove(nsFloatCache* aElement)
{
nsFloatCache* prev = nsFloatCacheList::RemoveAndReturnPrev(aElement);
if (mTail == aElement) {
mTail = prev;
}
}
void
nsFloatCacheFreeList::DeleteAll()
{
nsFloatCacheList::DeleteAll();
mTail = nsnull;
}
nsFloatCache*
nsFloatCacheFreeList::Alloc()
{

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

@ -120,14 +120,12 @@ public:
nsFloatCache* Tail() const;
void DeleteAll();
nsFloatCache* Find(nsIFrame* aOutOfFlowFrame);
// Remove a nsFloatCache from this list. Deleting this nsFloatCache
// becomes the caller's responsibility.
void Remove(nsFloatCache* aElement) { RemoveAndReturnPrev(aElement); }
void Remove(nsFloatCache* aElement);
// Steal away aList's nsFloatCache objects and put them in this
// list. aList must not be empty.
void Append(nsFloatCacheFreeList& aList);
@ -135,18 +133,12 @@ public:
protected:
nsFloatCache* mHead;
// Remove a nsFloatCache from this list. Deleting this nsFloatCache
// becomes the caller's responsibility. Returns the nsFloatCache that was
// before aElement, or nsnull if aElement was the first.
nsFloatCache* RemoveAndReturnPrev(nsFloatCache* aElement);
friend class nsFloatCacheFreeList;
};
//---------------------------------------
// Like nsFloatCacheList, but with fast access to the tail
class nsFloatCacheFreeList : private nsFloatCacheList {
class nsFloatCacheFreeList : public nsFloatCacheList {
public:
#ifdef NS_BUILD_REFCNT_LOGGING
nsFloatCacheFreeList();
@ -156,37 +148,15 @@ public:
~nsFloatCacheFreeList() { }
#endif
// Reimplement trivial functions
PRBool IsEmpty() const {
return nsnull == mHead;
}
nsFloatCache* Head() const {
return mHead;
}
nsFloatCache* Tail() const {
return mTail;
}
PRBool NotEmpty() const {
return nsnull != mHead;
}
void DeleteAll();
// Steal away aList's nsFloatCache objects and put them on this
// free-list. aList must not be empty.
void Append(nsFloatCacheList& aList);
void Append(nsFloatCache* aFloatCache);
void Remove(nsFloatCache* aElement);
// Remove an nsFloatCache object from this list and return it, or create
// a new one if this one is empty;
// Allocate a new nsFloatCache object
nsFloatCache* Alloc();
protected:
nsFloatCache* mTail;