Bug 654002 - Remove frame continuations iteratively, not recursively. r=roc
☠☠ backed out by 12b5e82f6ffd ☠ ☠
authorMats Palmgren <matspal@gmail.com>
Thu, 23 Jun 2011 01:16:00 +0200
changeset 71591 3e54c496db92d1199306da1131ba105cfdcdb510
parent 71590 00a5700edf6b31505fbfd676ea9ee410f886ac2c
child 71592 8b5646a07963004d5fb5ae969b7dbdf0087488ce
push id20570
push usermlamouri@mozilla.com
push dateThu, 23 Jun 2011 14:46:06 +0000
treeherdermozilla-central@3e54c496db92 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs654002
milestone7.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 654002 - Remove frame continuations iteratively, not recursively. r=roc
layout/generic/nsContainerFrame.cpp
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -214,43 +214,46 @@ nsContainerFrame::RemoveFrame(nsIAtom*  
     // the line the brFrame was on can attempt to pull up any frames
     // that can fit from lines below it.
     PRBool generateReflowCommand = PR_TRUE;
 #ifdef IBMBIDI
     if (nsGkAtoms::nextBidi == aListName) {
       generateReflowCommand = PR_FALSE;
     }
 #endif
-    nsContainerFrame* parent = static_cast<nsContainerFrame*>(aOldFrame->GetParent());
     while (aOldFrame) {
+      nsContainerFrame* parent =
+        static_cast<nsContainerFrame*>(aOldFrame->GetParent());
       // When the parent is an inline frame we have a simple task - just
       // remove the frame from its parents list and generate a reflow
       // command.
       nsIFrame* oldFrameNextContinuation = aOldFrame->GetNextContinuation();
       //XXXfr probably should use StealFrame here. I'm not sure if we need to
       //      check the overflow lists atm, but we'll need a prescontext lookup
       //      for overflow containers once we can split abspos elements with
       //      inline containing blocks.
       if (parent == this) {
         if (!parent->mFrames.DestroyFrameIfPresent(aOldFrame)) {
           // Try to remove it from our overflow list, if we have one.
           // The simplest way is to reuse StealFrame.
           StealFrame(PresContext(), aOldFrame, PR_TRUE);
           aOldFrame->Destroy();
         }
       } else {
-        // This recursive call takes care of all continuations after aOldFrame,
-        // so we don't need to loop anymore.
-        parent->RemoveFrame(nsnull, aOldFrame);
-        break;
+        // We don't want to simply make a recursive call here because with
+        // thousands of continuations it would exhaust the stack.  Instead,
+        // unhook aOldFrame from the continuation chain, destroy it, and
+        // continue the loop.
+        if (oldFrameNextContinuation) {
+          oldFrameNextContinuation->SetPrevContinuation(nsnull);
+          aOldFrame->SetNextContinuation(nsnull);
+        }
+        parent->RemoveFrame(aListName, aOldFrame);
       }
       aOldFrame = oldFrameNextContinuation;
-      if (aOldFrame) {
-        parent = static_cast<nsContainerFrame*>(aOldFrame->GetParent());
-      }
     }
 
     if (generateReflowCommand) {
       PresContext()->PresShell()->
         FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                          NS_FRAME_HAS_DIRTY_CHILDREN);
     }
   }