Backed out changeset 6a452e522e07 - Boris Zbarsky – Bug 67752. Implement interruptible reflow. r=roc,dbaron - because of apparent Tp hangs.

This commit is contained in:
Joe Drew
2009-04-21 23:02:17 -04:00
parent 600528e80b
commit 659abece3b
37 changed files with 147 additions and 823 deletions

View File

@@ -1122,20 +1122,12 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext,
// in that situation --- what we think is our "new size"
// will not be our real new size. This also happens to be more efficient.
if (mAbsoluteContainer.HasAbsoluteFrames()) {
PRBool haveInterrupt = aPresContext->HasPendingInterrupt();
if (aReflowState.WillReflowAgainForClearance() ||
haveInterrupt) {
if (aReflowState.WillReflowAgainForClearance()) {
// Make sure that when we reflow again we'll actually reflow all the abs
// pos frames that might conceivably depend on our size (or all of them,
// if we're dirty right now and interrupted; in that case we also need
// to mark them all with NS_FRAME_IS_DIRTY). Sadly, we can't do much
// better than that, because we don't really know what our size will be,
// and it might in fact not change on the followup reflow!
if (haveInterrupt && (GetStateBits() & NS_FRAME_IS_DIRTY)) {
mAbsoluteContainer.MarkAllFramesDirty();
} else {
mAbsoluteContainer.MarkSizeDependentFramesDirty();
}
// pos frames that might conceivably depend on our size. Sadly, we can't
// do much better than that, because we don't really know what our size
// will be, and it might in fact not change on the followup reflow!
mAbsoluteContainer.MarkSizeDependentFramesDirty();
} else {
nsRect childBounds;
nsSize containingBlockSize =
@@ -2024,18 +2016,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
}
DumpLine(aState, line, deltaY, -1);
if (aState.mPresContext->CheckForInterrupt(this)) {
willReflowAgain = PR_TRUE;
// Another option here might be to leave |line| clean if
// !HasPendingInterrupt() before the CheckForInterrupt() call, since in
// that case the line really did reflow as it should have. Not sure
// whether that would be safe, so doing this for now instead. Also not
// sure whether we really want to mark all lines dirty after an
// interrupt, but until we get better at propagating float damage we
// really do need to do it this way; see comments inside MarkLineDirty.
MarkLineDirtyForInterrupt(line);
}
}
// Handle BR-clearance from the last line of the block
@@ -2057,9 +2037,8 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
if (repositionViews)
::PlaceFrameView(this);
// We can skip trying to pull up the next line if our height is constrained
// (so we can report being incomplete) and there is no next in flow or we
// were told not to or we know it will be futile, i.e.,
// We can skip trying to pull up the next line if there is no next
// in flow or we were told not to or we know it will be futile, i.e.,
// -- the next in flow is not changing
// -- and we cannot have added more space for its first line to be
// pulled up into,
@@ -2068,10 +2047,8 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// didn't change)
// -- my chain of next-in-flows either has no first line, or its first
// line isn't dirty.
PRBool heightConstrained =
aState.mReflowState.availableHeight != NS_UNCONSTRAINEDSIZE;
PRBool skipPull = willReflowAgain && heightConstrained;
if (!skipPull && heightConstrained && aState.mNextInFlow &&
PRBool skipPull = willReflowAgain;
if (aState.mNextInFlow &&
(aState.mReflowState.mFlags.mNextInFlowUntouched &&
!lastLineMovedUp &&
!(GetStateBits() & NS_FRAME_IS_DIRTY) &&
@@ -2090,18 +2067,14 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
// (First, see if there is such a line, and second, see if it's clean)
if (!bifLineIter.Next() ||
!bifLineIter.GetLine()->IsDirty()) {
if (IS_TRUE_OVERFLOW_CONTAINER(aState.mNextInFlow))
NS_FRAME_SET_OVERFLOW_INCOMPLETE(aState.mReflowStatus);
else
NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
skipPull=PR_TRUE;
}
}
}
if (skipPull && aState.mNextInFlow) {
NS_ASSERTION(heightConstrained, "Height should be constrained here\n");
if (IS_TRUE_OVERFLOW_CONTAINER(aState.mNextInFlow))
NS_FRAME_SET_OVERFLOW_INCOMPLETE(aState.mReflowStatus);
else
NS_FRAME_SET_INCOMPLETE(aState.mReflowStatus);
}
if (!skipPull && aState.mNextInFlow) {
// Pull data from a next-in-flow if there's still room for more
@@ -2184,38 +2157,28 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
AutoNoisyIndenter indent2(gNoisyReflow);
#endif
if (aState.mPresContext->HasPendingInterrupt()) {
MarkLineDirtyForInterrupt(line);
} else {
// Now reflow it and any lines that it makes during it's reflow
// (we have to loop here because reflowing the line may case a new
// line to be created; see SplitLine's callers for examples of
// when this happens).
while (line != end_lines()) {
rv = ReflowLine(aState, line, &keepGoing);
NS_ENSURE_SUCCESS(rv, rv);
DumpLine(aState, line, deltaY, -1);
if (!keepGoing) {
if (0 == line->GetChildCount()) {
DeleteLine(aState, line, line_end);
}
break;
// Now reflow it and any lines that it makes during it's reflow
// (we have to loop here because reflowing the line may case a new
// line to be created; see SplitLine's callers for examples of
// when this happens).
while (line != end_lines()) {
rv = ReflowLine(aState, line, &keepGoing);
NS_ENSURE_SUCCESS(rv, rv);
DumpLine(aState, line, deltaY, -1);
if (!keepGoing) {
if (0 == line->GetChildCount()) {
DeleteLine(aState, line, line_end);
}
if (LineHasClear(line.get())) {
foundAnyClears = PR_TRUE;
}
if (aState.mPresContext->CheckForInterrupt(this)) {
willReflowAgain = PR_TRUE;
MarkLineDirtyForInterrupt(line);
break;
}
// If this is an inline frame then its time to stop
++line;
aState.AdvanceToNextLine();
break;
}
if (LineHasClear(line.get())) {
foundAnyClears = PR_TRUE;
}
// If this is an inline frame then its time to stop
++line;
aState.AdvanceToNextLine();
}
}
@@ -2253,54 +2216,6 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
return rv;
}
static void MarkAllDescendantLinesDirty(nsBlockFrame* aBlock)
{
nsLineList::iterator line = aBlock->begin_lines();
nsLineList::iterator endLine = aBlock->end_lines();
while (line != endLine) {
if (line->IsBlock()) {
nsIFrame* f = line->mFirstChild;
nsBlockFrame* bf = nsLayoutUtils::GetAsBlock(f);
if (bf) {
MarkAllDescendantLinesDirty(bf);
}
}
line->MarkDirty();
++line;
}
}
void
nsBlockFrame::MarkLineDirtyForInterrupt(nsLineBox* aLine)
{
aLine->MarkDirty();
// Just checking NS_FRAME_IS_DIRTY is ok, because we've already
// marked the lines that need to be marked dirty based on our
// vertical resize stuff. So we'll definitely reflow all those kids;
// the only question is how they should behave.
if (GetStateBits() & NS_FRAME_IS_DIRTY) {
// Mark all our child frames dirty so we make sure to reflow them
// later.
PRInt32 n = aLine->GetChildCount();
for (nsIFrame* f = aLine->mFirstChild; n > 0;
f = f->GetNextSibling(), --n) {
f->AddStateBits(NS_FRAME_IS_DIRTY);
}
} else {
// Dirty all the descendant lines of block kids to handle float damage,
// since our nsFloatManager will go away by the next time we're reflowing.
// XXXbz Can we do something more like what PropagateFloatDamage does?
// Would need to sort out the exact business with mBlockDelta for that....
// This marks way too much dirty. If we ever make this better, revisit
// which lines we mark dirty in the interrupt case in ReflowDirtyLines.
nsBlockFrame* bf = nsLayoutUtils::GetAsBlock(aLine->mFirstChild);
if (bf) {
MarkAllDescendantLinesDirty(bf);
}
}
}
void
nsBlockFrame::DeleteLine(nsBlockReflowState& aState,
nsLineList::iterator aLine,
@@ -5043,6 +4958,23 @@ nsBlockFrame::RemoveFloat(nsIFrame* aFloat) {
return line_end;
}
static void MarkAllDescendantLinesDirty(nsBlockFrame* aBlock)
{
nsLineList::iterator line = aBlock->begin_lines();
nsLineList::iterator endLine = aBlock->end_lines();
while (line != endLine) {
if (line->IsBlock()) {
nsIFrame* f = line->mFirstChild;
nsBlockFrame* bf = nsLayoutUtils::GetAsBlock(f);
if (bf) {
MarkAllDescendantLinesDirty(bf);
}
}
line->MarkDirty();
++line;
}
}
static void MarkSameFloatManagerLinesDirty(nsBlockFrame* aBlock)
{
nsBlockFrame* blockWithFloatMgr = aBlock;