Bug 654002 - Remove frame continuations iteratively, not recursively. r=roc
☠☠ backed out by 8c598532de9f ☠ ☠
authorMats Palmgren <matspal@gmail.com>
Thu, 23 Jun 2011 01:16:00 +0200
changeset 71581 bc0b2201ca8594d96aec985b9ad33ec98e84f6ba
parent 71580 7bb02cc447e0145c73cf23bc5193d7742d80a7cd
child 71582 5544f74c84b96fde258b9244664c20250599e135
push id20566
push usermlamouri@mozilla.com
push dateThu, 23 Jun 2011 09:20:24 +0000
treeherdermozilla-central@c70b05ca6e88 [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);
     }
   }