Bug 896138 patch 4: Move restyle management code from nsCSSFrameConstructor to RestyleManager. r=heycam
authorL. David Baron <dbaron@dbaron.org>
Sat, 20 Jul 2013 12:14:25 -0700
changeset 151660 b960146cc1edfb165d358503c0265802e393e6a5
parent 151659 48769eacc0b8de9d569c7751e9ec8cc6b0390140
child 151661 108208f9f817981e57eb229803d50cf6f46ada8a
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs896138
milestone25.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 896138 patch 4: Move restyle management code from nsCSSFrameConstructor to RestyleManager. r=heycam This moves restyling management out of nsCSSFrameConstructor (thus reducing its size), and keeps the restyling code closer together. This is the first of two big chunks of code moved in this patch series. A later patch in this series will move related code from nsFrameManager into the same destination file.
editor/libeditor/html/nsHTMLAnonymousUtils.cpp
layout/base/RestyleManager.cpp
layout/base/RestyleManager.h
layout/base/RestyleTracker.cpp
layout/base/RestyleTracker.h
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
layout/base/nsLayoutUtils.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/base/nsPresShell.cpp
layout/base/nsRefreshDriver.cpp
layout/generic/nsImageMap.cpp
layout/mathml/nsMathMLTokenFrame.cpp
layout/mathml/nsMathMLmtableFrame.cpp
layout/printing/nsPrintEngine.cpp
layout/style/AnimationCommon.cpp
layout/style/nsHTMLStyleSheet.cpp
layout/style/nsTransitionManager.cpp
layout/svg/nsSVGContainerFrame.cpp
layout/svg/nsSVGEffects.cpp
--- a/editor/libeditor/html/nsHTMLAnonymousUtils.cpp
+++ b/editor/libeditor/html/nsHTMLAnonymousUtils.cpp
@@ -231,17 +231,17 @@ nsHTMLEditor::DeleteRefToAnonymousNode(n
         if (docObserver) {
           // Call BeginUpdate() so that the nsCSSFrameConstructor/PresShell
           // knows we're messing with the frame tree.
           nsCOMPtr<nsIDocument> document = GetDocument();
           if (document)
             docObserver->BeginUpdate(document, UPDATE_CONTENT_MODEL);
 
           // XXX This is wrong (bug 439258).  Once it's fixed, the NS_WARNING
-          // in nsCSSFrameConstructor::RestyleForRemove should be changed back
+          // in RestyleManager::RestyleForRemove should be changed back
           // to an assertion.
           docObserver->ContentRemoved(content->GetCurrentDoc(),
                                       aParentContent, content, -1,
                                       content->GetPreviousSibling());
           if (document)
             docObserver->EndUpdate(document, UPDATE_CONTENT_MODEL);
         }
       }
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -4,17 +4,1453 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * Code responsible for managing style changes: tracking what style
  * changes need to happen, scheduling them, and doing them.
  */
 
 #include "RestyleManager.h"
+#include "nsLayoutUtils.h"
+#include "GeckoProfiler.h"
+#include "nsStyleChangeList.h"
+#include "nsStyleUtil.h"
+#include "nsCSSFrameConstructor.h"
+#include "nsSVGEffects.h"
+#include "nsCSSRendering.h"
+#include "nsAnimationManager.h"
+#include "nsTransitionManager.h"
+#include "nsViewManager.h"
+#include "nsRenderingContext.h"
+#include "nsSVGIntegrationUtils.h"
+#include "nsContainerFrame.h"
+#include "nsPlaceholderFrame.h"
+#include "nsViewportFrame.h"
+#include "nsSVGTextFrame2.h"
+#include "nsSVGTextPathFrame.h"
+#include "nsIRootBox.h"
+#include "nsIDOMMutationEvent.h"
 
 namespace mozilla {
 
 RestyleManager::RestyleManager(nsPresContext* aPresContext)
   : mPresContext(aPresContext)
+  , mRebuildAllStyleData(false)
+  , mObservingRefreshDriver(false)
+  , mInStyleRefresh(false)
+  , mPromoteReflowsToReframeRoot(false)
+  , mHoverGeneration(0)
+  , mRebuildAllExtraHint(nsChangeHint(0))
+  , mAnimationGeneration(0)
+  , mPendingRestyles(ELEMENT_HAS_PENDING_RESTYLE |
+                     ELEMENT_IS_POTENTIAL_RESTYLE_ROOT)
+  , mPendingAnimationRestyles(ELEMENT_HAS_PENDING_ANIMATION_RESTYLE |
+                              ELEMENT_IS_POTENTIAL_ANIMATION_RESTYLE_ROOT)
 {
+  mPendingRestyles.Init(this);
+  mPendingAnimationRestyles.Init(this);
+}
+
+void
+RestyleManager::NotifyDestroyingFrame(nsIFrame* aFrame)
+{
+  mOverflowChangedTracker.RemoveFrame(aFrame);
+}
+
+#ifdef DEBUG
+  // To ensure that the functions below are only called within
+  // |ApplyRenderingChangeToTree|.
+static bool gInApplyRenderingChangeToTree = false;
+#endif
+
+static void
+DoApplyRenderingChangeToTree(nsIFrame* aFrame,
+                             nsFrameManager* aFrameManager,
+                             nsChangeHint aChange);
+
+/**
+ * Sync views on aFrame and all of aFrame's descendants (following placeholders),
+ * if aChange has nsChangeHint_SyncFrameView.
+ * Calls DoApplyRenderingChangeToTree on all aFrame's out-of-flow descendants
+ * (following placeholders), if aChange has nsChangeHint_RepaintFrame.
+ * aFrame should be some combination of nsChangeHint_SyncFrameView and
+ * nsChangeHint_RepaintFrame and nsChangeHint_UpdateOpacityLayer, nothing else.
+*/
+static void
+SyncViewsAndInvalidateDescendants(nsIFrame* aFrame,
+                                  nsFrameManager* aFrameManager,
+                                  nsChangeHint aChange)
+{
+  NS_PRECONDITION(gInApplyRenderingChangeToTree,
+                  "should only be called within ApplyRenderingChangeToTree");
+  NS_ASSERTION(aChange == (aChange & (nsChangeHint_RepaintFrame |
+                                      nsChangeHint_SyncFrameView |
+                                      nsChangeHint_UpdateOpacityLayer)),
+               "Invalid change flag");
+
+  nsView* view = aFrame->GetView();
+  if (view) {
+    if (aChange & nsChangeHint_SyncFrameView) {
+      nsContainerFrame::SyncFrameViewProperties(aFrame->PresContext(),
+                                                aFrame, nullptr, view);
+    }
+  }
+
+  nsIFrame::ChildListIterator lists(aFrame);
+  for (; !lists.IsDone(); lists.Next()) {
+    nsFrameList::Enumerator childFrames(lists.CurrentList());
+    for (; !childFrames.AtEnd(); childFrames.Next()) {
+      nsIFrame* child = childFrames.get();
+      if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
+        // only do frames that don't have placeholders
+        if (nsGkAtoms::placeholderFrame == child->GetType()) {
+          // do the out-of-flow frame and its continuations
+          nsIFrame* outOfFlowFrame =
+            nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
+          DoApplyRenderingChangeToTree(outOfFlowFrame, aFrameManager,
+                                       aChange);
+        } else if (lists.CurrentID() == nsIFrame::kPopupList) {
+          DoApplyRenderingChangeToTree(child, aFrameManager,
+                                       aChange);
+        } else {  // regular frame
+          SyncViewsAndInvalidateDescendants(child, aFrameManager, aChange);
+        }
+      }
+    }
+  }
+}
+
+/**
+ * To handle nsChangeHint_ChildrenOnlyTransform we must iterate over the child
+ * frames of the SVG frame concerned. This helper function is used to find that
+ * SVG frame when we encounter nsChangeHint_ChildrenOnlyTransform to ensure
+ * that we iterate over the intended children, since sometimes we end up
+ * handling that hint while processing hints for one of the SVG frame's
+ * ancestor frames.
+ *
+ * The reason that we sometimes end up trying to process the hint for an
+ * ancestor of the SVG frame that the hint is intended for is due to the way we
+ * process restyle events. ApplyRenderingChangeToTree adjusts the frame from
+ * the restyled element's principle frame to one of its ancestor frames based
+ * on what nsCSSRendering::FindBackground returns, since the background style
+ * may have been propagated up to an ancestor frame. Processing hints using an
+ * ancestor frame is fine in general, but nsChangeHint_ChildrenOnlyTransform is
+ * a special case since it is intended to update the children of a specific
+ * frame.
+ */
+static nsIFrame*
+GetFrameForChildrenOnlyTransformHint(nsIFrame *aFrame)
+{
+  if (aFrame->GetType() == nsGkAtoms::viewportFrame) {
+    // This happens if the root-<svg> is fixed positioned, in which case we
+    // can't use aFrame->GetContent() to find the primary frame, since
+    // GetContent() returns nullptr for ViewportFrame.
+    aFrame = aFrame->GetFirstPrincipalChild();
+  }
+  // For an nsHTMLScrollFrame, this will get the SVG frame that has the
+  // children-only transforms:
+  aFrame = aFrame->GetContent()->GetPrimaryFrame();
+  if (aFrame->GetType() == nsGkAtoms::svgOuterSVGFrame) {
+    aFrame = aFrame->GetFirstPrincipalChild();
+    NS_ABORT_IF_FALSE(aFrame->GetType() == nsGkAtoms::svgOuterSVGAnonChildFrame,
+                      "Where is the nsSVGOuterSVGFrame's anon child??");
+  }
+  NS_ABORT_IF_FALSE(aFrame->IsFrameOfType(nsIFrame::eSVG |
+                                          nsIFrame::eSVGContainer),
+                    "Children-only transforms only expected on SVG frames");
+  return aFrame;
+}
+
+static void
+DoApplyRenderingChangeToTree(nsIFrame* aFrame,
+                             nsFrameManager* aFrameManager,
+                             nsChangeHint aChange)
+{
+  NS_PRECONDITION(gInApplyRenderingChangeToTree,
+                  "should only be called within ApplyRenderingChangeToTree");
+
+  for ( ; aFrame; aFrame = nsLayoutUtils::GetNextContinuationOrSpecialSibling(aFrame)) {
+    // Invalidate and sync views on all descendant frames, following placeholders.
+    // We don't need to update transforms in SyncViewsAndInvalidateDescendants, because
+    // there can't be any out-of-flows or popups that need to be transformed;
+    // all out-of-flow descendants of the transformed element must also be
+    // descendants of the transformed frame.
+    SyncViewsAndInvalidateDescendants(aFrame, aFrameManager,
+      nsChangeHint(aChange & (nsChangeHint_RepaintFrame |
+                              nsChangeHint_SyncFrameView |
+                              nsChangeHint_UpdateOpacityLayer)));
+    // This must be set to true if the rendering change needs to
+    // invalidate content.  If it's false, a composite-only paint
+    // (empty transaction) will be scheduled.
+    bool needInvalidatingPaint = false;
+
+    // if frame has view, will already be invalidated
+    if (aChange & nsChangeHint_RepaintFrame) {
+      // Note that this whole block will be skipped when painting is suppressed
+      // (due to our caller ApplyRendingChangeToTree() discarding the
+      // nsChangeHint_RepaintFrame hint).  If you add handling for any other
+      // hints within this block, be sure that they too should be ignored when
+      // painting is suppressed.
+      needInvalidatingPaint = true;
+      aFrame->InvalidateFrameSubtree();
+      if (aChange & nsChangeHint_UpdateEffects &&
+          aFrame->IsFrameOfType(nsIFrame::eSVG) &&
+          !(aFrame->GetStateBits() & NS_STATE_IS_OUTER_SVG)) {
+        // Need to update our overflow rects:
+        nsSVGUtils::ScheduleReflowSVG(aFrame);
+      }
+    }
+    if (aChange & nsChangeHint_UpdateTextPath) {
+      if (aFrame->GetType() == nsGkAtoms::svgTextPathFrame) {
+        // Invalidate and reflow the entire nsSVGTextFrame:
+        static_cast<nsSVGTextPathFrame*>(aFrame)->NotifyGlyphMetricsChange();
+      } else if (aFrame->IsSVGText()) {
+        // Invalidate and reflow the entire nsSVGTextFrame2:
+        NS_ASSERTION(aFrame->GetContent()->IsSVG(nsGkAtoms::textPath),
+                     "expected frame for a <textPath> element");
+        nsIFrame* text = nsLayoutUtils::GetClosestFrameOfType(
+                                                      aFrame,
+                                                      nsGkAtoms::svgTextFrame2);
+        NS_ASSERTION(text, "expected to find an ancestor nsSVGTextFrame2");
+        static_cast<nsSVGTextFrame2*>(text)->NotifyGlyphMetricsChange();
+      } else {
+        NS_ABORT_IF_FALSE(false, "unexpected frame got "
+                                 "nsChangeHint_UpdateTextPath");
+      }
+    }
+    if (aChange & nsChangeHint_UpdateOpacityLayer) {
+      // FIXME/bug 796697: we can get away with empty transactions for
+      // opacity updates in many cases.
+      needInvalidatingPaint = true;
+      aFrame->MarkLayersActive(nsChangeHint_UpdateOpacityLayer);
+      if (nsSVGIntegrationUtils::UsingEffectsForFrame(aFrame)) {
+        // SVG effects paints the opacity without using
+        // nsDisplayOpacity. We need to invalidate manually.
+        aFrame->InvalidateFrameSubtree();
+      }
+    }
+    if ((aChange & nsChangeHint_UpdateTransformLayer) &&
+        aFrame->IsTransformed()) {
+      aFrame->MarkLayersActive(nsChangeHint_UpdateTransformLayer);
+      // If we're not already going to do an invalidating paint, see
+      // if we can get away with only updating the transform on a
+      // layer for this frame, and not scheduling an invalidating
+      // paint.
+      if (!needInvalidatingPaint) {
+        needInvalidatingPaint |= !aFrame->TryUpdateTransformOnly();
+      }
+    }
+    if (aChange & nsChangeHint_ChildrenOnlyTransform) {
+      needInvalidatingPaint = true;
+      nsIFrame* childFrame =
+        GetFrameForChildrenOnlyTransformHint(aFrame)->GetFirstPrincipalChild();
+      for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
+        childFrame->MarkLayersActive(nsChangeHint_UpdateTransformLayer);
+      }
+    }
+    aFrame->SchedulePaint(needInvalidatingPaint ?
+                          nsIFrame::PAINT_DEFAULT :
+                          nsIFrame::PAINT_COMPOSITE_ONLY);
+  }
+}
+
+static void
+ApplyRenderingChangeToTree(nsPresContext* aPresContext,
+                           nsIFrame* aFrame,
+                           nsChangeHint aChange)
+{
+  // We check StyleDisplay()->HasTransform() in addition to checking
+  // IsTransformed() since we can get here for some frames that don't support
+  // CSS transforms.
+  NS_ASSERTION(!(aChange & nsChangeHint_UpdateTransformLayer) ||
+               aFrame->IsTransformed() ||
+               aFrame->StyleDisplay()->HasTransformStyle(),
+               "Unexpected UpdateTransformLayer hint");
+
+  nsIPresShell *shell = aPresContext->PresShell();
+  if (shell->IsPaintingSuppressed()) {
+    // Don't allow synchronous rendering changes when painting is turned off.
+    aChange = NS_SubtractHint(aChange, nsChangeHint_RepaintFrame);
+    if (!aChange) {
+      return;
+    }
+  }
+
+  // If the frame's background is propagated to an ancestor, walk up to
+  // that ancestor.
+  nsStyleContext *bgSC;
+  while (!nsCSSRendering::FindBackground(aFrame, &bgSC)) {
+    aFrame = aFrame->GetParent();
+    NS_ASSERTION(aFrame, "root frame must paint");
+  }
+
+  // Trigger rendering updates by damaging this frame and any
+  // continuations of this frame.
+
+  // XXX this needs to detect the need for a view due to an opacity change and deal with it...
+
+#ifdef DEBUG
+  gInApplyRenderingChangeToTree = true;
+#endif
+  DoApplyRenderingChangeToTree(aFrame, shell->FrameManager(), aChange);
+#ifdef DEBUG
+  gInApplyRenderingChangeToTree = false;
+#endif
+}
+
+nsresult
+RestyleManager::StyleChangeReflow(nsIFrame* aFrame, nsChangeHint aHint)
+{
+  // If the frame hasn't even received an initial reflow, then don't
+  // send it a style-change reflow!
+  if (aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)
+    return NS_OK;
+
+  nsIPresShell::IntrinsicDirty dirtyType;
+  if (aHint & nsChangeHint_ClearDescendantIntrinsics) {
+    NS_ASSERTION(aHint & nsChangeHint_ClearAncestorIntrinsics,
+                 "Please read the comments in nsChangeHint.h");
+    dirtyType = nsIPresShell::eStyleChange;
+  } else if (aHint & nsChangeHint_ClearAncestorIntrinsics) {
+    dirtyType = nsIPresShell::eTreeChange;
+  } else {
+    dirtyType = nsIPresShell::eResize;
+  }
+
+  nsFrameState dirtyBits;
+  if (aHint & nsChangeHint_NeedDirtyReflow) {
+    dirtyBits = NS_FRAME_IS_DIRTY;
+  } else {
+    dirtyBits = NS_FRAME_HAS_DIRTY_CHILDREN;
+  }
+
+  do {
+    mPresContext->PresShell()->FrameNeedsReflow(aFrame, dirtyType, dirtyBits);
+    aFrame = nsLayoutUtils::GetNextContinuationOrSpecialSibling(aFrame);
+  } while (aFrame);
+
+  return NS_OK;
+}
+
+NS_DECLARE_FRAME_PROPERTY(ChangeListProperty, nullptr)
+
+/**
+ * Return true if aFrame's subtree has placeholders for out-of-flow content
+ * whose 'position' style's bit in aPositionMask is set.
+ */
+static bool
+FrameHasPositionedPlaceholderDescendants(nsIFrame* aFrame, uint32_t aPositionMask)
+{
+  const nsIFrame::ChildListIDs skip(nsIFrame::kAbsoluteList |
+                                    nsIFrame::kFixedList);
+  for (nsIFrame::ChildListIterator lists(aFrame); !lists.IsDone(); lists.Next()) {
+    if (!skip.Contains(lists.CurrentID())) {
+      for (nsFrameList::Enumerator childFrames(lists.CurrentList());
+           !childFrames.AtEnd(); childFrames.Next()) {
+        nsIFrame* f = childFrames.get();
+        if (f->GetType() == nsGkAtoms::placeholderFrame) {
+          nsIFrame* outOfFlow = nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
+          // If SVG text frames could appear here, they could confuse us since
+          // they ignore their position style ... but they can't.
+          NS_ASSERTION(!outOfFlow->IsSVGText(),
+                       "SVG text frames can't be out of flow");
+          if (aPositionMask & (1 << outOfFlow->StyleDisplay()->mPosition)) {
+            return true;
+          }
+        }
+        if (FrameHasPositionedPlaceholderDescendants(f, aPositionMask)) {
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+}
+
+static bool
+NeedToReframeForAddingOrRemovingTransform(nsIFrame* aFrame)
+{
+  MOZ_STATIC_ASSERT(0 <= NS_STYLE_POSITION_ABSOLUTE &&
+                    NS_STYLE_POSITION_ABSOLUTE < 32, "Style constant out of range");
+  MOZ_STATIC_ASSERT(0 <= NS_STYLE_POSITION_FIXED &&
+                    NS_STYLE_POSITION_FIXED < 32, "Style constant out of range");
+
+  uint32_t positionMask;
+  // Don't call aFrame->IsPositioned here, since that returns true if
+  // the frame already has a transform, and we want to ignore that here
+  if (aFrame->IsAbsolutelyPositioned() ||
+      aFrame->IsRelativelyPositioned()) {
+    // This frame is a container for abs-pos descendants whether or not it
+    // has a transform.
+    // So abs-pos descendants are no problem; we only need to reframe if
+    // we have fixed-pos descendants.
+    positionMask = 1 << NS_STYLE_POSITION_FIXED;
+  } else {
+    // This frame may not be a container for abs-pos descendants already.
+    // So reframe if we have abs-pos or fixed-pos descendants.
+    positionMask = (1 << NS_STYLE_POSITION_FIXED) |
+        (1 << NS_STYLE_POSITION_ABSOLUTE);
+  }
+  for (nsIFrame* f = aFrame; f;
+       f = nsLayoutUtils::GetNextContinuationOrSpecialSibling(f)) {
+    if (FrameHasPositionedPlaceholderDescendants(f, positionMask)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+static nsIFrame*
+FindReflowRootFor(nsIFrame* aFrame)
+{
+  for (nsIFrame* f = aFrame; f; f = f->GetParent()) {
+    if (f->GetStateBits() & NS_FRAME_REFLOW_ROOT) {
+      return f;
+    }
+  }
+  return nullptr;
+}
+
+nsresult
+RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
+{
+  NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
+               "Someone forgot a script blocker");
+  int32_t count = aChangeList.Count();
+  if (!count)
+    return NS_OK;
+
+  PROFILER_LABEL("CSS", "ProcessRestyledFrames");
+
+  // Make sure to not rebuild quote or counter lists while we're
+  // processing restyles
+  FrameConstructor()->BeginUpdate();
+
+  FramePropertyTable* propTable = mPresContext->PropertyTable();
+
+  // Mark frames so that we skip frames that die along the way, bug 123049.
+  // A frame can be in the list multiple times with different hints. Further
+  // optmization is possible if nsStyleChangeList::AppendChange could coalesce
+  int32_t index = count;
+
+  while (0 <= --index) {
+    const nsStyleChangeData* changeData;
+    aChangeList.ChangeAt(index, &changeData);
+    if (changeData->mFrame) {
+      propTable->Set(changeData->mFrame, ChangeListProperty(),
+                     NS_INT32_TO_PTR(1));
+    }
+  }
+
+  index = count;
+
+  while (0 <= --index) {
+    nsIFrame* frame;
+    nsIContent* content;
+    bool didReflowThisFrame = false;
+    nsChangeHint hint;
+    aChangeList.ChangeAt(index, frame, content, hint);
+
+    NS_ASSERTION(!(hint & nsChangeHint_AllReflowHints) ||
+                 (hint & nsChangeHint_NeedReflow),
+                 "Reflow hint bits set without actually asking for a reflow");
+
+    // skip any frame that has been destroyed due to a ripple effect
+    if (frame && !propTable->Get(frame, ChangeListProperty())) {
+      continue;
+    }
+
+    if (frame && frame->GetContent() != content) {
+      // XXXbz this is due to image maps messing with the primary frame of
+      // <area>s.  See bug 135040.  Remove this block once that's fixed.
+      frame = nullptr;
+      if (!(hint & nsChangeHint_ReconstructFrame)) {
+        continue;
+      }
+    }
+
+    if (mPromoteReflowsToReframeRoot &&
+        (hint & (nsChangeHint_ReconstructFrame | nsChangeHint_NeedReflow))) {
+      nsIFrame* reflowRoot = FindReflowRootFor(frame);
+      if (!reflowRoot) {
+        // Reflow root is the viewport. Better reframe the document.
+        // We don't do this for elements which are inside a reflow root --- they
+        // should be OK.
+        nsIContent* root = mPresContext->Document()->GetRootElement();
+        if (root) {
+          NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
+          content = root;
+        }
+      }
+    }
+
+    if ((hint & nsChangeHint_AddOrRemoveTransform) && frame &&
+        !(hint & nsChangeHint_ReconstructFrame)) {
+      if (NeedToReframeForAddingOrRemovingTransform(frame)) {
+        NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
+      } else {
+        // Normally frame construction would set state bits as needed,
+        // but we're not going to reconstruct the frame so we need to set them.
+        // It's because we need to set this state on each affected frame
+        // that we can't coalesce nsChangeHint_AddOrRemoveTransform hints up
+        // to ancestors (i.e. it can't be an inherited change hint).
+        if (frame->IsPositioned()) {
+          // If a transform has been added, we'll be taking this path,
+          // but we may be taking this path even if a transform has been
+          // removed. It's OK to add the bit even if it's not needed.
+          frame->AddStateBits(NS_FRAME_MAY_BE_TRANSFORMED);
+          if (!frame->IsAbsoluteContainer() &&
+              (frame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN)) {
+            frame->MarkAsAbsoluteContainingBlock();
+          }
+        } else {
+          // Don't remove NS_FRAME_MAY_BE_TRANSFORMED since it may still by
+          // transformed by other means. It's OK to have the bit even if it's
+          // not needed.
+          if (frame->IsAbsoluteContainer()) {
+            frame->MarkAsNotAbsoluteContainingBlock();
+          }
+        }
+      }
+    }
+    if (hint & nsChangeHint_ReconstructFrame) {
+      // If we ever start passing true here, be careful of restyles
+      // that involve a reframe and animations.  In particular, if the
+      // restyle we're processing here is an animation restyle, but
+      // the style resolution we will do for the frame construction
+      // happens async when we're not in an animation restyle already,
+      // problems could arise.
+      FrameConstructor()->RecreateFramesForContent(content, false);
+    } else {
+      NS_ASSERTION(frame, "This shouldn't happen");
+
+      if ((frame->GetStateBits() & NS_FRAME_SVG_LAYOUT) &&
+          (frame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
+        // frame does not maintain overflow rects, so avoid calling
+        // FinishAndStoreOverflow on it:
+        hint = NS_SubtractHint(hint,
+                 NS_CombineHint(nsChangeHint_UpdateOverflow,
+                                nsChangeHint_ChildrenOnlyTransform));
+      }
+
+      if (hint & nsChangeHint_UpdateEffects) {
+        nsSVGEffects::UpdateEffects(frame);
+      }
+      if (hint & nsChangeHint_NeedReflow) {
+        StyleChangeReflow(frame, hint);
+        didReflowThisFrame = true;
+      }
+      if (hint & (nsChangeHint_RepaintFrame | nsChangeHint_SyncFrameView |
+                  nsChangeHint_UpdateOpacityLayer | nsChangeHint_UpdateTransformLayer |
+                  nsChangeHint_ChildrenOnlyTransform)) {
+        ApplyRenderingChangeToTree(mPresContext, frame, hint);
+      }
+      if ((hint & nsChangeHint_RecomputePosition) && !didReflowThisFrame) {
+        // It is possible for this to fall back to a reflow
+        if (!RecomputePosition(frame)) {
+          didReflowThisFrame = true;
+        }
+      }
+      NS_ASSERTION(!(hint & nsChangeHint_ChildrenOnlyTransform) ||
+                   (hint & nsChangeHint_UpdateOverflow),
+                   "nsChangeHint_UpdateOverflow should be passed too");
+      if ((hint & nsChangeHint_UpdateOverflow) && !didReflowThisFrame) {
+        if (hint & nsChangeHint_ChildrenOnlyTransform) {
+          // The overflow areas of the child frames need to be updated:
+          nsIFrame* hintFrame = GetFrameForChildrenOnlyTransformHint(frame);
+          nsIFrame* childFrame = hintFrame->GetFirstPrincipalChild();
+          for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
+            NS_ABORT_IF_FALSE(childFrame->IsFrameOfType(nsIFrame::eSVG),
+                              "Not expecting non-SVG children");
+            // If |childFrame| is dirty or has dirty children, we don't bother
+            // updating overflows since that will happen when it's reflowed.
+            if (!(childFrame->GetStateBits() &
+                  (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
+              mOverflowChangedTracker.AddFrame(childFrame);
+            }
+            NS_ASSERTION(!nsLayoutUtils::GetNextContinuationOrSpecialSibling(childFrame),
+                         "SVG frames should not have continuations or special siblings");
+            NS_ASSERTION(childFrame->GetParent() == hintFrame,
+                         "SVG child frame not expected to have different parent");
+          }
+        }
+        // If |frame| is dirty or has dirty children, we don't bother updating
+        // overflows since that will happen when it's reflowed.
+        if (!(frame->GetStateBits() &
+              (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
+          while (frame) {
+            mOverflowChangedTracker.AddFrame(frame);
+
+            frame =
+              nsLayoutUtils::GetNextContinuationOrSpecialSibling(frame);
+          }
+        }
+      }
+      if (hint & nsChangeHint_UpdateCursor) {
+        mPresContext->PresShell()->SynthesizeMouseMove(false);
+      }
+    }
+  }
+
+  FrameConstructor()->EndUpdate();
+
+  // cleanup references and verify the style tree.  Note that the latter needs
+  // to happen once we've processed the whole list, since until then the tree
+  // is not in fact in a consistent state.
+  index = count;
+  while (0 <= --index) {
+    const nsStyleChangeData* changeData;
+    aChangeList.ChangeAt(index, &changeData);
+    if (changeData->mFrame) {
+      propTable->Delete(changeData->mFrame, ChangeListProperty());
+    }
+
+#ifdef DEBUG
+    // reget frame from content since it may have been regenerated...
+    if (changeData->mContent) {
+      if (!nsAnimationManager::ContentOrAncestorHasAnimation(changeData->mContent) &&
+          !nsTransitionManager::ContentOrAncestorHasTransition(changeData->mContent)) {
+        nsIFrame* frame = changeData->mContent->GetPrimaryFrame();
+        if (frame) {
+          FrameConstructor()->DebugVerifyStyleTree(frame);
+        }
+      }
+    } else if (!changeData->mFrame ||
+               changeData->mFrame->GetType() != nsGkAtoms::viewportFrame) {
+      NS_WARNING("Unable to test style tree integrity -- no content node "
+                 "(and not a viewport frame)");
+    }
+#endif
+  }
+
+  aChangeList.Clear();
+  return NS_OK;
+}
+
+void
+RestyleManager::RestyleElement(Element*        aElement,
+                               nsIFrame*       aPrimaryFrame,
+                               nsChangeHint    aMinHint,
+                               RestyleTracker& aRestyleTracker,
+                               bool            aRestyleDescendants)
+{
+  NS_ASSERTION(aPrimaryFrame == aElement->GetPrimaryFrame(),
+               "frame/content mismatch");
+  if (aPrimaryFrame && aPrimaryFrame->GetContent() != aElement) {
+    // XXXbz this is due to image maps messing with the primary frame pointer
+    // of <area>s.  See bug 135040.  We can remove this block once that's fixed.
+    aPrimaryFrame = nullptr;
+  }
+  NS_ASSERTION(!aPrimaryFrame || aPrimaryFrame->GetContent() == aElement,
+               "frame/content mismatch");
+
+  // If we're restyling the root element and there are 'rem' units in
+  // use, handle dynamic changes to the definition of a 'rem' here.
+  if (mPresContext->UsesRootEMUnits() && aPrimaryFrame) {
+    nsStyleContext *oldContext = aPrimaryFrame->StyleContext();
+    if (!oldContext->GetParent()) { // check that we're the root element
+      nsRefPtr<nsStyleContext> newContext = mPresContext->StyleSet()->
+        ResolveStyleFor(aElement, nullptr /* == oldContext->GetParent() */);
+      if (oldContext->StyleFont()->mFont.size !=
+          newContext->StyleFont()->mFont.size) {
+        // The basis for 'rem' units has changed.
+        newContext = nullptr;
+        DoRebuildAllStyleData(aRestyleTracker, nsChangeHint(0));
+        if (aMinHint == 0) {
+          return;
+        }
+        aPrimaryFrame = aElement->GetPrimaryFrame();
+      }
+    }
+  }
+
+  if (aMinHint & nsChangeHint_ReconstructFrame) {
+    FrameConstructor()->RecreateFramesForContent(aElement, false);
+  } else if (aPrimaryFrame) {
+    nsStyleChangeList changeList;
+    FrameConstructor()-> // NOTE: removed later in patch series
+    ComputeStyleChangeFor(aPrimaryFrame, &changeList, aMinHint,
+                          aRestyleTracker, aRestyleDescendants);
+    ProcessRestyledFrames(changeList);
+  } else {
+    // no frames, reconstruct for content
+    FrameConstructor()->MaybeRecreateFramesForElement(aElement);
+  }
+}
+
+// Forwarded nsIDocumentObserver method, to handle restyling (and
+// passing the notification to the frame).
+nsresult
+RestyleManager::ContentStateChanged(nsIContent* aContent,
+                                    nsEventStates aStateMask)
+{
+  // XXXbz it would be good if this function only took Elements, but
+  // we'd have to make ESM guarantee that usefully.
+  if (!aContent->IsElement()) {
+    return NS_OK;
+  }
+
+  Element* aElement = aContent->AsElement();
+
+  nsStyleSet* styleSet = mPresContext->StyleSet();
+  NS_ASSERTION(styleSet, "couldn't get style set");
+
+  nsChangeHint hint = NS_STYLE_HINT_NONE;
+  // Any change to a content state that affects which frames we construct
+  // must lead to a frame reconstruct here if we already have a frame.
+  // Note that we never decide through non-CSS means to not create frames
+  // based on content states, so if we already don't have a frame we don't
+  // need to force a reframe -- if it's needed, the HasStateDependentStyle
+  // call will handle things.
+  nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
+  if (primaryFrame) {
+    // If it's generated content, ignore LOADING/etc state changes on it.
+    if (!primaryFrame->IsGeneratedContentFrame() &&
+        aStateMask.HasAtLeastOneOfStates(NS_EVENT_STATE_BROKEN |
+                                         NS_EVENT_STATE_USERDISABLED |
+                                         NS_EVENT_STATE_SUPPRESSED |
+                                         NS_EVENT_STATE_LOADING)) {
+      hint = nsChangeHint_ReconstructFrame;
+    } else {
+      uint8_t app = primaryFrame->StyleDisplay()->mAppearance;
+      if (app) {
+        nsITheme *theme = mPresContext->GetTheme();
+        if (theme && theme->ThemeSupportsWidget(mPresContext,
+                                                primaryFrame, app)) {
+          bool repaint = false;
+          theme->WidgetStateChanged(primaryFrame, app, nullptr, &repaint);
+          if (repaint) {
+            NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
+          }
+        }
+      }
+    }
+
+    primaryFrame->ContentStatesChanged(aStateMask);
+  }
+
+
+  nsRestyleHint rshint =
+    styleSet->HasStateDependentStyle(mPresContext, aElement, aStateMask);
+
+  if (aStateMask.HasState(NS_EVENT_STATE_HOVER) && rshint != 0) {
+    ++mHoverGeneration;
+  }
+
+  if (aStateMask.HasState(NS_EVENT_STATE_VISITED)) {
+    // Exposing information to the page about whether the link is
+    // visited or not isn't really something we can worry about here.
+    // FIXME: We could probably do this a bit better.
+    NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
+  }
+
+  PostRestyleEvent(aElement, rshint, hint);
+  return NS_OK;
+}
+
+// Forwarded nsIMutationObserver method, to handle restyling.
+void
+RestyleManager::AttributeWillChange(Element* aElement,
+                                    int32_t aNameSpaceID,
+                                    nsIAtom* aAttribute,
+                                    int32_t aModType)
+{
+  nsRestyleHint rshint =
+    mPresContext->StyleSet()->HasAttributeDependentStyle(mPresContext,
+                                                         aElement,
+                                                         aAttribute,
+                                                         aModType,
+                                                         false);
+  PostRestyleEvent(aElement, rshint, NS_STYLE_HINT_NONE);
+}
+
+// Forwarded nsIMutationObserver method, to handle restyling (and
+// passing the notification to the frame).
+void
+RestyleManager::AttributeChanged(Element* aElement,
+                                 int32_t aNameSpaceID,
+                                 nsIAtom* aAttribute,
+                                 int32_t aModType)
+{
+  // Hold onto the PresShell to prevent ourselves from being destroyed.
+  // XXXbz how, exactly, would this attribute change cause us to be
+  // destroyed from inside this function?
+  nsCOMPtr<nsIPresShell> shell = mPresContext->GetPresShell();
+
+  // Get the frame associated with the content which is the highest in the frame tree
+  nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
+
+#if 0
+  NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
+     ("RestyleManager::AttributeChanged: content=%p[%s] frame=%p",
+      aContent, ContentTag(aElement, 0), frame));
+#endif
+
+  // the style tag has its own interpretation based on aHint
+  nsChangeHint hint = aElement->GetAttributeChangeHint(aAttribute, aModType);
+
+  bool reframe = (hint & nsChangeHint_ReconstructFrame) != 0;
+
+#ifdef MOZ_XUL
+  // The following listbox widget trap prevents offscreen listbox widget
+  // content from being removed and re-inserted (which is what would
+  // happen otherwise).
+  if (!primaryFrame && !reframe) {
+    int32_t namespaceID;
+    nsIAtom* tag = mPresContext->Document()->BindingManager()->
+                     ResolveTag(aElement, &namespaceID);
+
+    if (namespaceID == kNameSpaceID_XUL &&
+        (tag == nsGkAtoms::listitem ||
+         tag == nsGkAtoms::listcell))
+      return;
+  }
+
+  if (aAttribute == nsGkAtoms::tooltiptext ||
+      aAttribute == nsGkAtoms::tooltip)
+  {
+    nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresContext->GetPresShell());
+    if (rootBox) {
+      if (aModType == nsIDOMMutationEvent::REMOVAL)
+        rootBox->RemoveTooltipSupport(aElement);
+      if (aModType == nsIDOMMutationEvent::ADDITION)
+        rootBox->AddTooltipSupport(aElement);
+    }
+  }
+
+#endif // MOZ_XUL
+
+  if (primaryFrame) {
+    // See if we have appearance information for a theme.
+    const nsStyleDisplay* disp = primaryFrame->StyleDisplay();
+    if (disp->mAppearance) {
+      nsITheme *theme = mPresContext->GetTheme();
+      if (theme && theme->ThemeSupportsWidget(mPresContext, primaryFrame, disp->mAppearance)) {
+        bool repaint = false;
+        theme->WidgetStateChanged(primaryFrame, disp->mAppearance, aAttribute, &repaint);
+        if (repaint)
+          NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
+      }
+    }
+
+    // let the frame deal with it now, so we don't have to deal later
+    primaryFrame->AttributeChanged(aNameSpaceID, aAttribute, aModType);
+    // XXXwaterson should probably check for special IB siblings
+    // here, and propagate the AttributeChanged notification to
+    // them, as well. Currently, inline frames don't do anything on
+    // this notification, so it's not that big a deal.
+  }
+
+  // See if we can optimize away the style re-resolution -- must be called after
+  // the frame's AttributeChanged() in case it does something that affects the style
+  nsRestyleHint rshint =
+    mPresContext->StyleSet()->HasAttributeDependentStyle(mPresContext,
+                                                         aElement,
+                                                         aAttribute,
+                                                         aModType,
+                                                         true);
+
+  PostRestyleEvent(aElement, rshint, hint);
+}
+
+void
+RestyleManager::RestyleForEmptyChange(Element* aContainer)
+{
+  // In some cases (:empty + E, :empty ~ E), a change if the content of
+  // an element requires restyling its parent's siblings.
+  nsRestyleHint hint = eRestyle_Subtree;
+  nsIContent* grandparent = aContainer->GetParent();
+  if (grandparent &&
+      (grandparent->GetFlags() & NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS)) {
+    hint = nsRestyleHint(hint | eRestyle_LaterSiblings);
+  }
+  PostRestyleEvent(aContainer, hint, NS_STYLE_HINT_NONE);
+}
+
+void
+RestyleManager::RestyleForAppend(Element* aContainer,
+                                 nsIContent* aFirstNewContent)
+{
+  NS_ASSERTION(aContainer, "must have container for append");
+#ifdef DEBUG
+  {
+    for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) {
+      NS_ASSERTION(!cur->IsRootOfAnonymousSubtree(),
+                   "anonymous nodes should not be in child lists");
+    }
+  }
+#endif
+  uint32_t selectorFlags =
+    aContainer->GetFlags() & (NODE_ALL_SELECTOR_FLAGS &
+                              ~NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS);
+  if (selectorFlags == 0)
+    return;
+
+  if (selectorFlags & NODE_HAS_EMPTY_SELECTOR) {
+    // see whether we need to restyle the container
+    bool wasEmpty = true; // :empty or :-moz-only-whitespace
+    for (nsIContent* cur = aContainer->GetFirstChild();
+         cur != aFirstNewContent;
+         cur = cur->GetNextSibling()) {
+      // We don't know whether we're testing :empty or :-moz-only-whitespace,
+      // so be conservative and assume :-moz-only-whitespace (i.e., make
+      // IsSignificantChild less likely to be true, and thus make us more
+      // likely to restyle).
+      if (nsStyleUtil::IsSignificantChild(cur, true, false)) {
+        wasEmpty = false;
+        break;
+      }
+    }
+    if (wasEmpty) {
+      RestyleForEmptyChange(aContainer);
+      return;
+    }
+  }
+
+  if (selectorFlags & NODE_HAS_SLOW_SELECTOR) {
+    PostRestyleEvent(aContainer, eRestyle_Subtree, NS_STYLE_HINT_NONE);
+    // Restyling the container is the most we can do here, so we're done.
+    return;
+  }
+
+  if (selectorFlags & NODE_HAS_EDGE_CHILD_SELECTOR) {
+    // restyle the last element child before this node
+    for (nsIContent* cur = aFirstNewContent->GetPreviousSibling();
+         cur;
+         cur = cur->GetPreviousSibling()) {
+      if (cur->IsElement()) {
+        PostRestyleEvent(cur->AsElement(), eRestyle_Subtree, NS_STYLE_HINT_NONE);
+        break;
+      }
+    }
+  }
+}
+
+// Needed since we can't use PostRestyleEvent on non-elements (with
+// eRestyle_LaterSiblings or nsRestyleHint(eRestyle_Subtree |
+// eRestyle_LaterSiblings) as appropriate).
+static void
+RestyleSiblingsStartingWith(RestyleManager* aRestyleManager,
+                            nsIContent* aStartingSibling /* may be null */)
+{
+  for (nsIContent *sibling = aStartingSibling; sibling;
+       sibling = sibling->GetNextSibling()) {
+    if (sibling->IsElement()) {
+      aRestyleManager->
+        PostRestyleEvent(sibling->AsElement(),
+                         nsRestyleHint(eRestyle_Subtree | eRestyle_LaterSiblings),
+                         NS_STYLE_HINT_NONE);
+      break;
+    }
+  }
+}
+
+// Restyling for a ContentInserted or CharacterDataChanged notification.
+// This could be used for ContentRemoved as well if we got the
+// notification before the removal happened (and sometimes
+// CharacterDataChanged is more like a removal than an addition).
+// The comments are written and variables are named in terms of it being
+// a ContentInserted notification.
+void
+RestyleManager::RestyleForInsertOrChange(Element* aContainer,
+                                         nsIContent* aChild)
+{
+  NS_ASSERTION(!aChild->IsRootOfAnonymousSubtree(),
+               "anonymous nodes should not be in child lists");
+  uint32_t selectorFlags =
+    aContainer ? (aContainer->GetFlags() & NODE_ALL_SELECTOR_FLAGS) : 0;
+  if (selectorFlags == 0)
+    return;
+
+  if (selectorFlags & NODE_HAS_EMPTY_SELECTOR) {
+    // see whether we need to restyle the container
+    bool wasEmpty = true; // :empty or :-moz-only-whitespace
+    for (nsIContent* child = aContainer->GetFirstChild();
+         child;
+         child = child->GetNextSibling()) {
+      if (child == aChild)
+        continue;
+      // We don't know whether we're testing :empty or :-moz-only-whitespace,
+      // so be conservative and assume :-moz-only-whitespace (i.e., make
+      // IsSignificantChild less likely to be true, and thus make us more
+      // likely to restyle).
+      if (nsStyleUtil::IsSignificantChild(child, true, false)) {
+        wasEmpty = false;
+        break;
+      }
+    }
+    if (wasEmpty) {
+      RestyleForEmptyChange(aContainer);
+      return;
+    }
+  }
+
+  if (selectorFlags & NODE_HAS_SLOW_SELECTOR) {
+    PostRestyleEvent(aContainer, eRestyle_Subtree, NS_STYLE_HINT_NONE);
+    // Restyling the container is the most we can do here, so we're done.
+    return;
+  }
+
+  if (selectorFlags & NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS) {
+    // Restyle all later siblings.
+    RestyleSiblingsStartingWith(this, aChild->GetNextSibling());
+  }
+
+  if (selectorFlags & NODE_HAS_EDGE_CHILD_SELECTOR) {
+    // restyle the previously-first element child if it is after this node
+    bool passedChild = false;
+    for (nsIContent* content = aContainer->GetFirstChild();
+         content;
+         content = content->GetNextSibling()) {
+      if (content == aChild) {
+        passedChild = true;
+        continue;
+      }
+      if (content->IsElement()) {
+        if (passedChild) {
+          PostRestyleEvent(content->AsElement(), eRestyle_Subtree,
+                           NS_STYLE_HINT_NONE);
+        }
+        break;
+      }
+    }
+    // restyle the previously-last element child if it is before this node
+    passedChild = false;
+    for (nsIContent* content = aContainer->GetLastChild();
+         content;
+         content = content->GetPreviousSibling()) {
+      if (content == aChild) {
+        passedChild = true;
+        continue;
+      }
+      if (content->IsElement()) {
+        if (passedChild) {
+          PostRestyleEvent(content->AsElement(), eRestyle_Subtree,
+                           NS_STYLE_HINT_NONE);
+        }
+        break;
+      }
+    }
+  }
+}
+
+void
+RestyleManager::RestyleForRemove(Element* aContainer,
+                                 nsIContent* aOldChild,
+                                 nsIContent* aFollowingSibling)
+{
+  if (aOldChild->IsRootOfAnonymousSubtree()) {
+    // This should be an assert, but this is called incorrectly in
+    // nsHTMLEditor::DeleteRefToAnonymousNode and the assertions were clogging
+    // up the logs.  Make it an assert again when that's fixed.
+    NS_WARNING("anonymous nodes should not be in child lists (bug 439258)");
+  }
+  uint32_t selectorFlags =
+    aContainer ? (aContainer->GetFlags() & NODE_ALL_SELECTOR_FLAGS) : 0;
+  if (selectorFlags == 0)
+    return;
+
+  if (selectorFlags & NODE_HAS_EMPTY_SELECTOR) {
+    // see whether we need to restyle the container
+    bool isEmpty = true; // :empty or :-moz-only-whitespace
+    for (nsIContent* child = aContainer->GetFirstChild();
+         child;
+         child = child->GetNextSibling()) {
+      // We don't know whether we're testing :empty or :-moz-only-whitespace,
+      // so be conservative and assume :-moz-only-whitespace (i.e., make
+      // IsSignificantChild less likely to be true, and thus make us more
+      // likely to restyle).
+      if (nsStyleUtil::IsSignificantChild(child, true, false)) {
+        isEmpty = false;
+        break;
+      }
+    }
+    if (isEmpty) {
+      RestyleForEmptyChange(aContainer);
+      return;
+    }
+  }
+
+  if (selectorFlags & NODE_HAS_SLOW_SELECTOR) {
+    PostRestyleEvent(aContainer, eRestyle_Subtree, NS_STYLE_HINT_NONE);
+    // Restyling the container is the most we can do here, so we're done.
+    return;
+  }
+
+  if (selectorFlags & NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS) {
+    // Restyle all later siblings.
+    RestyleSiblingsStartingWith(this, aFollowingSibling);
+  }
+
+  if (selectorFlags & NODE_HAS_EDGE_CHILD_SELECTOR) {
+    // restyle the now-first element child if it was after aOldChild
+    bool reachedFollowingSibling = false;
+    for (nsIContent* content = aContainer->GetFirstChild();
+         content;
+         content = content->GetNextSibling()) {
+      if (content == aFollowingSibling) {
+        reachedFollowingSibling = true;
+        // do NOT continue here; we might want to restyle this node
+      }
+      if (content->IsElement()) {
+        if (reachedFollowingSibling) {
+          PostRestyleEvent(content->AsElement(), eRestyle_Subtree,
+                           NS_STYLE_HINT_NONE);
+        }
+        break;
+      }
+    }
+    // restyle the now-last element child if it was before aOldChild
+    reachedFollowingSibling = (aFollowingSibling == nullptr);
+    for (nsIContent* content = aContainer->GetLastChild();
+         content;
+         content = content->GetPreviousSibling()) {
+      if (content->IsElement()) {
+        if (reachedFollowingSibling) {
+          PostRestyleEvent(content->AsElement(), eRestyle_Subtree, NS_STYLE_HINT_NONE);
+        }
+        break;
+      }
+      if (content == aFollowingSibling) {
+        reachedFollowingSibling = true;
+      }
+    }
+  }
+}
+
+void
+RestyleManager::RebuildAllStyleData(nsChangeHint aExtraHint)
+{
+  NS_ASSERTION(!(aExtraHint & nsChangeHint_ReconstructFrame),
+               "Should not reconstruct the root of the frame tree.  "
+               "Use ReconstructDocElementHierarchy instead.");
+
+  mRebuildAllStyleData = false;
+  NS_UpdateHint(aExtraHint, mRebuildAllExtraHint);
+  mRebuildAllExtraHint = nsChangeHint(0);
+
+  nsIPresShell* presShell = mPresContext->GetPresShell();
+  if (!presShell || !presShell->GetRootFrame())
+    return;
+
+  // Make sure that the viewmanager will outlive the presshell
+  nsRefPtr<nsViewManager> vm = presShell->GetViewManager();
+
+  // Processing the style changes could cause a flush that propagates to
+  // the parent frame and thus destroys the pres shell.
+  nsCOMPtr<nsIPresShell> kungFuDeathGrip(presShell);
+
+  // We may reconstruct frames below and hence process anything that is in the
+  // tree. We don't want to get notified to process those items again after.
+  presShell->GetDocument()->FlushPendingNotifications(Flush_ContentAndNotify);
+
+  nsAutoScriptBlocker scriptBlocker;
+
+  mPresContext->SetProcessingRestyles(true);
+
+  DoRebuildAllStyleData(mPendingRestyles, aExtraHint);
+
+  mPresContext->SetProcessingRestyles(false);
+
+  // Make sure that we process any pending animation restyles from the
+  // above style change.  Note that we can *almost* implement the above
+  // by just posting a style change -- except we really need to restyle
+  // the root frame rather than the root element's primary frame.
+  ProcessPendingRestyles();
+}
+
+void
+RestyleManager::DoRebuildAllStyleData(RestyleTracker& aRestyleTracker,
+                                      nsChangeHint aExtraHint)
+{
+  // Tell the style set to get the old rule tree out of the way
+  // so we can recalculate while maintaining rule tree immutability
+  nsresult rv = mPresContext->StyleSet()->BeginReconstruct();
+  if (NS_FAILED(rv)) {
+    return;
+  }
+
+  // Recalculate all of the style contexts for the document
+  // Note that we can ignore the return value of ComputeStyleChangeFor
+  // because we never need to reframe the root frame
+  // XXX This could be made faster by not rerunning rule matching
+  // (but note that nsPresShell::SetPreferenceStyleRules currently depends
+  // on us re-running rule matching here
+  nsStyleChangeList changeList;
+  // XXX Does it matter that we're passing aExtraHint to the real root
+  // frame and not the root node's primary frame?
+  // Note: The restyle tracker we pass in here doesn't matter.
+  FrameConstructor()-> // NOTE: removed later in patch series
+  ComputeStyleChangeFor(mPresContext->PresShell()->GetRootFrame(),
+                        &changeList, aExtraHint,
+                        aRestyleTracker, true);
+  // Process the required changes
+  ProcessRestyledFrames(changeList);
+  FlushOverflowChangedTracker();
+
+  // Tell the style set it's safe to destroy the old rule tree.  We
+  // must do this after the ProcessRestyledFrames call in case the
+  // change list has frame reconstructs in it (since frames to be
+  // reconstructed will still have their old style context pointers
+  // until they are destroyed).
+  mPresContext->StyleSet()->EndReconstruct();
+}
+
+void
+RestyleManager::ProcessPendingRestyles()
+{
+  NS_PRECONDITION(mPresContext->Document(), "No document?  Pshaw!");
+  NS_PRECONDITION(!nsContentUtils::IsSafeToRunScript(),
+                  "Missing a script blocker!");
+
+  // Process non-animation restyles...
+  NS_ABORT_IF_FALSE(!mPresContext->IsProcessingRestyles(),
+                    "Nesting calls to ProcessPendingRestyles?");
+  mPresContext->SetProcessingRestyles(true);
+
+  // Before we process any restyles, we need to ensure that style
+  // resulting from any throttled animations (animations that we're
+  // running entirely on the compositor thread) is up-to-date, so that
+  // if any style changes we cause trigger transitions, we have the
+  // correct old style for starting the transition.
+  if (nsLayoutUtils::AreAsyncAnimationsEnabled() &&
+      mPendingRestyles.Count() > 0) {
+    ++mAnimationGeneration;
+    mPresContext->TransitionManager()->UpdateAllThrottledStyles();
+  }
+
+  mPendingRestyles.ProcessRestyles();
+
+#ifdef DEBUG
+  uint32_t oldPendingRestyleCount = mPendingRestyles.Count();
+#endif
+
+  // ...and then process animation restyles.  This needs to happen
+  // second because we need to start animations that resulted from the
+  // first set of restyles (e.g., CSS transitions with negative
+  // transition-delay), and because we need to immediately
+  // restyle-with-animation any just-restyled elements that are
+  // mid-transition (since processing the non-animation restyle ignores
+  // the running transition so it can check for a new change on the same
+  // property, and then posts an immediate animation style change).
+  mPresContext->SetProcessingAnimationStyleChange(true);
+  mPendingAnimationRestyles.ProcessRestyles();
+  mPresContext->SetProcessingAnimationStyleChange(false);
+
+  mPresContext->SetProcessingRestyles(false);
+  NS_POSTCONDITION(mPendingRestyles.Count() == oldPendingRestyleCount,
+                   "We should not have posted new non-animation restyles while "
+                   "processing animation restyles");
+
+  if (mRebuildAllStyleData) {
+    // We probably wasted a lot of work up above, but this seems safest
+    // and it should be rarely used.
+    // This might add us as a refresh observer again; that's ok.
+    RebuildAllStyleData(nsChangeHint(0));
+  }
+}
+
+void
+RestyleManager::PostRestyleEventCommon(Element* aElement,
+                                       nsRestyleHint aRestyleHint,
+                                       nsChangeHint aMinChangeHint,
+                                       bool aForAnimation)
+{
+  if (MOZ_UNLIKELY(mPresContext->PresShell()->IsDestroying())) {
+    return;
+  }
+
+  if (aRestyleHint == 0 && !aMinChangeHint) {
+    // Nothing to do here
+    return;
+  }
+
+  RestyleTracker& tracker =
+    aForAnimation ? mPendingAnimationRestyles : mPendingRestyles;
+  tracker.AddPendingRestyle(aElement, aRestyleHint, aMinChangeHint);
+
+  PostRestyleEventInternal(false);
+}
+
+void
+RestyleManager::PostRestyleEventInternal(bool aForLazyConstruction)
+{
+  // Make sure we're not in a style refresh; if we are, we still have
+  // a call to ProcessPendingRestyles coming and there's no need to
+  // add ourselves as a refresh observer until then.
+  bool inRefresh = !aForLazyConstruction && mInStyleRefresh;
+  nsIPresShell* presShell = mPresContext->PresShell();
+  if (!mObservingRefreshDriver && !inRefresh) {
+    mObservingRefreshDriver = mPresContext->RefreshDriver()->
+      AddStyleFlushObserver(presShell);
+  }
+
+  // Unconditionally flag our document as needing a flush.  The other
+  // option here would be a dedicated boolean to track whether we need
+  // to do so (set here and unset in ProcessPendingRestyles).
+  presShell->GetDocument()->SetNeedStyleFlush();
+}
+
+void
+RestyleManager::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint)
+{
+  NS_ASSERTION(!(aExtraHint & nsChangeHint_ReconstructFrame),
+               "Should not reconstruct the root of the frame tree.  "
+               "Use ReconstructDocElementHierarchy instead.");
+
+  mRebuildAllStyleData = true;
+  NS_UpdateHint(mRebuildAllExtraHint, aExtraHint);
+
+  // Get a restyle event posted if necessary
+  PostRestyleEventInternal(false);
+}
+
+bool
+RestyleManager::RecomputePosition(nsIFrame* aFrame)
+{
+  // Don't process position changes on table frames, since we already handle
+  // the dynamic position change on the outer table frame, and the reflow-based
+  // fallback code path also ignores positions on inner table frames.
+  if (aFrame->GetType() == nsGkAtoms::tableFrame) {
+    return true;
+  }
+
+  // Don't process position changes on frames which have views or the ones which
+  // have a view somewhere in their descendants, because the corresponding view
+  // needs to be repositioned properly as well.
+  if (aFrame->HasView() ||
+      (aFrame->GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW)) {
+    StyleChangeReflow(aFrame, nsChangeHint_NeedReflow);
+    return false;
+  }
+
+  const nsStyleDisplay* display = aFrame->StyleDisplay();
+  // Changes to the offsets of a non-positioned element can safely be ignored.
+  if (display->mPosition == NS_STYLE_POSITION_STATIC) {
+    return true;
+  }
+
+  aFrame->SchedulePaint();
+
+  // For relative positioning, we can simply update the frame rect
+  if (display->mPosition == NS_STYLE_POSITION_RELATIVE) {
+    switch (display->mDisplay) {
+      case NS_STYLE_DISPLAY_TABLE_CAPTION:
+      case NS_STYLE_DISPLAY_TABLE_CELL:
+      case NS_STYLE_DISPLAY_TABLE_ROW:
+      case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
+      case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
+      case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
+      case NS_STYLE_DISPLAY_TABLE_COLUMN:
+      case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP:
+        // We don't currently support relative positioning of inner
+        // table elements.  If we apply offsets to things we haven't
+        // previously offset, we'll get confused.  So bail.
+        return true;
+      default:
+        break;
+    }
+
+    nsIFrame* cb = aFrame->GetContainingBlock();
+    const nsSize size = cb->GetSize();
+    const nsPoint oldOffsets = aFrame->GetRelativeOffset();
+    nsMargin newOffsets;
+
+    // Move the frame
+    nsHTMLReflowState::ComputeRelativeOffsets(
+        cb->StyleVisibility()->mDirection,
+        aFrame, size.width, size.height, newOffsets);
+    NS_ASSERTION(newOffsets.left == -newOffsets.right &&
+                 newOffsets.top == -newOffsets.bottom,
+                 "ComputeRelativeOffsets should return valid results");
+    aFrame->SetPosition(aFrame->GetPosition() - oldOffsets +
+                        nsPoint(newOffsets.left, newOffsets.top));
+
+    return true;
+  }
+
+  // For absolute positioning, the width can potentially change if width is
+  // auto and either of left or right are not.  The height can also potentially
+  // change if height is auto and either of top or bottom are not.  In these
+  // cases we fall back to a reflow, and in all other cases, we attempt to
+  // move the frame here.
+  // Note that it is possible for the dimensions to not change in the above
+  // cases, so we should be a little smarter here and only fall back to reflow
+  // when the dimensions will really change (bug 745485).
+  const nsStylePosition* position = aFrame->StylePosition();
+  if (position->mWidth.GetUnit() != eStyleUnit_Auto &&
+      position->mHeight.GetUnit() != eStyleUnit_Auto) {
+    // For the absolute positioning case, set up a fake HTML reflow state for
+    // the frame, and then get the offsets from it.
+    nsRefPtr<nsRenderingContext> rc = aFrame->PresContext()->GetPresShell()->
+      GetReferenceRenderingContext();
+
+    // Construct a bogus parent reflow state so that there's a usable
+    // containing block reflow state.
+    nsIFrame* parentFrame = aFrame->GetParent();
+    nsSize parentSize = parentFrame->GetSize();
+
+    nsFrameState savedState = parentFrame->GetStateBits();
+    nsHTMLReflowState parentReflowState(aFrame->PresContext(), parentFrame,
+                                        rc, parentSize);
+    parentFrame->RemoveStateBits(~nsFrameState(0));
+    parentFrame->AddStateBits(savedState);
+
+    NS_WARN_IF_FALSE(parentSize.width != NS_INTRINSICSIZE &&
+                     parentSize.height != NS_INTRINSICSIZE,
+                     "parentSize should be valid");
+    parentReflowState.SetComputedWidth(std::max(parentSize.width, 0));
+    parentReflowState.SetComputedHeight(std::max(parentSize.height, 0));
+    parentReflowState.mComputedMargin.SizeTo(0, 0, 0, 0);
+    parentSize.height = NS_AUTOHEIGHT;
+
+    parentReflowState.mComputedPadding = parentFrame->GetUsedPadding();
+    parentReflowState.mComputedBorderPadding =
+      parentFrame->GetUsedBorderAndPadding();
+
+    nsSize availSize(parentSize.width, NS_INTRINSICSIZE);
+
+    nsSize size = aFrame->GetSize();
+    ViewportFrame* viewport = do_QueryFrame(parentFrame);
+    nsSize cbSize = viewport ?
+      viewport->AdjustReflowStateAsContainingBlock(&parentReflowState).Size()
+      : aFrame->GetContainingBlock()->GetSize();
+    const nsMargin& parentBorder =
+      parentReflowState.mStyleBorder->GetComputedBorder();
+    cbSize -= nsSize(parentBorder.LeftRight(), parentBorder.TopBottom());
+    nsHTMLReflowState reflowState(aFrame->PresContext(), parentReflowState,
+                                  aFrame, availSize, cbSize.width,
+                                  cbSize.height);
+
+    // If we're solving for 'left' or 'top', then compute it here, in order to
+    // match the reflow code path.
+    if (NS_AUTOOFFSET == reflowState.mComputedOffsets.left) {
+      reflowState.mComputedOffsets.left = cbSize.width -
+                                          reflowState.mComputedOffsets.right -
+                                          reflowState.mComputedMargin.right -
+                                          size.width -
+                                          reflowState.mComputedMargin.left;
+    }
+
+    if (NS_AUTOOFFSET == reflowState.mComputedOffsets.top) {
+      reflowState.mComputedOffsets.top = cbSize.height -
+                                         reflowState.mComputedOffsets.bottom -
+                                         reflowState.mComputedMargin.bottom -
+                                         size.height -
+                                         reflowState.mComputedMargin.top;
+    }
+
+    // Move the frame
+    nsPoint pos(parentBorder.left + reflowState.mComputedOffsets.left +
+                reflowState.mComputedMargin.left,
+                parentBorder.top + reflowState.mComputedOffsets.top +
+                reflowState.mComputedMargin.top);
+    aFrame->SetPosition(pos);
+
+    return true;
+  }
+
+  // Fall back to a reflow
+  StyleChangeReflow(aFrame, nsChangeHint_NeedReflow);
+  return false;
 }
 
 } // namespace mozilla
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -7,35 +7,231 @@
  * Code responsible for managing style changes: tracking what style
  * changes need to happen, scheduling them, and doing them.
  */
 
 #ifndef mozilla_RestyleManager_h
 #define mozilla_RestyleManager_h
 
 #include "nsISupportsImpl.h"
+#include "nsChangeHint.h"
+#include "RestyleTracker.h"
+#include "nsPresContext.h"
 
-class nsPresContext;
+class nsRefreshDriver;
+class nsIFrame;
 
 namespace mozilla {
 
+namespace dom {
+  class Element;
+} // namespace dom
+
 class RestyleManager {
 public:
+  friend class ::nsRefreshDriver;
+  friend class RestyleTracker;
+
+  typedef mozilla::dom::Element Element;
+
   RestyleManager(nsPresContext* aPresContext);
 
   NS_INLINE_DECL_REFCOUNTING(mozilla::RestyleManager)
 
   void Disconnect() {
     mPresContext = nullptr;
   }
 
   nsPresContext* PresContext() const {
     MOZ_ASSERT(mPresContext);
     return mPresContext;
   }
 
+  nsCSSFrameConstructor* FrameConstructor() const
+    { return PresContext()->FrameConstructor(); }
+
+  // Should be called when a frame is going to be destroyed and
+  // WillDestroyFrameTree hasn't been called yet.
+  void NotifyDestroyingFrame(nsIFrame* aFrame);
+
+  // Forwarded nsIDocumentObserver method, to handle restyling (and
+  // passing the notification to the frame).
+  nsresult ContentStateChanged(nsIContent*   aContent,
+                               nsEventStates aStateMask);
+
+  // Forwarded nsIMutationObserver method, to handle restyling.
+  void AttributeWillChange(Element* aElement,
+                           int32_t  aNameSpaceID,
+                           nsIAtom* aAttribute,
+                           int32_t  aModType);
+  // Forwarded nsIMutationObserver method, to handle restyling (and
+  // passing the notification to the frame).
+  void AttributeChanged(Element* aElement,
+                        int32_t  aNameSpaceID,
+                        nsIAtom* aAttribute,
+                        int32_t  aModType);
+
+  // Get an integer that increments every time there is a style change
+  // as a result of a change to the :hover content state.
+  uint32_t GetHoverGeneration() const { return mHoverGeneration; }
+
+  // Get a counter that increments on every style change, that we use to
+  // track whether off-main-thread animations are up-to-date.
+  uint64_t GetAnimationGeneration() const { return mAnimationGeneration; }
+
+  // Note: It's the caller's responsibility to make sure to wrap a
+  // ProcessRestyledFrames call in a view update batch and a script blocker.
+  // This function does not call ProcessAttachedQueue() on the binding manager.
+  // If the caller wants that to happen synchronously, it needs to handle that
+  // itself.
+  nsresult ProcessRestyledFrames(nsStyleChangeList& aRestyleArray);
+
+private:
+  void RestyleForEmptyChange(Element* aContainer);
+
+public:
+  // Restyling for a ContentInserted (notification after insertion) or
+  // for a CharacterDataChanged.  |aContainer| must be non-null; when
+  // the container is null, no work is needed.
+  void RestyleForInsertOrChange(Element* aContainer, nsIContent* aChild);
+
+  // This would be the same as RestyleForInsertOrChange if we got the
+  // notification before the removal.  However, we get it after, so we need the
+  // following sibling in addition to the old child.  |aContainer| must be
+  // non-null; when the container is null, no work is needed.  aFollowingSibling
+  // is the sibling that used to come after aOldChild before the removal.
+  void RestyleForRemove(Element* aContainer,
+                        nsIContent* aOldChild,
+                        nsIContent* aFollowingSibling);
+
+  // Same for a ContentAppended.  |aContainer| must be non-null; when
+  // the container is null, no work is needed.
+  void RestyleForAppend(Element* aContainer, nsIContent* aFirstNewContent);
+
+  // Process any pending restyles. This should be called after
+  // CreateNeededFrames.
+  // Note: It's the caller's responsibility to make sure to wrap a
+  // ProcessPendingRestyles call in a view update batch and a script blocker.
+  // This function does not call ProcessAttachedQueue() on the binding manager.
+  // If the caller wants that to happen synchronously, it needs to handle that
+  // itself.
+  void ProcessPendingRestyles();
+
+  // Rebuilds all style data by throwing out the old rule tree and
+  // building a new one, and additionally applying aExtraHint (which
+  // must not contain nsChangeHint_ReconstructFrame) to the root frame.
+  void RebuildAllStyleData(nsChangeHint aExtraHint);
+
+  // Helper that does part of the work of RebuildAllStyleData, shared by
+  // RestyleElement for 'rem' handling.
+  void DoRebuildAllStyleData(RestyleTracker& aRestyleTracker,
+                             nsChangeHint aExtraHint);
+
+  // See PostRestyleEventCommon below.
+  void PostRestyleEvent(Element* aElement,
+                        nsRestyleHint aRestyleHint,
+                        nsChangeHint aMinChangeHint)
+  {
+    if (mPresContext) {
+      PostRestyleEventCommon(aElement, aRestyleHint, aMinChangeHint,
+                             mPresContext->IsProcessingAnimationStyleChange());
+    }
+  }
+
+  // See PostRestyleEventCommon below.
+  void PostAnimationRestyleEvent(Element* aElement,
+                                 nsRestyleHint aRestyleHint,
+                                 nsChangeHint aMinChangeHint)
+  {
+    PostRestyleEventCommon(aElement, aRestyleHint, aMinChangeHint, true);
+  }
+
+  void PostRestyleEventForLazyConstruction()
+  {
+    PostRestyleEventInternal(true);
+  }
+
+  void FlushOverflowChangedTracker()
+  {
+    mOverflowChangedTracker.Flush();
+  }
+
+private:
+  /**
+   * Notify the frame constructor that an element needs to have its
+   * style recomputed.
+   * @param aElement: The element to be restyled.
+   * @param aRestyleHint: Which nodes need to have selector matching run
+   *                      on them.
+   * @param aMinChangeHint: A minimum change hint for aContent and its
+   *                        descendants.
+   * @param aForAnimation: Whether the style should be computed with or
+   *                       without animation data.  Animation code
+   *                       sometimes needs to pass true; other code
+   *                       should generally pass the the pres context's
+   *                       IsProcessingAnimationStyleChange() value
+   *                       (which is the default value).
+   */
+  void PostRestyleEventCommon(Element* aElement,
+                              nsRestyleHint aRestyleHint,
+                              nsChangeHint aMinChangeHint,
+                              bool aForAnimation);
+  void PostRestyleEventInternal(bool aForLazyConstruction);
+
+public:
+  /**
+   * Asynchronously clear style data from the root frame downwards and ensure
+   * it will all be rebuilt. This is safe to call anytime; it will schedule
+   * a restyle and take effect next time style changes are flushed.
+   * This method is used to recompute the style data when some change happens
+   * outside of any style rules, like a color preference change or a change
+   * in a system font size, or to fix things up when an optimization in the
+   * style data has become invalid. We assume that the root frame will not
+   * need to be reframed.
+   */
+  void PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint);
+
+  void SetPromoteReflowsToReframeRoot(bool aPromote)
+    { mPromoteReflowsToReframeRoot = aPromote; }
+
+private:
+  /* aMinHint is the minimal change that should be made to the element */
+  // XXXbz do we really need the aPrimaryFrame argument here?
+  void RestyleElement(Element* aElement,
+                      nsIFrame*       aPrimaryFrame,
+                      nsChangeHint    aMinHint,
+                      RestyleTracker& aRestyleTracker,
+                      bool            aRestyleDescendants);
+
+  nsresult StyleChangeReflow(nsIFrame* aFrame, nsChangeHint aHint);
+
+  // Returns true if this function managed to successfully move a frame, and
+  // false if it could not process the position change, and a reflow should
+  // be performed instead.
+  bool RecomputePosition(nsIFrame* aFrame);
+
 private:
   nsPresContext* mPresContext; // weak, disconnected in Disconnect
+
+  bool mRebuildAllStyleData : 1;
+  // True if we're already waiting for a refresh notification
+  bool mObservingRefreshDriver : 1;
+  // True if we're in the middle of a nsRefreshDriver refresh
+  bool mInStyleRefresh : 1;
+  // True if reflows/frame reconstruction should be promoted to reframe
+  // the root element
+  bool mPromoteReflowsToReframeRoot : 1;
+  uint32_t mHoverGeneration;
+  nsChangeHint mRebuildAllExtraHint;
+
+  OverflowChangedTracker mOverflowChangedTracker;
+
+  // The total number of animation flushes by this frame constructor.
+  // Used to keep the layer and animation manager in sync.
+  uint64_t mAnimationGeneration;
+
+  RestyleTracker mPendingRestyles;
+  RestyleTracker mPendingAnimationRestyles;
 };
 
 } // namespace mozilla
 
 #endif /* mozilla_RestyleManager_h */
--- a/layout/base/RestyleTracker.cpp
+++ b/layout/base/RestyleTracker.cpp
@@ -12,17 +12,17 @@
 #include "nsCSSFrameConstructor.h"
 #include "nsStyleChangeList.h"
 #include "GeckoProfiler.h"
 
 namespace mozilla {
 
 inline nsIDocument*
 RestyleTracker::Document() const {
-  return mFrameConstructor->mDocument;
+  return mRestyleManager->PresContext()->Document();
 }
 
 #define RESTYLE_ARRAY_STACKSIZE 128
 
 struct LaterSiblingCollector {
   RestyleTracker* tracker;
   nsTArray< nsRefPtr<dom::Element> >* elements;
 };
@@ -113,38 +113,38 @@ RestyleTracker::ProcessOneRestyle(Elemen
   NS_PRECONDITION((aRestyleHint & eRestyle_LaterSiblings) == 0,
                   "Someone should have handled this before calling us");
   NS_PRECONDITION(Document(), "Must have a document");
   NS_PRECONDITION(aElement->GetCurrentDoc() == Document(),
                   "Element has unexpected document");
 
   nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
   if (aRestyleHint & (eRestyle_Self | eRestyle_Subtree)) {
-    mFrameConstructor->RestyleElement(aElement, primaryFrame, aChangeHint,
-                                      *this,
-                                      (aRestyleHint & eRestyle_Subtree) != 0);
+    mRestyleManager->RestyleElement(aElement, primaryFrame, aChangeHint,
+                                    *this,
+                                    (aRestyleHint & eRestyle_Subtree) != 0);
   } else if (aChangeHint &&
              (primaryFrame ||
               (aChangeHint & nsChangeHint_ReconstructFrame))) {
     // Don't need to recompute style; just apply the hint
     nsStyleChangeList changeList;
     changeList.AppendChange(primaryFrame, aElement, aChangeHint);
-    mFrameConstructor->ProcessRestyledFrames(changeList);
+    mRestyleManager->ProcessRestyledFrames(changeList);
   }
 }
 
 void
 RestyleTracker::DoProcessRestyles()
 {
   PROFILER_LABEL("CSS", "ProcessRestyles");
   // Make sure to not rebuild quote or counter lists while we're
   // processing restyles
-  mFrameConstructor->BeginUpdate();
+  mRestyleManager->PresContext()->FrameConstructor()->BeginUpdate();
 
-  mFrameConstructor->mInStyleRefresh = true;
+  mRestyleManager->mInStyleRefresh = true;
 
   // loop so that we process any restyle events generated by processing
   while (mPendingRestyles.Count()) {
     if (mHaveLaterSiblingRestyles) {
       // Convert them to individual restyles on all the later siblings
       nsAutoTArray<nsRefPtr<Element>, RESTYLE_ARRAY_STACKSIZE> laterSiblingArr;
       LaterSiblingCollector siblingCollector = { this, &laterSiblingArr };
       mPendingRestyles.Enumerate(CollectLaterSiblings, &siblingCollector);
@@ -234,26 +234,26 @@ RestyleTracker::DoProcessRestyles()
            ++currentRestyle) {
         ProcessOneRestyle(currentRestyle->mElement,
                           currentRestyle->mRestyleHint,
                           currentRestyle->mChangeHint);
       }
     }
   }
 
-  mFrameConstructor->FlushOverflowChangedTracker();
+  mRestyleManager->FlushOverflowChangedTracker();
 
   // Set mInStyleRefresh to false now, since the EndUpdate call might
   // add more restyles.
-  mFrameConstructor->mInStyleRefresh = false;
+  mRestyleManager->mInStyleRefresh = false;
 
-  mFrameConstructor->EndUpdate();
+  mRestyleManager->PresContext()->FrameConstructor()->EndUpdate();
 
 #ifdef DEBUG
-  mFrameConstructor->mPresShell->VerifyStyleTree();
+  mRestyleManager->PresContext()->PresShell()->VerifyStyleTree();
 #endif
 }
 
 bool
 RestyleTracker::GetRestyleData(Element* aElement, RestyleData* aData)
 {
   NS_PRECONDITION(aElement->GetCurrentDoc() == Document(),
                   "Unexpected document; this will lead to incorrect behavior!");
--- a/layout/base/RestyleTracker.h
+++ b/layout/base/RestyleTracker.h
@@ -12,19 +12,19 @@
 #define mozilla_RestyleTracker_h
 
 #include "mozilla/dom/Element.h"
 #include "nsDataHashtable.h"
 #include "nsIFrame.h"
 #include "nsTPriorityQueue.h"
 #include "mozilla/SplayTree.h"
 
-class nsCSSFrameConstructor;
+namespace mozilla {
 
-namespace mozilla {
+class RestyleManager;
 
 /** 
  * Helper class that collects a list of frames that need
  * UpdateOverflow() called on them, and coalesces them
  * to avoid walking up the same ancestor tree multiple times.
  */
 class OverflowChangedTracker
 {
@@ -185,18 +185,18 @@ public:
                     "Shouldn't have both restyle flags set");
     NS_PRECONDITION((mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS) != 0,
                     "Must have root flag");
     NS_PRECONDITION((mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS) !=
                     (ELEMENT_ALL_RESTYLE_FLAGS & ~ELEMENT_PENDING_RESTYLE_FLAGS),
                     "Shouldn't have both root flags");
   }
 
-  void Init(nsCSSFrameConstructor* aFrameConstructor) {
-    mFrameConstructor = aFrameConstructor;
+  void Init(RestyleManager* aRestyleManager) {
+    mRestyleManager = aRestyleManager;
     mPendingRestyles.Init();
   }
 
   uint32_t Count() const {
     return mPendingRestyles.Count();
   }
 
   /**
@@ -270,17 +270,17 @@ private:
   void DoProcessRestyles();
 
   typedef nsDataHashtable<nsISupportsHashKey, RestyleData> PendingRestyleTable;
   typedef nsAutoTArray< nsRefPtr<Element>, 32> RestyleRootArray;
   // Our restyle bits.  These will be a subset of ELEMENT_ALL_RESTYLE_FLAGS, and
   // will include one flag from ELEMENT_PENDING_RESTYLE_FLAGS and one flag
   // that's not in ELEMENT_PENDING_RESTYLE_FLAGS.
   uint32_t mRestyleBits;
-  nsCSSFrameConstructor* mFrameConstructor; // Owns us
+  RestyleManager* mRestyleManager; // Owns us
   // A hashtable that maps elements to RestyleData structs.  The
   // values only make sense if the element's current document is our
   // document and it has our RestyleBit() flag set.  In particular,
   // said bit might not be set if the element had a restyle posted and
   // then was moved around in the DOM.
   PendingRestyleTable mPendingRestyles;
   // An array that keeps track of our possible restyle roots.  This
   // maintains the invariant that if A and B are both restyle roots
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -45,17 +45,16 @@
 #include "nsIDOMHTMLLegendElement.h"
 #include "nsIComboboxControlFrame.h"
 #include "nsIListControlFrame.h"
 #include "nsISelectControlFrame.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsPlaceholderFrame.h"
 #include "nsTableRowGroupFrame.h"
-#include "nsStyleChangeList.h"
 #include "nsIFormControl.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsTextFragment.h"
 #include "nsIAnonymousContentCreator.h"
 #include "nsLegendFrame.h"
 #include "nsIContentIterator.h"
 #include "nsBoxLayoutState.h"
 #include "nsBindingManager.h"
@@ -75,29 +74,25 @@
 #include "nsLayoutUtils.h"
 #include "nsAutoPtr.h"
 #include "nsBoxFrame.h"
 #include "nsBoxLayout.h"
 #include "nsFlexContainerFrame.h"
 #include "nsImageFrame.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIPrincipal.h"
-#include "nsStyleUtil.h"
 #include "nsBox.h"
 #include "nsTArray.h"
 #include "nsGenericDOMDataNode.h"
 #include "mozilla/dom/Element.h"
 #include "FrameLayerBuilder.h"
 #include "nsAutoLayoutPhase.h"
 #include "nsCSSRenderingBorders.h"
 #include "nsRenderingContext.h"
 #include "nsStyleStructInlines.h"
-#include "nsAnimationManager.h"
-#include "nsTransitionManager.h"
-#include "nsSVGIntegrationUtils.h"
 #include "nsViewportFrame.h"
 #include "nsPageContentFrame.h"
 #include <algorithm>
 
 #ifdef MOZ_XUL
 #include "nsIRootBox.h"
 #include "nsIDOMXULCommandDispatcher.h"
 #include "nsIDOMXULDocument.h"
@@ -1413,32 +1408,18 @@ nsCSSFrameConstructor::nsCSSFrameConstru
   , mDocElementContainingBlock(nullptr)
   , mGfxScrollFrame(nullptr)
   , mPageSequenceFrame(nullptr)
   , mCurrentDepth(0)
   , mUpdateCount(0)
   , mQuotesDirty(false)
   , mCountersDirty(false)
   , mIsDestroyingFrameTree(false)
-  , mRebuildAllStyleData(false)
   , mHasRootAbsPosContainingBlock(false)
-  , mObservingRefreshDriver(false)
-  , mInStyleRefresh(false)
-  , mPromoteReflowsToReframeRoot(false)
-  , mHoverGeneration(0)
-  , mRebuildAllExtraHint(nsChangeHint(0))
-  , mAnimationGeneration(0)
-  , mPendingRestyles(ELEMENT_HAS_PENDING_RESTYLE |
-                     ELEMENT_IS_POTENTIAL_RESTYLE_ROOT)
-  , mPendingAnimationRestyles(ELEMENT_HAS_PENDING_ANIMATION_RESTYLE |
-                              ELEMENT_IS_POTENTIAL_ANIMATION_RESTYLE_ROOT)
-{
-  mPendingRestyles.Init(this);
-  mPendingAnimationRestyles.Init(this);
-
+{
 #ifdef DEBUG
   static bool gFirstTime = true;
   if (gFirstTime) {
     gFirstTime = false;
     char* flags = PR_GetEnv("GECKO_FRAMECTOR_DEBUG_FLAGS");
     if (flags) {
       bool error = false;
       for (;;) {
@@ -1498,17 +1479,17 @@ nsCSSFrameConstructor::NotifyDestroyingF
 
   if (mCounterManager.DestroyNodesFor(aFrame)) {
     // Technically we don't need to update anything if we destroyed only
     // USE nodes.  However, this is unlikely to happen in the real world
     // since USE nodes generally go along with INCREMENT nodes.
     CountersDirty();
   }
 
-  mOverflowChangedTracker.RemoveFrame(aFrame);
+  RestyleManager()->NotifyDestroyingFrame(aFrame);
 
   nsFrameManager::NotifyDestroyingFrame(aFrame);
 }
 
 struct nsGenConInitializer {
   nsAutoPtr<nsGenConNode> mNode;
   nsGenConList*           mList;
   void (nsCSSFrameConstructor::*mDirtyAll)();
@@ -6266,17 +6247,17 @@ nsCSSFrameConstructor::MaybeConstructLaz
                    //XXX the child->GetPrimaryFrame()->GetContent() != child
                    // check is needed due to bug 135040. Remove it once that's
                    // fixed.
                    "setting NEEDS_FRAME on a node that already has a frame?");
       child->SetFlags(NODE_NEEDS_FRAME);
     }
   }
 
-  PostRestyleEventInternal(true);
+  PostRestyleEventForLazyConstruction();
   return true;
 }
 
 void
 nsCSSFrameConstructor::CreateNeededFrames(nsIContent* aContent)
 {
   NS_ASSERTION(!aContent->HasFlag(NODE_NEEDS_FRAME),
     "shouldn't get here with a content node that has needs frame bit set");
@@ -7596,257 +7577,16 @@ nsCSSFrameConstructor::ContentRemoved(ns
       parentFrame->List(stdout, 0);
     }
 #endif
   }
 
   return rv;
 }
 
-#ifdef DEBUG
-  // To ensure that the functions below are only called within
-  // |ApplyRenderingChangeToTree|.
-static bool gInApplyRenderingChangeToTree = false;
-#endif
-
-static void
-DoApplyRenderingChangeToTree(nsIFrame* aFrame,
-                             nsFrameManager* aFrameManager,
-                             nsChangeHint aChange);
-
-/**
- * Sync views on aFrame and all of aFrame's descendants (following placeholders),
- * if aChange has nsChangeHint_SyncFrameView.
- * Calls DoApplyRenderingChangeToTree on all aFrame's out-of-flow descendants
- * (following placeholders), if aChange has nsChangeHint_RepaintFrame.
- * aFrame should be some combination of nsChangeHint_SyncFrameView and
- * nsChangeHint_RepaintFrame and nsChangeHint_UpdateOpacityLayer, nothing else.
-*/
-static void
-SyncViewsAndInvalidateDescendants(nsIFrame* aFrame,
-                                  nsFrameManager* aFrameManager,
-                                  nsChangeHint aChange)
-{
-  NS_PRECONDITION(gInApplyRenderingChangeToTree,
-                  "should only be called within ApplyRenderingChangeToTree");
-  NS_ASSERTION(aChange == (aChange & (nsChangeHint_RepaintFrame |
-                                      nsChangeHint_SyncFrameView |
-                                      nsChangeHint_UpdateOpacityLayer)),
-               "Invalid change flag");
-
-  nsView* view = aFrame->GetView();
-  if (view) {
-    if (aChange & nsChangeHint_SyncFrameView) {
-      nsContainerFrame::SyncFrameViewProperties(aFrame->PresContext(),
-                                                aFrame, nullptr, view);
-    }
-  }
-
-  nsIFrame::ChildListIterator lists(aFrame);
-  for (; !lists.IsDone(); lists.Next()) {
-    nsFrameList::Enumerator childFrames(lists.CurrentList());
-    for (; !childFrames.AtEnd(); childFrames.Next()) {
-      nsIFrame* child = childFrames.get();
-      if (!(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
-        // only do frames that don't have placeholders
-        if (nsGkAtoms::placeholderFrame == child->GetType()) {
-          // do the out-of-flow frame and its continuations
-          nsIFrame* outOfFlowFrame =
-            nsPlaceholderFrame::GetRealFrameForPlaceholder(child);
-          DoApplyRenderingChangeToTree(outOfFlowFrame, aFrameManager,
-                                       aChange);
-        } else if (lists.CurrentID() == nsIFrame::kPopupList) {
-          DoApplyRenderingChangeToTree(child, aFrameManager,
-                                       aChange);
-        } else {  // regular frame
-          SyncViewsAndInvalidateDescendants(child, aFrameManager, aChange);
-        }
-      }
-    }
-  }
-}
-
-/**
- * To handle nsChangeHint_ChildrenOnlyTransform we must iterate over the child
- * frames of the SVG frame concerned. This helper function is used to find that
- * SVG frame when we encounter nsChangeHint_ChildrenOnlyTransform to ensure
- * that we iterate over the intended children, since sometimes we end up
- * handling that hint while processing hints for one of the SVG frame's
- * ancestor frames.
- *
- * The reason that we sometimes end up trying to process the hint for an
- * ancestor of the SVG frame that the hint is intended for is due to the way we
- * process restyle events. ApplyRenderingChangeToTree adjusts the frame from
- * the restyled element's principle frame to one of its ancestor frames based
- * on what nsCSSRendering::FindBackground returns, since the background style
- * may have been propagated up to an ancestor frame. Processing hints using an
- * ancestor frame is fine in general, but nsChangeHint_ChildrenOnlyTransform is
- * a special case since it is intended to update the children of a specific
- * frame.
- */
-static nsIFrame*
-GetFrameForChildrenOnlyTransformHint(nsIFrame *aFrame)
-{
-  if (aFrame->GetType() == nsGkAtoms::viewportFrame) {
-    // This happens if the root-<svg> is fixed positioned, in which case we
-    // can't use aFrame->GetContent() to find the primary frame, since
-    // GetContent() returns nullptr for ViewportFrame.
-    aFrame = aFrame->GetFirstPrincipalChild();
-  }
-  // For an nsHTMLScrollFrame, this will get the SVG frame that has the
-  // children-only transforms:
-  aFrame = aFrame->GetContent()->GetPrimaryFrame();
-  if (aFrame->GetType() == nsGkAtoms::svgOuterSVGFrame) {
-    aFrame = aFrame->GetFirstPrincipalChild();
-    NS_ABORT_IF_FALSE(aFrame->GetType() == nsGkAtoms::svgOuterSVGAnonChildFrame,
-                      "Where is the nsSVGOuterSVGFrame's anon child??");
-  }
-  NS_ABORT_IF_FALSE(aFrame->IsFrameOfType(nsIFrame::eSVG |
-                                          nsIFrame::eSVGContainer),
-                    "Children-only transforms only expected on SVG frames");
-  return aFrame;
-}
-
-static void
-DoApplyRenderingChangeToTree(nsIFrame* aFrame,
-                             nsFrameManager* aFrameManager,
-                             nsChangeHint aChange)
-{
-  NS_PRECONDITION(gInApplyRenderingChangeToTree,
-                  "should only be called within ApplyRenderingChangeToTree");
-
-  for ( ; aFrame; aFrame = nsLayoutUtils::GetNextContinuationOrSpecialSibling(aFrame)) {
-    // Invalidate and sync views on all descendant frames, following placeholders.
-    // We don't need to update transforms in SyncViewsAndInvalidateDescendants, because
-    // there can't be any out-of-flows or popups that need to be transformed;
-    // all out-of-flow descendants of the transformed element must also be
-    // descendants of the transformed frame.
-    SyncViewsAndInvalidateDescendants(aFrame, aFrameManager,
-      nsChangeHint(aChange & (nsChangeHint_RepaintFrame |
-                              nsChangeHint_SyncFrameView |
-                              nsChangeHint_UpdateOpacityLayer)));
-    // This must be set to true if the rendering change needs to
-    // invalidate content.  If it's false, a composite-only paint
-    // (empty transaction) will be scheduled.
-    bool needInvalidatingPaint = false;
-
-    // if frame has view, will already be invalidated
-    if (aChange & nsChangeHint_RepaintFrame) {
-      // Note that this whole block will be skipped when painting is suppressed
-      // (due to our caller ApplyRendingChangeToTree() discarding the
-      // nsChangeHint_RepaintFrame hint).  If you add handling for any other
-      // hints within this block, be sure that they too should be ignored when
-      // painting is suppressed.
-      needInvalidatingPaint = true;
-      aFrame->InvalidateFrameSubtree();
-      if (aChange & nsChangeHint_UpdateEffects &&
-          aFrame->IsFrameOfType(nsIFrame::eSVG) &&
-          !(aFrame->GetStateBits() & NS_STATE_IS_OUTER_SVG)) {
-        // Need to update our overflow rects:
-        nsSVGUtils::ScheduleReflowSVG(aFrame);
-      }
-    }
-    if (aChange & nsChangeHint_UpdateTextPath) {
-      if (aFrame->GetType() == nsGkAtoms::svgTextPathFrame) {
-        // Invalidate and reflow the entire nsSVGTextFrame:
-        static_cast<nsSVGTextPathFrame*>(aFrame)->NotifyGlyphMetricsChange();
-      } else if (aFrame->IsSVGText()) {
-        // Invalidate and reflow the entire nsSVGTextFrame2:
-        NS_ASSERTION(aFrame->GetContent()->IsSVG(nsGkAtoms::textPath),
-                     "expected frame for a <textPath> element");
-        nsIFrame* text = nsLayoutUtils::GetClosestFrameOfType(
-                                                      aFrame,
-                                                      nsGkAtoms::svgTextFrame2);
-        NS_ASSERTION(text, "expected to find an ancestor nsSVGTextFrame2");
-        static_cast<nsSVGTextFrame2*>(text)->NotifyGlyphMetricsChange();
-      } else {
-        NS_ABORT_IF_FALSE(false, "unexpected frame got "
-                                 "nsChangeHint_UpdateTextPath");
-      }
-    }
-    if (aChange & nsChangeHint_UpdateOpacityLayer) {
-      // FIXME/bug 796697: we can get away with empty transactions for
-      // opacity updates in many cases.
-      needInvalidatingPaint = true;
-      aFrame->MarkLayersActive(nsChangeHint_UpdateOpacityLayer);
-      if (nsSVGIntegrationUtils::UsingEffectsForFrame(aFrame)) {
-        // SVG effects paints the opacity without using
-        // nsDisplayOpacity. We need to invalidate manually.
-        aFrame->InvalidateFrameSubtree();
-      }
-    }
-    if ((aChange & nsChangeHint_UpdateTransformLayer) &&
-        aFrame->IsTransformed()) {
-      aFrame->MarkLayersActive(nsChangeHint_UpdateTransformLayer);
-      // If we're not already going to do an invalidating paint, see
-      // if we can get away with only updating the transform on a
-      // layer for this frame, and not scheduling an invalidating
-      // paint.
-      if (!needInvalidatingPaint) {
-        needInvalidatingPaint |= !aFrame->TryUpdateTransformOnly();
-      }
-    }
-    if (aChange & nsChangeHint_ChildrenOnlyTransform) {
-      needInvalidatingPaint = true;
-      nsIFrame* childFrame =
-        GetFrameForChildrenOnlyTransformHint(aFrame)->GetFirstPrincipalChild();
-      for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
-        childFrame->MarkLayersActive(nsChangeHint_UpdateTransformLayer);
-      }
-    }
-    aFrame->SchedulePaint(needInvalidatingPaint ?
-                          nsIFrame::PAINT_DEFAULT :
-                          nsIFrame::PAINT_COMPOSITE_ONLY);
-  }
-}
-
-static void
-ApplyRenderingChangeToTree(nsPresContext* aPresContext,
-                           nsIFrame* aFrame,
-                           nsChangeHint aChange)
-{
-  // We check StyleDisplay()->HasTransform() in addition to checking
-  // IsTransformed() since we can get here for some frames that don't support
-  // CSS transforms.
-  NS_ASSERTION(!(aChange & nsChangeHint_UpdateTransformLayer) ||
-               aFrame->IsTransformed() ||
-               aFrame->StyleDisplay()->HasTransformStyle(),
-               "Unexpected UpdateTransformLayer hint");
-
-  nsIPresShell *shell = aPresContext->PresShell();
-  if (shell->IsPaintingSuppressed()) {
-    // Don't allow synchronous rendering changes when painting is turned off.
-    aChange = NS_SubtractHint(aChange, nsChangeHint_RepaintFrame);
-    if (!aChange) {
-      return;
-    }
-  }
-
-  // If the frame's background is propagated to an ancestor, walk up to
-  // that ancestor.
-  nsStyleContext *bgSC;
-  while (!nsCSSRendering::FindBackground(aFrame, &bgSC)) {
-    aFrame = aFrame->GetParent();
-    NS_ASSERTION(aFrame, "root frame must paint");
-  }
-
-  // Trigger rendering updates by damaging this frame and any
-  // continuations of this frame.
-
-  // XXX this needs to detect the need for a view due to an opacity change and deal with it...
-
-#ifdef DEBUG
-  gInApplyRenderingChangeToTree = true;
-#endif
-  DoApplyRenderingChangeToTree(aFrame, shell->FrameManager(), aChange);
-#ifdef DEBUG
-  gInApplyRenderingChangeToTree = false;
-#endif
-}
-
 /**
  * This method invalidates the canvas when frames are removed or added for a
  * node that might have its background propagated to the canvas, i.e., a
  * document root node or an HTML BODY which is a child of the root node.
  *
  * @param aFrame a frame for a content node about to be removed or a frame that
  *               was just created for a content node that was inserted.
  */ 
@@ -7880,59 +7620,16 @@ InvalidateCanvasIfNeeded(nsIPresShell* p
   // XHTML or something), but chances are we want to.  Play it safe.
   // Invalidate the viewport.
 
   nsIFrame* rootFrame = presShell->GetRootFrame();
   rootFrame->InvalidateFrameSubtree();
 }
 
 nsresult
-nsCSSFrameConstructor::StyleChangeReflow(nsIFrame* aFrame,
-                                         nsChangeHint aHint)
-{
-  // If the frame hasn't even received an initial reflow, then don't
-  // send it a style-change reflow!
-  if (aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)
-    return NS_OK;
-
-#ifdef DEBUG
-  if (gNoisyContentUpdates) {
-    printf("nsCSSFrameConstructor::StyleChangeReflow: aFrame=");
-    nsFrame::ListTag(stdout, aFrame);
-    printf("\n");
-  }
-#endif
-
-  nsIPresShell::IntrinsicDirty dirtyType;
-  if (aHint & nsChangeHint_ClearDescendantIntrinsics) {
-    NS_ASSERTION(aHint & nsChangeHint_ClearAncestorIntrinsics,
-                 "Please read the comments in nsChangeHint.h");
-    dirtyType = nsIPresShell::eStyleChange;
-  } else if (aHint & nsChangeHint_ClearAncestorIntrinsics) {
-    dirtyType = nsIPresShell::eTreeChange;
-  } else {
-    dirtyType = nsIPresShell::eResize;
-  }
-
-  nsFrameState dirtyBits;
-  if (aHint & nsChangeHint_NeedDirtyReflow) {
-    dirtyBits = NS_FRAME_IS_DIRTY;
-  } else {
-    dirtyBits = NS_FRAME_HAS_DIRTY_CHILDREN;
-  }
-
-  do {
-    mPresShell->FrameNeedsReflow(aFrame, dirtyType, dirtyBits);
-    aFrame = nsLayoutUtils::GetNextContinuationOrSpecialSibling(aFrame);
-  } while (aFrame);
-
-  return NS_OK;
-}
-
-nsresult
 nsCSSFrameConstructor::CharacterDataChanged(nsIContent* aContent,
                                             CharacterDataChangeInfo* aInfo)
 {
   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
   nsresult      rv = NS_OK;
 
   if ((aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) &&
        !aContent->TextIsOnlyWhitespace()) ||
@@ -7994,534 +7691,16 @@ nsCSSFrameConstructor::CharacterDataChan
     if (haveFirstLetterStyle) {
       RecoverLetterFrames(block);
     }
   }
 
   return rv;
 }
 
-NS_DECLARE_FRAME_PROPERTY(ChangeListProperty, nullptr)
-
-/**
- * Return true if aFrame's subtree has placeholders for out-of-flow content
- * whose 'position' style's bit in aPositionMask is set.
- */
-static bool
-FrameHasPositionedPlaceholderDescendants(nsIFrame* aFrame, uint32_t aPositionMask)
-{
-  const nsIFrame::ChildListIDs skip(nsIFrame::kAbsoluteList |
-                                    nsIFrame::kFixedList);
-  for (nsIFrame::ChildListIterator lists(aFrame); !lists.IsDone(); lists.Next()) {
-    if (!skip.Contains(lists.CurrentID())) {
-      for (nsFrameList::Enumerator childFrames(lists.CurrentList());
-           !childFrames.AtEnd(); childFrames.Next()) {
-        nsIFrame* f = childFrames.get();
-        if (f->GetType() == nsGkAtoms::placeholderFrame) {
-          nsIFrame* outOfFlow = nsPlaceholderFrame::GetRealFrameForPlaceholder(f);
-          // If SVG text frames could appear here, they could confuse us since
-          // they ignore their position style ... but they can't.
-          NS_ASSERTION(!outOfFlow->IsSVGText(),
-                       "SVG text frames can't be out of flow");
-          if (aPositionMask & (1 << outOfFlow->StyleDisplay()->mPosition)) {
-            return true;
-          }
-        }
-        if (FrameHasPositionedPlaceholderDescendants(f, aPositionMask)) {
-          return true;
-        }
-      }
-    }
-  }
-  return false;
-}
-
-static bool
-NeedToReframeForAddingOrRemovingTransform(nsIFrame* aFrame)
-{
-  MOZ_STATIC_ASSERT(0 <= NS_STYLE_POSITION_ABSOLUTE &&
-                    NS_STYLE_POSITION_ABSOLUTE < 32, "Style constant out of range");
-  MOZ_STATIC_ASSERT(0 <= NS_STYLE_POSITION_FIXED &&
-                    NS_STYLE_POSITION_FIXED < 32, "Style constant out of range");
-
-  uint32_t positionMask;
-  // Don't call aFrame->IsPositioned here, since that returns true if
-  // the frame already has a transform, and we want to ignore that here
-  if (aFrame->IsAbsolutelyPositioned() ||
-      aFrame->IsRelativelyPositioned()) {
-    // This frame is a container for abs-pos descendants whether or not it
-    // has a transform.
-    // So abs-pos descendants are no problem; we only need to reframe if
-    // we have fixed-pos descendants.
-    positionMask = 1 << NS_STYLE_POSITION_FIXED;
-  } else {
-    // This frame may not be a container for abs-pos descendants already.
-    // So reframe if we have abs-pos or fixed-pos descendants.
-    positionMask = (1 << NS_STYLE_POSITION_FIXED) |
-        (1 << NS_STYLE_POSITION_ABSOLUTE);
-  }
-  for (nsIFrame* f = aFrame; f;
-       f = nsLayoutUtils::GetNextContinuationOrSpecialSibling(f)) {
-    if (FrameHasPositionedPlaceholderDescendants(f, positionMask)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-static nsIFrame*
-FindReflowRootFor(nsIFrame* aFrame)
-{
-  for (nsIFrame* f = aFrame; f; f = f->GetParent()) {
-    if (f->GetStateBits() & NS_FRAME_REFLOW_ROOT) {
-      return f;
-    }
-  }
-  return nullptr;
-}
-
-nsresult
-nsCSSFrameConstructor::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
-{
-  NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
-               "Someone forgot a script blocker");
-  int32_t count = aChangeList.Count();
-  if (!count)
-    return NS_OK;
-
-  PROFILER_LABEL("CSS", "ProcessRestyledFrames");
-
-  // Make sure to not rebuild quote or counter lists while we're
-  // processing restyles
-  BeginUpdate();
-
-  nsPresContext* presContext = mPresShell->GetPresContext();
-  FramePropertyTable* propTable = presContext->PropertyTable();
-
-  // Mark frames so that we skip frames that die along the way, bug 123049.
-  // A frame can be in the list multiple times with different hints. Further
-  // optmization is possible if nsStyleChangeList::AppendChange could coalesce
-  int32_t index = count;
-
-  while (0 <= --index) {
-    const nsStyleChangeData* changeData;
-    aChangeList.ChangeAt(index, &changeData);
-    if (changeData->mFrame) {
-      propTable->Set(changeData->mFrame, ChangeListProperty(),
-                     NS_INT32_TO_PTR(1));
-    }
-  }
-
-  index = count;
-
-  while (0 <= --index) {
-    nsIFrame* frame;
-    nsIContent* content;
-    bool didReflowThisFrame = false;
-    nsChangeHint hint;
-    aChangeList.ChangeAt(index, frame, content, hint);
-
-    NS_ASSERTION(!(hint & nsChangeHint_AllReflowHints) ||
-                 (hint & nsChangeHint_NeedReflow),
-                 "Reflow hint bits set without actually asking for a reflow");
-
-    // skip any frame that has been destroyed due to a ripple effect
-    if (frame && !propTable->Get(frame, ChangeListProperty())) {
-      continue;
-    }
-
-    if (frame && frame->GetContent() != content) {
-      // XXXbz this is due to image maps messing with the primary frame of
-      // <area>s.  See bug 135040.  Remove this block once that's fixed.
-      frame = nullptr;
-      if (!(hint & nsChangeHint_ReconstructFrame)) {
-        continue;
-      }
-    }
-
-    if (mPromoteReflowsToReframeRoot &&
-        (hint & (nsChangeHint_ReconstructFrame | nsChangeHint_NeedReflow))) {
-      nsIFrame* reflowRoot = FindReflowRootFor(frame);
-      if (!reflowRoot) {
-        // Reflow root is the viewport. Better reframe the document.
-        // We don't do this for elements which are inside a reflow root --- they
-        // should be OK.
-        nsIContent* root = mDocument->GetRootElement();
-        if (root) {
-          NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
-          content = root;
-        }
-      }
-    }
-
-    if ((hint & nsChangeHint_AddOrRemoveTransform) && frame &&
-        !(hint & nsChangeHint_ReconstructFrame)) {
-      if (NeedToReframeForAddingOrRemovingTransform(frame)) {
-        NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
-      } else {
-        // Normally frame construction would set state bits as needed,
-        // but we're not going to reconstruct the frame so we need to set them.
-        // It's because we need to set this state on each affected frame
-        // that we can't coalesce nsChangeHint_AddOrRemoveTransform hints up
-        // to ancestors (i.e. it can't be an inherited change hint).
-        if (frame->IsPositioned()) {
-          // If a transform has been added, we'll be taking this path,
-          // but we may be taking this path even if a transform has been
-          // removed. It's OK to add the bit even if it's not needed.
-          frame->AddStateBits(NS_FRAME_MAY_BE_TRANSFORMED);
-          if (!frame->IsAbsoluteContainer() &&
-              (frame->GetStateBits() & NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN)) {
-            frame->MarkAsAbsoluteContainingBlock();
-          }
-        } else {
-          // Don't remove NS_FRAME_MAY_BE_TRANSFORMED since it may still by
-          // transformed by other means. It's OK to have the bit even if it's
-          // not needed.
-          if (frame->IsAbsoluteContainer()) {
-            frame->MarkAsNotAbsoluteContainingBlock();
-          }
-        }
-      }
-    }
-    if (hint & nsChangeHint_ReconstructFrame) {
-      // If we ever start passing true here, be careful of restyles
-      // that involve a reframe and animations.  In particular, if the
-      // restyle we're processing here is an animation restyle, but
-      // the style resolution we will do for the frame construction
-      // happens async when we're not in an animation restyle already,
-      // problems could arise.
-      RecreateFramesForContent(content, false);
-    } else {
-      NS_ASSERTION(frame, "This shouldn't happen");
-
-      if ((frame->GetStateBits() & NS_FRAME_SVG_LAYOUT) &&
-          (frame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
-        // frame does not maintain overflow rects, so avoid calling
-        // FinishAndStoreOverflow on it:
-        hint = NS_SubtractHint(hint,
-                 NS_CombineHint(nsChangeHint_UpdateOverflow,
-                                nsChangeHint_ChildrenOnlyTransform));
-      }
-
-      if (hint & nsChangeHint_UpdateEffects) {
-        nsSVGEffects::UpdateEffects(frame);
-      }
-      if (hint & nsChangeHint_NeedReflow) {
-        StyleChangeReflow(frame, hint);
-        didReflowThisFrame = true;
-      }
-      if (hint & (nsChangeHint_RepaintFrame | nsChangeHint_SyncFrameView |
-                  nsChangeHint_UpdateOpacityLayer | nsChangeHint_UpdateTransformLayer |
-                  nsChangeHint_ChildrenOnlyTransform)) {
-        ApplyRenderingChangeToTree(presContext, frame, hint);
-      }
-      if ((hint & nsChangeHint_RecomputePosition) && !didReflowThisFrame) {
-        // It is possible for this to fall back to a reflow
-        if (!RecomputePosition(frame)) {
-          didReflowThisFrame = true;
-        }
-      }
-      NS_ASSERTION(!(hint & nsChangeHint_ChildrenOnlyTransform) ||
-                   (hint & nsChangeHint_UpdateOverflow),
-                   "nsChangeHint_UpdateOverflow should be passed too");
-      if ((hint & nsChangeHint_UpdateOverflow) && !didReflowThisFrame) {
-        if (hint & nsChangeHint_ChildrenOnlyTransform) {
-          // The overflow areas of the child frames need to be updated:
-          nsIFrame* hintFrame = GetFrameForChildrenOnlyTransformHint(frame);
-          nsIFrame* childFrame = hintFrame->GetFirstPrincipalChild();
-          for ( ; childFrame; childFrame = childFrame->GetNextSibling()) {
-            NS_ABORT_IF_FALSE(childFrame->IsFrameOfType(nsIFrame::eSVG),
-                              "Not expecting non-SVG children");
-            // If |childFrame| is dirty or has dirty children, we don't bother
-            // updating overflows since that will happen when it's reflowed.
-            if (!(childFrame->GetStateBits() &
-                  (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
-              mOverflowChangedTracker.AddFrame(childFrame);
-            }
-            NS_ASSERTION(!nsLayoutUtils::GetNextContinuationOrSpecialSibling(childFrame),
-                         "SVG frames should not have continuations or special siblings");
-            NS_ASSERTION(childFrame->GetParent() == hintFrame,
-                         "SVG child frame not expected to have different parent");
-          }
-        }
-        // If |frame| is dirty or has dirty children, we don't bother updating
-        // overflows since that will happen when it's reflowed.
-        if (!(frame->GetStateBits() &
-              (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
-          while (frame) {
-            mOverflowChangedTracker.AddFrame(frame);
-
-            frame =
-              nsLayoutUtils::GetNextContinuationOrSpecialSibling(frame);
-          }
-        }
-      }
-      if (hint & nsChangeHint_UpdateCursor) {
-        mPresShell->SynthesizeMouseMove(false);
-      }
-    }
-  }
-
-  EndUpdate();
-
-  // cleanup references and verify the style tree.  Note that the latter needs
-  // to happen once we've processed the whole list, since until then the tree
-  // is not in fact in a consistent state.
-  index = count;
-  while (0 <= --index) {
-    const nsStyleChangeData* changeData;
-    aChangeList.ChangeAt(index, &changeData);
-    if (changeData->mFrame) {
-      propTable->Delete(changeData->mFrame, ChangeListProperty());
-    }
-
-#ifdef DEBUG
-    // reget frame from content since it may have been regenerated...
-    if (changeData->mContent) {
-      if (!nsAnimationManager::ContentOrAncestorHasAnimation(changeData->mContent) &&
-          !nsTransitionManager::ContentOrAncestorHasTransition(changeData->mContent)) {
-        nsIFrame* frame = changeData->mContent->GetPrimaryFrame();
-        if (frame) {
-          DebugVerifyStyleTree(frame);
-        }
-      }
-    } else if (!changeData->mFrame ||
-               changeData->mFrame->GetType() != nsGkAtoms::viewportFrame) {
-      NS_WARNING("Unable to test style tree integrity -- no content node "
-                 "(and not a viewport frame)");
-    }
-#endif
-  }
-
-  aChangeList.Clear();
-  return NS_OK;
-}
-
-void
-nsCSSFrameConstructor::RestyleElement(Element        *aElement,
-                                      nsIFrame       *aPrimaryFrame,
-                                      nsChangeHint   aMinHint,
-                                      RestyleTracker& aRestyleTracker,
-                                      bool            aRestyleDescendants)
-{
-  NS_ASSERTION(aPrimaryFrame == aElement->GetPrimaryFrame(),
-               "frame/content mismatch");
-  if (aPrimaryFrame && aPrimaryFrame->GetContent() != aElement) {
-    // XXXbz this is due to image maps messing with the primary frame pointer
-    // of <area>s.  See bug 135040.  We can remove this block once that's fixed.
-    aPrimaryFrame = nullptr;
-  }
-  NS_ASSERTION(!aPrimaryFrame || aPrimaryFrame->GetContent() == aElement,
-               "frame/content mismatch");
-
-  // If we're restyling the root element and there are 'rem' units in
-  // use, handle dynamic changes to the definition of a 'rem' here.
-  if (GetPresContext()->UsesRootEMUnits() && aPrimaryFrame) {
-    nsStyleContext *oldContext = aPrimaryFrame->StyleContext();
-    if (!oldContext->GetParent()) { // check that we're the root element
-      nsRefPtr<nsStyleContext> newContext = mPresShell->StyleSet()->
-        ResolveStyleFor(aElement, nullptr /* == oldContext->GetParent() */);
-      if (oldContext->StyleFont()->mFont.size !=
-          newContext->StyleFont()->mFont.size) {
-        // The basis for 'rem' units has changed.
-        newContext = nullptr;
-        DoRebuildAllStyleData(aRestyleTracker, nsChangeHint(0));
-        if (aMinHint == 0) {
-          return;
-        }
-        aPrimaryFrame = aElement->GetPrimaryFrame();
-      }
-    }
-  }
-
-  if (aMinHint & nsChangeHint_ReconstructFrame) {
-    RecreateFramesForContent(aElement, false);
-  } else if (aPrimaryFrame) {
-    nsStyleChangeList changeList;
-    ComputeStyleChangeFor(aPrimaryFrame, &changeList, aMinHint,
-                          aRestyleTracker, aRestyleDescendants);
-    ProcessRestyledFrames(changeList);
-  } else {
-    // no frames, reconstruct for content
-    MaybeRecreateFramesForElement(aElement);
-  }
-}
-
-nsresult
-nsCSSFrameConstructor::ContentStateChanged(nsIContent* aContent,
-                                           nsEventStates aStateMask)
-{
-  // XXXbz it would be good if this function only took Elements, but
-  // we'd have to make ESM guarantee that usefully.
-  if (!aContent->IsElement()) {
-    return NS_OK;
-  }
-
-  Element* aElement = aContent->AsElement();
-
-  nsStyleSet *styleSet = mPresShell->StyleSet();
-  nsPresContext *presContext = mPresShell->GetPresContext();
-  NS_ASSERTION(styleSet, "couldn't get style set");
-
-  nsChangeHint hint = NS_STYLE_HINT_NONE;
-  // Any change to a content state that affects which frames we construct
-  // must lead to a frame reconstruct here if we already have a frame.
-  // Note that we never decide through non-CSS means to not create frames
-  // based on content states, so if we already don't have a frame we don't
-  // need to force a reframe -- if it's needed, the HasStateDependentStyle
-  // call will handle things.
-  nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
-  if (primaryFrame) {
-    // If it's generated content, ignore LOADING/etc state changes on it.
-    if (!primaryFrame->IsGeneratedContentFrame() &&
-        aStateMask.HasAtLeastOneOfStates(NS_EVENT_STATE_BROKEN |
-                                         NS_EVENT_STATE_USERDISABLED |
-                                         NS_EVENT_STATE_SUPPRESSED |
-                                         NS_EVENT_STATE_LOADING)) {
-      hint = nsChangeHint_ReconstructFrame;
-    } else {
-      uint8_t app = primaryFrame->StyleDisplay()->mAppearance;
-      if (app) {
-        nsITheme *theme = presContext->GetTheme();
-        if (theme && theme->ThemeSupportsWidget(presContext,
-                                                primaryFrame, app)) {
-          bool repaint = false;
-          theme->WidgetStateChanged(primaryFrame, app, nullptr, &repaint);
-          if (repaint) {
-            NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
-          }
-        }
-      }
-    }
-
-    primaryFrame->ContentStatesChanged(aStateMask);
-  }
-
-
-  nsRestyleHint rshint = 
-    styleSet->HasStateDependentStyle(presContext, aElement, aStateMask);
-      
-  if (aStateMask.HasState(NS_EVENT_STATE_HOVER) && rshint != 0) {
-    ++mHoverGeneration;
-  }
-
-  if (aStateMask.HasState(NS_EVENT_STATE_VISITED)) {
-    // Exposing information to the page about whether the link is
-    // visited or not isn't really something we can worry about here.
-    // FIXME: We could probably do this a bit better.
-    NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
-  }
-
-  PostRestyleEvent(aElement, rshint, hint);
-  return NS_OK;
-}
-
-void
-nsCSSFrameConstructor::AttributeWillChange(Element* aElement,
-                                           int32_t aNameSpaceID,
-                                           nsIAtom* aAttribute,
-                                           int32_t aModType)
-{
-  nsRestyleHint rshint =
-    mPresShell->StyleSet()->HasAttributeDependentStyle(mPresShell->GetPresContext(),
-                                                       aElement,
-                                                       aAttribute,
-                                                       aModType,
-                                                       false);
-  PostRestyleEvent(aElement, rshint, NS_STYLE_HINT_NONE);
-}
-
-void
-nsCSSFrameConstructor::AttributeChanged(Element* aElement,
-                                        int32_t aNameSpaceID,
-                                        nsIAtom* aAttribute,
-                                        int32_t aModType)
-{
-  // Hold onto the PresShell to prevent ourselves from being destroyed.
-  // XXXbz how, exactly, would this attribute change cause us to be
-  // destroyed from inside this function?
-  nsCOMPtr<nsIPresShell> shell = mPresShell;
-
-  // Get the frame associated with the content which is the highest in the frame tree
-  nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
-
-#if 0
-  NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
-     ("HTMLStyleSheet::AttributeChanged: content=%p[%s] frame=%p",
-      aContent, ContentTag(aElement, 0), frame));
-#endif
-
-  // the style tag has its own interpretation based on aHint 
-  nsChangeHint hint = aElement->GetAttributeChangeHint(aAttribute, aModType);
-
-  bool reframe = (hint & nsChangeHint_ReconstructFrame) != 0;
-
-#ifdef MOZ_XUL
-  // The following listbox widget trap prevents offscreen listbox widget
-  // content from being removed and re-inserted (which is what would
-  // happen otherwise).
-  if (!primaryFrame && !reframe) {
-    int32_t namespaceID;
-    nsIAtom* tag =
-      mDocument->BindingManager()->ResolveTag(aElement, &namespaceID);
-
-    if (namespaceID == kNameSpaceID_XUL &&
-        (tag == nsGkAtoms::listitem ||
-         tag == nsGkAtoms::listcell))
-      return;
-  }
-
-  if (aAttribute == nsGkAtoms::tooltiptext ||
-      aAttribute == nsGkAtoms::tooltip) 
-  {
-    nsIRootBox* rootBox = nsIRootBox::GetRootBox(mPresShell);
-    if (rootBox) {
-      if (aModType == nsIDOMMutationEvent::REMOVAL)
-        rootBox->RemoveTooltipSupport(aElement);
-      if (aModType == nsIDOMMutationEvent::ADDITION)
-        rootBox->AddTooltipSupport(aElement);
-    }
-  }
-
-#endif // MOZ_XUL
-
-  if (primaryFrame) {
-    // See if we have appearance information for a theme.
-    const nsStyleDisplay* disp = primaryFrame->StyleDisplay();
-    if (disp->mAppearance) {
-      nsPresContext* presContext = mPresShell->GetPresContext();
-      nsITheme *theme = presContext->GetTheme();
-      if (theme && theme->ThemeSupportsWidget(presContext, primaryFrame, disp->mAppearance)) {
-        bool repaint = false;
-        theme->WidgetStateChanged(primaryFrame, disp->mAppearance, aAttribute, &repaint);
-        if (repaint)
-          NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
-      }
-    }
-   
-    // let the frame deal with it now, so we don't have to deal later
-    primaryFrame->AttributeChanged(aNameSpaceID, aAttribute, aModType);
-    // XXXwaterson should probably check for special IB siblings
-    // here, and propagate the AttributeChanged notification to
-    // them, as well. Currently, inline frames don't do anything on
-    // this notification, so it's not that big a deal.
-  }
-
-  // See if we can optimize away the style re-resolution -- must be called after
-  // the frame's AttributeChanged() in case it does something that affects the style
-  nsRestyleHint rshint =
-    mPresShell->StyleSet()->HasAttributeDependentStyle(mPresShell->GetPresContext(),
-                                                       aElement,
-                                                       aAttribute,
-                                                       aModType,
-                                                       true);
-
-  PostRestyleEvent(aElement, rshint, hint);
-}
-
 void
 nsCSSFrameConstructor::BeginUpdate() {
   NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
                "Someone forgot a script blocker");
 
   nsRootPresContext* rootPresContext =
     mPresShell->GetPresContext()->GetRootPresContext();
   if (rootPresContext) {
@@ -8572,18 +7751,19 @@ nsCSSFrameConstructor::WillDestroyFrameT
 
   mIsDestroyingFrameTree = true;
 
   // Prevent frame tree destruction from being O(N^2)
   mQuoteList.Clear();
   mCounterManager.Clear();
 
   // Remove our presshell as a style flush observer.  But leave
-  // mObservingRefreshDriver true so we don't readd to it even if someone tries
-  // to post restyle events on us from this point on for some reason.
+  // RestyleManager::mObservingRefreshDriver true so we don't readd to
+  // it even if someone tries to post restyle events on us from this
+  // point on for some reason.
   mPresShell->GetPresContext()->RefreshDriver()->
     RemoveStyleFlushObserver(mPresShell);
 
   nsFrameManager::Destroy();
 }
 
 //STATIC
 
@@ -11695,468 +10875,16 @@ nsCSSFrameConstructor::ReframeContaining
     }
   }
 
   // If we get here, we're screwed!
   return RecreateFramesForContent(mPresShell->GetDocument()->GetRootElement(),
 				  true);
 }
 
-void
-nsCSSFrameConstructor::RestyleForEmptyChange(Element* aContainer)
-{
-  // In some cases (:empty + E, :empty ~ E), a change if the content of
-  // an element requires restyling its parent's siblings.
-  nsRestyleHint hint = eRestyle_Subtree;
-  nsIContent* grandparent = aContainer->GetParent();
-  if (grandparent &&
-      (grandparent->GetFlags() & NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS)) {
-    hint = nsRestyleHint(hint | eRestyle_LaterSiblings);
-  }
-  PostRestyleEvent(aContainer, hint, NS_STYLE_HINT_NONE);
-}
-
-void
-nsCSSFrameConstructor::RestyleForAppend(Element* aContainer,
-                                        nsIContent* aFirstNewContent)
-{
-  NS_ASSERTION(aContainer, "must have container for append");
-#ifdef DEBUG
-  {
-    for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) {
-      NS_ASSERTION(!cur->IsRootOfAnonymousSubtree(),
-                   "anonymous nodes should not be in child lists");
-    }
-  }
-#endif
-  uint32_t selectorFlags =
-    aContainer->GetFlags() & (NODE_ALL_SELECTOR_FLAGS &
-                              ~NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS);
-  if (selectorFlags == 0)
-    return;
-
-  if (selectorFlags & NODE_HAS_EMPTY_SELECTOR) {
-    // see whether we need to restyle the container
-    bool wasEmpty = true; // :empty or :-moz-only-whitespace
-    for (nsIContent* cur = aContainer->GetFirstChild();
-         cur != aFirstNewContent;
-         cur = cur->GetNextSibling()) {
-      // We don't know whether we're testing :empty or :-moz-only-whitespace,
-      // so be conservative and assume :-moz-only-whitespace (i.e., make
-      // IsSignificantChild less likely to be true, and thus make us more
-      // likely to restyle).
-      if (nsStyleUtil::IsSignificantChild(cur, true, false)) {
-        wasEmpty = false;
-        break;
-      }
-    }
-    if (wasEmpty) {
-      RestyleForEmptyChange(aContainer);
-      return;
-    }
-  }
-
-  if (selectorFlags & NODE_HAS_SLOW_SELECTOR) {
-    PostRestyleEvent(aContainer, eRestyle_Subtree, NS_STYLE_HINT_NONE);
-    // Restyling the container is the most we can do here, so we're done.
-    return;
-  }
-
-  if (selectorFlags & NODE_HAS_EDGE_CHILD_SELECTOR) {
-    // restyle the last element child before this node
-    for (nsIContent* cur = aFirstNewContent->GetPreviousSibling();
-         cur;
-         cur = cur->GetPreviousSibling()) {
-      if (cur->IsElement()) {
-        PostRestyleEvent(cur->AsElement(), eRestyle_Subtree, NS_STYLE_HINT_NONE);
-        break;
-      }
-    }
-  }
-}
-
-// Needed since we can't use PostRestyleEvent on non-elements (with
-// eRestyle_LaterSiblings or nsRestyleHint(eRestyle_Subtree |
-// eRestyle_LaterSiblings) as appropriate).
-static void
-RestyleSiblingsStartingWith(nsCSSFrameConstructor *aFrameConstructor,
-                            nsIContent *aStartingSibling /* may be null */)
-{
-  for (nsIContent *sibling = aStartingSibling; sibling;
-       sibling = sibling->GetNextSibling()) {
-    if (sibling->IsElement()) {
-      aFrameConstructor->
-        PostRestyleEvent(sibling->AsElement(),
-                         nsRestyleHint(eRestyle_Subtree | eRestyle_LaterSiblings),
-                         NS_STYLE_HINT_NONE);
-      break;
-    }
-  }
-}
-
-// Restyling for a ContentInserted or CharacterDataChanged notification.
-// This could be used for ContentRemoved as well if we got the
-// notification before the removal happened (and sometimes
-// CharacterDataChanged is more like a removal than an addition).
-// The comments are written and variables are named in terms of it being
-// a ContentInserted notification.
-void
-nsCSSFrameConstructor::RestyleForInsertOrChange(Element* aContainer,
-                                                nsIContent* aChild)
-{
-  NS_ASSERTION(!aChild->IsRootOfAnonymousSubtree(),
-               "anonymous nodes should not be in child lists");
-  uint32_t selectorFlags =
-    aContainer ? (aContainer->GetFlags() & NODE_ALL_SELECTOR_FLAGS) : 0;
-  if (selectorFlags == 0)
-    return;
-
-  if (selectorFlags & NODE_HAS_EMPTY_SELECTOR) {
-    // see whether we need to restyle the container
-    bool wasEmpty = true; // :empty or :-moz-only-whitespace
-    for (nsIContent* child = aContainer->GetFirstChild();
-         child;
-         child = child->GetNextSibling()) {
-      if (child == aChild)
-        continue;
-      // We don't know whether we're testing :empty or :-moz-only-whitespace,
-      // so be conservative and assume :-moz-only-whitespace (i.e., make
-      // IsSignificantChild less likely to be true, and thus make us more
-      // likely to restyle).
-      if (nsStyleUtil::IsSignificantChild(child, true, false)) {
-        wasEmpty = false;
-        break;
-      }
-    }
-    if (wasEmpty) {
-      RestyleForEmptyChange(aContainer);
-      return;
-    }
-  }
-
-  if (selectorFlags & NODE_HAS_SLOW_SELECTOR) {
-    PostRestyleEvent(aContainer, eRestyle_Subtree, NS_STYLE_HINT_NONE);
-    // Restyling the container is the most we can do here, so we're done.
-    return;
-  }
-
-  if (selectorFlags & NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS) {
-    // Restyle all later siblings.
-    RestyleSiblingsStartingWith(this, aChild->GetNextSibling());
-  }
-
-  if (selectorFlags & NODE_HAS_EDGE_CHILD_SELECTOR) {
-    // restyle the previously-first element child if it is after this node
-    bool passedChild = false;
-    for (nsIContent* content = aContainer->GetFirstChild();
-         content;
-         content = content->GetNextSibling()) {
-      if (content == aChild) {
-        passedChild = true;
-        continue;
-      }
-      if (content->IsElement()) {
-        if (passedChild) {
-          PostRestyleEvent(content->AsElement(), eRestyle_Subtree,
-                           NS_STYLE_HINT_NONE);
-        }
-        break;
-      }
-    }
-    // restyle the previously-last element child if it is before this node
-    passedChild = false;
-    for (nsIContent* content = aContainer->GetLastChild();
-         content;
-         content = content->GetPreviousSibling()) {
-      if (content == aChild) {
-        passedChild = true;
-        continue;
-      }
-      if (content->IsElement()) {
-        if (passedChild) {
-          PostRestyleEvent(content->AsElement(), eRestyle_Subtree,
-                           NS_STYLE_HINT_NONE);
-        }
-        break;
-      }
-    }
-  }
-}
-
-void
-nsCSSFrameConstructor::RestyleForRemove(Element* aContainer,
-                                        nsIContent* aOldChild,
-                                        nsIContent* aFollowingSibling)
-{
-  if (aOldChild->IsRootOfAnonymousSubtree()) {
-    // This should be an assert, but this is called incorrectly in
-    // nsHTMLEditor::DeleteRefToAnonymousNode and the assertions were clogging
-    // up the logs.  Make it an assert again when that's fixed.
-    NS_WARNING("anonymous nodes should not be in child lists (bug 439258)");
-  }
-  uint32_t selectorFlags =
-    aContainer ? (aContainer->GetFlags() & NODE_ALL_SELECTOR_FLAGS) : 0;
-  if (selectorFlags == 0)
-    return;
-
-  if (selectorFlags & NODE_HAS_EMPTY_SELECTOR) {
-    // see whether we need to restyle the container
-    bool isEmpty = true; // :empty or :-moz-only-whitespace
-    for (nsIContent* child = aContainer->GetFirstChild();
-         child;
-         child = child->GetNextSibling()) {
-      // We don't know whether we're testing :empty or :-moz-only-whitespace,
-      // so be conservative and assume :-moz-only-whitespace (i.e., make
-      // IsSignificantChild less likely to be true, and thus make us more
-      // likely to restyle).
-      if (nsStyleUtil::IsSignificantChild(child, true, false)) {
-        isEmpty = false;
-        break;
-      }
-    }
-    if (isEmpty) {
-      RestyleForEmptyChange(aContainer);
-      return;
-    }
-  }
-
-  if (selectorFlags & NODE_HAS_SLOW_SELECTOR) {
-    PostRestyleEvent(aContainer, eRestyle_Subtree, NS_STYLE_HINT_NONE);
-    // Restyling the container is the most we can do here, so we're done.
-    return;
-  }
-
-  if (selectorFlags & NODE_HAS_SLOW_SELECTOR_LATER_SIBLINGS) {
-    // Restyle all later siblings.
-    RestyleSiblingsStartingWith(this, aFollowingSibling);
-  }
-
-  if (selectorFlags & NODE_HAS_EDGE_CHILD_SELECTOR) {
-    // restyle the now-first element child if it was after aOldChild
-    bool reachedFollowingSibling = false;
-    for (nsIContent* content = aContainer->GetFirstChild();
-         content;
-         content = content->GetNextSibling()) {
-      if (content == aFollowingSibling) {
-        reachedFollowingSibling = true;
-        // do NOT continue here; we might want to restyle this node
-      }
-      if (content->IsElement()) {
-        if (reachedFollowingSibling) {
-          PostRestyleEvent(content->AsElement(), eRestyle_Subtree,
-                           NS_STYLE_HINT_NONE);
-        }
-        break;
-      }
-    }
-    // restyle the now-last element child if it was before aOldChild
-    reachedFollowingSibling = (aFollowingSibling == nullptr);
-    for (nsIContent* content = aContainer->GetLastChild();
-         content;
-         content = content->GetPreviousSibling()) {
-      if (content->IsElement()) {
-        if (reachedFollowingSibling) {
-          PostRestyleEvent(content->AsElement(), eRestyle_Subtree, NS_STYLE_HINT_NONE);
-        }
-        break;
-      }
-      if (content == aFollowingSibling) {
-        reachedFollowingSibling = true;
-      }
-    }
-  }
-}
-
-
-void
-nsCSSFrameConstructor::RebuildAllStyleData(nsChangeHint aExtraHint)
-{
-  NS_ASSERTION(!(aExtraHint & nsChangeHint_ReconstructFrame),
-               "Should not reconstruct the root of the frame tree.  "
-               "Use ReconstructDocElementHierarchy instead.");
-
-  mRebuildAllStyleData = false;
-  NS_UpdateHint(aExtraHint, mRebuildAllExtraHint);
-  mRebuildAllExtraHint = nsChangeHint(0);
-
-  if (!mPresShell || !mPresShell->GetRootFrame())
-    return;
-
-  // Make sure that the viewmanager will outlive the presshell
-  nsRefPtr<nsViewManager> vm = mPresShell->GetViewManager();
-
-  // Processing the style changes could cause a flush that propagates to
-  // the parent frame and thus destroys the pres shell.
-  nsCOMPtr<nsIPresShell> kungFuDeathGrip(mPresShell);
-
-  // We may reconstruct frames below and hence process anything that is in the
-  // tree. We don't want to get notified to process those items again after.
-  mPresShell->GetDocument()->FlushPendingNotifications(Flush_ContentAndNotify);
-
-  nsAutoScriptBlocker scriptBlocker;
-
-  nsPresContext *presContext = mPresShell->GetPresContext();
-  presContext->SetProcessingRestyles(true);
-
-  DoRebuildAllStyleData(mPendingRestyles, aExtraHint);
-
-  presContext->SetProcessingRestyles(false);
-
-  // Make sure that we process any pending animation restyles from the
-  // above style change.  Note that we can *almost* implement the above
-  // by just posting a style change -- except we really need to restyle
-  // the root frame rather than the root element's primary frame.
-  ProcessPendingRestyles();
-}
-
-void
-nsCSSFrameConstructor::DoRebuildAllStyleData(RestyleTracker& aRestyleTracker,
-                                             nsChangeHint aExtraHint)
-{
-  // Tell the style set to get the old rule tree out of the way
-  // so we can recalculate while maintaining rule tree immutability
-  nsresult rv = mPresShell->StyleSet()->BeginReconstruct();
-  if (NS_FAILED(rv)) {
-    return;
-  }
-
-  // Recalculate all of the style contexts for the document
-  // Note that we can ignore the return value of ComputeStyleChangeFor
-  // because we never need to reframe the root frame
-  // XXX This could be made faster by not rerunning rule matching
-  // (but note that nsPresShell::SetPreferenceStyleRules currently depends
-  // on us re-running rule matching here
-  nsStyleChangeList changeList;
-  // XXX Does it matter that we're passing aExtraHint to the real root
-  // frame and not the root node's primary frame?
-  // Note: The restyle tracker we pass in here doesn't matter.
-  ComputeStyleChangeFor(mPresShell->GetRootFrame(),
-                        &changeList, aExtraHint,
-                        aRestyleTracker, true);
-  // Process the required changes
-  ProcessRestyledFrames(changeList);
-  FlushOverflowChangedTracker();
-
-  // Tell the style set it's safe to destroy the old rule tree.  We
-  // must do this after the ProcessRestyledFrames call in case the
-  // change list has frame reconstructs in it (since frames to be
-  // reconstructed will still have their old style context pointers
-  // until they are destroyed).
-  mPresShell->StyleSet()->EndReconstruct();
-}
-
-void
-nsCSSFrameConstructor::ProcessPendingRestyles()
-{
-  NS_PRECONDITION(mDocument, "No document?  Pshaw!");
-  NS_PRECONDITION(!nsContentUtils::IsSafeToRunScript(),
-                  "Missing a script blocker!");
-
-  // Process non-animation restyles...
-  nsPresContext *presContext = mPresShell->GetPresContext();
-  NS_ABORT_IF_FALSE(!presContext->IsProcessingRestyles(),
-                    "Nesting calls to ProcessPendingRestyles?");
-  presContext->SetProcessingRestyles(true);
-
-  // Before we process any restyles, we need to ensure that style
-  // resulting from any throttled animations (animations that we're
-  // running entirely on the compositor thread) is up-to-date, so that
-  // if any style changes we cause trigger transitions, we have the
-  // correct old style for starting the transition.
-  if (nsLayoutUtils::AreAsyncAnimationsEnabled() &&
-      mPendingRestyles.Count() > 0) {
-    ++mAnimationGeneration;
-    presContext->TransitionManager()->UpdateAllThrottledStyles();
-  }
-
-  mPendingRestyles.ProcessRestyles();
-
-#ifdef DEBUG
-  uint32_t oldPendingRestyleCount = mPendingRestyles.Count();
-#endif
-
-  // ...and then process animation restyles.  This needs to happen
-  // second because we need to start animations that resulted from the
-  // first set of restyles (e.g., CSS transitions with negative
-  // transition-delay), and because we need to immediately
-  // restyle-with-animation any just-restyled elements that are
-  // mid-transition (since processing the non-animation restyle ignores
-  // the running transition so it can check for a new change on the same
-  // property, and then posts an immediate animation style change).
-  presContext->SetProcessingAnimationStyleChange(true);
-  mPendingAnimationRestyles.ProcessRestyles();
-  presContext->SetProcessingAnimationStyleChange(false);
-
-  presContext->SetProcessingRestyles(false);
-  NS_POSTCONDITION(mPendingRestyles.Count() == oldPendingRestyleCount,
-                   "We should not have posted new non-animation restyles while "
-                   "processing animation restyles");
-
-  if (mRebuildAllStyleData) {
-    // We probably wasted a lot of work up above, but this seems safest
-    // and it should be rarely used.
-    // This might add us as a refresh observer again; that's ok.
-    RebuildAllStyleData(nsChangeHint(0));
-  }
-}
-
-void
-nsCSSFrameConstructor::PostRestyleEventCommon(Element* aElement,
-                                              nsRestyleHint aRestyleHint,
-                                              nsChangeHint aMinChangeHint,
-                                              bool aForAnimation)
-{
-  if (MOZ_UNLIKELY(mPresShell->IsDestroying())) {
-    return;
-  }
-
-  if (aRestyleHint == 0 && !aMinChangeHint) {
-    // Nothing to do here
-    return;
-  }
-
-  RestyleTracker& tracker =
-    aForAnimation ? mPendingAnimationRestyles : mPendingRestyles;
-  tracker.AddPendingRestyle(aElement, aRestyleHint, aMinChangeHint);
-
-  PostRestyleEventInternal(false);
-}
-    
-void
-nsCSSFrameConstructor::PostRestyleEventInternal(bool aForLazyConstruction)
-{
-  // Make sure we're not in a style refresh; if we are, we still have
-  // a call to ProcessPendingRestyles coming and there's no need to
-  // add ourselves as a refresh observer until then.
-  bool inRefresh = !aForLazyConstruction && mInStyleRefresh;
-  if (!mObservingRefreshDriver && !inRefresh) {
-    mObservingRefreshDriver = mPresShell->GetPresContext()->RefreshDriver()->
-      AddStyleFlushObserver(mPresShell);
-  }
-
-  // Unconditionally flag our document as needing a flush.  The other
-  // option here would be a dedicated boolean to track whether we need
-  // to do so (set here and unset in ProcessPendingRestyles).
-  mPresShell->GetDocument()->SetNeedStyleFlush();
-}
-
-void
-nsCSSFrameConstructor::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint)
-{
-  NS_ASSERTION(!(aExtraHint & nsChangeHint_ReconstructFrame),
-               "Should not reconstruct the root of the frame tree.  "
-               "Use ReconstructDocElementHierarchy instead.");
-
-  mRebuildAllStyleData = true;
-  NS_UpdateHint(mRebuildAllExtraHint, aExtraHint);
-
-  // Get a restyle event posted if necessary
-  PostRestyleEventInternal(false);
-}
-
 nsresult
 nsCSSFrameConstructor::GenerateChildFrames(nsIFrame* aFrame)
 {
   {
     nsAutoScriptBlocker scriptBlocker;
     BeginUpdate();
 
     nsFrameItems childItems;
@@ -12393,158 +11121,8 @@ Iterator::DeleteItemsTo(const Iterator& 
     NS_ASSERTION(!IsDone(), "Ran off end of list?");
     FrameConstructionItem* item = ToItem(mCurrent);
     Next();
     PR_REMOVE_LINK(item);
     mList.AdjustCountsForItem(item, -1);
     delete item;
   } while (*this != aEnd);
 }
-
-bool
-nsCSSFrameConstructor::RecomputePosition(nsIFrame* aFrame)
-{
-  // Don't process position changes on table frames, since we already handle
-  // the dynamic position change on the outer table frame, and the reflow-based
-  // fallback code path also ignores positions on inner table frames.
-  if (aFrame->GetType() == nsGkAtoms::tableFrame) {
-    return true;
-  }
-
-  // Don't process position changes on frames which have views or the ones which
-  // have a view somewhere in their descendants, because the corresponding view
-  // needs to be repositioned properly as well.
-  if (aFrame->HasView() ||
-      (aFrame->GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW)) {
-    StyleChangeReflow(aFrame, nsChangeHint_NeedReflow);
-    return false;
-  }
-
-  const nsStyleDisplay* display = aFrame->StyleDisplay();
-  // Changes to the offsets of a non-positioned element can safely be ignored.
-  if (display->mPosition == NS_STYLE_POSITION_STATIC) {
-    return true;
-  }
-
-  aFrame->SchedulePaint();
-
-  // For relative positioning, we can simply update the frame rect
-  if (display->mPosition == NS_STYLE_POSITION_RELATIVE) {
-    switch (display->mDisplay) {
-      case NS_STYLE_DISPLAY_TABLE_CAPTION:
-      case NS_STYLE_DISPLAY_TABLE_CELL:
-      case NS_STYLE_DISPLAY_TABLE_ROW:
-      case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
-      case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
-      case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
-      case NS_STYLE_DISPLAY_TABLE_COLUMN:
-      case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP:
-        // We don't currently support relative positioning of inner
-        // table elements.  If we apply offsets to things we haven't
-        // previously offset, we'll get confused.  So bail.
-        return true;
-      default:
-        break;
-    }
-
-    nsIFrame* cb = aFrame->GetContainingBlock();
-    const nsSize size = cb->GetSize();
-    const nsPoint oldOffsets = aFrame->GetRelativeOffset();
-    nsMargin newOffsets;
-
-    // Move the frame
-    nsHTMLReflowState::ComputeRelativeOffsets(
-        cb->StyleVisibility()->mDirection,
-        aFrame, size.width, size.height, newOffsets);
-    NS_ASSERTION(newOffsets.left == -newOffsets.right &&
-                 newOffsets.top == -newOffsets.bottom,
-                 "ComputeRelativeOffsets should return valid results");
-    aFrame->SetPosition(aFrame->GetPosition() - oldOffsets +
-                        nsPoint(newOffsets.left, newOffsets.top));
-
-    return true;
-  }
-
-  // For absolute positioning, the width can potentially change if width is
-  // auto and either of left or right are not.  The height can also potentially
-  // change if height is auto and either of top or bottom are not.  In these
-  // cases we fall back to a reflow, and in all other cases, we attempt to
-  // move the frame here.
-  // Note that it is possible for the dimensions to not change in the above
-  // cases, so we should be a little smarter here and only fall back to reflow
-  // when the dimensions will really change (bug 745485).
-  const nsStylePosition* position = aFrame->StylePosition();
-  if (position->mWidth.GetUnit() != eStyleUnit_Auto &&
-      position->mHeight.GetUnit() != eStyleUnit_Auto) {
-    // For the absolute positioning case, set up a fake HTML reflow state for
-    // the frame, and then get the offsets from it.
-    nsRefPtr<nsRenderingContext> rc = aFrame->PresContext()->GetPresShell()->
-      GetReferenceRenderingContext();
-
-    // Construct a bogus parent reflow state so that there's a usable
-    // containing block reflow state.
-    nsIFrame* parentFrame = aFrame->GetParent();
-    nsSize parentSize = parentFrame->GetSize();
-
-    nsFrameState savedState = parentFrame->GetStateBits();
-    nsHTMLReflowState parentReflowState(aFrame->PresContext(), parentFrame,
-                                        rc, parentSize);
-    parentFrame->RemoveStateBits(~nsFrameState(0));
-    parentFrame->AddStateBits(savedState);
-
-    NS_WARN_IF_FALSE(parentSize.width != NS_INTRINSICSIZE &&
-                     parentSize.height != NS_INTRINSICSIZE,
-                     "parentSize should be valid");
-    parentReflowState.SetComputedWidth(std::max(parentSize.width, 0));
-    parentReflowState.SetComputedHeight(std::max(parentSize.height, 0));
-    parentReflowState.mComputedMargin.SizeTo(0, 0, 0, 0);
-    parentSize.height = NS_AUTOHEIGHT;
-
-    parentReflowState.mComputedPadding = parentFrame->GetUsedPadding();
-    parentReflowState.mComputedBorderPadding =
-      parentFrame->GetUsedBorderAndPadding();
-
-    nsSize availSize(parentSize.width, NS_INTRINSICSIZE);
-
-    nsSize size = aFrame->GetSize();
-    ViewportFrame* viewport = do_QueryFrame(parentFrame);
-    nsSize cbSize = viewport ?
-      viewport->AdjustReflowStateAsContainingBlock(&parentReflowState).Size()
-      : aFrame->GetContainingBlock()->GetSize();
-    const nsMargin& parentBorder =
-      parentReflowState.mStyleBorder->GetComputedBorder();
-    cbSize -= nsSize(parentBorder.LeftRight(), parentBorder.TopBottom());
-    nsHTMLReflowState reflowState(aFrame->PresContext(), parentReflowState,
-                                  aFrame, availSize, cbSize.width,
-                                  cbSize.height);
-
-    // If we're solving for 'left' or 'top', then compute it here, in order to
-    // match the reflow code path.
-    if (NS_AUTOOFFSET == reflowState.mComputedOffsets.left) {
-      reflowState.mComputedOffsets.left = cbSize.width -
-                                          reflowState.mComputedOffsets.right -
-                                          reflowState.mComputedMargin.right -
-                                          size.width -
-                                          reflowState.mComputedMargin.left;
-    }
-
-    if (NS_AUTOOFFSET == reflowState.mComputedOffsets.top) {
-      reflowState.mComputedOffsets.top = cbSize.height -
-                                         reflowState.mComputedOffsets.bottom -
-                                         reflowState.mComputedMargin.bottom -
-                                         size.height -
-                                         reflowState.mComputedMargin.top;
-    }
-    
-    // Move the frame
-    nsPoint pos(parentBorder.left + reflowState.mComputedOffsets.left +
-                reflowState.mComputedMargin.left,
-                parentBorder.top + reflowState.mComputedOffsets.top +
-                reflowState.mComputedMargin.top);
-    aFrame->SetPosition(pos);
-
-    return true;
-  }
-
-  // Fall back to a reflow
-  StyleChangeReflow(aFrame, nsChangeHint_NeedReflow);
-  return false;
-}
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -15,19 +15,19 @@
 
 #include "nsCOMPtr.h"
 #include "nsILayoutHistoryState.h"
 #include "nsQuoteList.h"
 #include "nsCounterManager.h"
 #include "nsHashKeys.h"
 #include "nsThreadUtils.h"
 #include "nsCSSPseudoElements.h"
-#include "RestyleTracker.h"
 #include "nsIAnonymousContentCreator.h"
 #include "nsFrameManager.h"
+#include "RestyleManager.h"
 
 class nsIDocument;
 struct nsFrameItems;
 struct nsAbsoluteItems;
 class nsStyleContext;
 struct nsStyleContent;
 struct nsStyleDisplay;
 class nsIPresShell;
@@ -35,37 +35,37 @@ class nsIDOMHTMLSelectElement;
 class nsPresContext;
 class nsStyleChangeList;
 class nsIFrame;
 struct nsGenConInitializer;
 
 class nsICSSAnonBoxPseudo;
 class nsPageContentFrame;
 struct PendingBinding;
-class nsRefreshDriver;
 
 class nsFrameConstructorState;
 class nsFrameConstructorSaveState;
 
 namespace mozilla {
+
+class RestyleManager;
+
 namespace dom {
 
 class FlattenedChildIterator;
 
 }
 }
 
 class nsCSSFrameConstructor : public nsFrameManager
 {
-  friend class nsRefreshDriver;
-
 public:
   typedef mozilla::dom::Element Element;
-  typedef mozilla::RestyleTracker RestyleTracker;
-  typedef mozilla::OverflowChangedTracker OverflowChangedTracker;
+
+  friend class mozilla::RestyleManager;
 
   nsCSSFrameConstructor(nsIDocument *aDocument, nsIPresShell* aPresShell,
                         nsStyleSet* aStyleSet);
   ~nsCSSFrameConstructor(void) {
     NS_ASSERTION(mUpdateCount == 0, "Dying in the middle of our own update?");
   }
 
   // get the alternate text for a content node
@@ -73,16 +73,19 @@ public:
                                   nsIAtom*       aTag,  // content object's tag
                                   nsXPIDLString& aAltText);
 
 private:
   nsCSSFrameConstructor(const nsCSSFrameConstructor& aCopy) MOZ_DELETE;
   nsCSSFrameConstructor& operator=(const nsCSSFrameConstructor& aCopy) MOZ_DELETE;
 
 public:
+  mozilla::RestyleManager* RestyleManager() const
+    { return mPresShell->GetPresContext()->RestyleManager(); }
+
   nsIFrame* ConstructRootFrame();
 
   nsresult ReconstructDocElementHierarchy();
 
   // Create frames for content nodes that are marked as needing frames. This
   // should be called before ProcessPendingRestyles.
   // Note: It's the caller's responsibility to make sure to wrap a
   // CreateNeededFrames call in a view update batch and a script blocker.
@@ -199,161 +202,31 @@ public:
                           nsIContent* aChild,
                           nsIContent* aOldNextSibling,
                           RemoveFlags aFlags,
                           bool*     aDidReconstruct);
 
   nsresult CharacterDataChanged(nsIContent* aContent,
                                 CharacterDataChangeInfo* aInfo);
 
-  nsresult ContentStateChanged(nsIContent*   aContent,
-                               nsEventStates aStateMask);
-
   // generate the child frames and process bindings
   nsresult GenerateChildFrames(nsIFrame* aFrame);
 
   // Should be called when a frame is going to be destroyed and
   // WillDestroyFrameTree hasn't been called yet.
   void NotifyDestroyingFrame(nsIFrame* aFrame);
 
-  void AttributeWillChange(Element* aElement,
-                           int32_t  aNameSpaceID,
-                           nsIAtom* aAttribute,
-                           int32_t  aModType);
-  void AttributeChanged(Element* aElement,
-                        int32_t  aNameSpaceID,
-                        nsIAtom* aAttribute,
-                        int32_t  aModType);
-
   void BeginUpdate();
   void EndUpdate();
   void RecalcQuotesAndCounters();
 
   // Gets called when the presshell is destroying itself and also
   // when we tear down our frame tree to reconstruct it
   void WillDestroyFrameTree();
 
-  // Get an integer that increments every time there is a style change
-  // as a result of a change to the :hover content state.
-  uint32_t GetHoverGeneration() const { return mHoverGeneration; }
-
-  // Get a counter that increments on every style change, that we use to
-  // track whether off-main-thread animations are up-to-date.
-  uint64_t GetAnimationGeneration() const { return mAnimationGeneration; }
-
-  // Note: It's the caller's responsibility to make sure to wrap a
-  // ProcessRestyledFrames call in a view update batch and a script blocker.
-  // This function does not call ProcessAttachedQueue() on the binding manager.
-  // If the caller wants that to happen synchronously, it needs to handle that
-  // itself.
-  nsresult ProcessRestyledFrames(nsStyleChangeList& aRestyleArray);
-
-private:
-
-  friend class mozilla::RestyleTracker;
-
-  void RestyleForEmptyChange(Element* aContainer);
-
-public:
-  // Restyling for a ContentInserted (notification after insertion) or
-  // for a CharacterDataChanged.  |aContainer| must be non-null; when
-  // the container is null, no work is needed.
-  void RestyleForInsertOrChange(Element* aContainer, nsIContent* aChild);
-
-  // This would be the same as RestyleForInsertOrChange if we got the
-  // notification before the removal.  However, we get it after, so we need the
-  // following sibling in addition to the old child.  |aContainer| must be
-  // non-null; when the container is null, no work is needed.  aFollowingSibling
-  // is the sibling that used to come after aOldChild before the removal.
-  void RestyleForRemove(Element* aContainer,
-                        nsIContent* aOldChild,
-                        nsIContent* aFollowingSibling);
-  // Same for a ContentAppended.  |aContainer| must be non-null; when
-  // the container is null, no work is needed.
-  void RestyleForAppend(Element* aContainer, nsIContent* aFirstNewContent);
-
-  // Process any pending restyles. This should be called after
-  // CreateNeededFrames.
-  // Note: It's the caller's responsibility to make sure to wrap a
-  // ProcessPendingRestyles call in a view update batch and a script blocker.
-  // This function does not call ProcessAttachedQueue() on the binding manager.
-  // If the caller wants that to happen synchronously, it needs to handle that
-  // itself.
-  void ProcessPendingRestyles();
-  
-  // Rebuilds all style data by throwing out the old rule tree and
-  // building a new one, and additionally applying aExtraHint (which
-  // must not contain nsChangeHint_ReconstructFrame) to the root frame.
-  void RebuildAllStyleData(nsChangeHint aExtraHint);
-
-  // Helper that does part of the work of RebuildAllStyleData, shared by
-  // RestyleElement for 'rem' handling.
-  void DoRebuildAllStyleData(RestyleTracker& aRestyleTracker,
-                             nsChangeHint aExtraHint);
-
-  // See PostRestyleEventCommon below.
-  void PostRestyleEvent(Element* aElement,
-                        nsRestyleHint aRestyleHint,
-                        nsChangeHint aMinChangeHint)
-  {
-    nsPresContext *presContext = mPresShell->GetPresContext();
-    if (presContext) {
-      PostRestyleEventCommon(aElement, aRestyleHint, aMinChangeHint,
-                             presContext->IsProcessingAnimationStyleChange());
-    }
-  }
-
-  // See PostRestyleEventCommon below.
-  void PostAnimationRestyleEvent(Element* aElement,
-                                 nsRestyleHint aRestyleHint,
-                                 nsChangeHint aMinChangeHint)
-  {
-    PostRestyleEventCommon(aElement, aRestyleHint, aMinChangeHint, true);
-  }
-
-  void FlushOverflowChangedTracker() 
-  {
-    mOverflowChangedTracker.Flush();
-  }
-
-private:
-  /**
-   * Notify the frame constructor that an element needs to have its
-   * style recomputed.
-   * @param aElement: The element to be restyled.
-   * @param aRestyleHint: Which nodes need to have selector matching run
-   *                      on them.
-   * @param aMinChangeHint: A minimum change hint for aContent and its
-   *                        descendants.
-   * @param aForAnimation: Whether the style should be computed with or
-   *                       without animation data.  Animation code
-   *                       sometimes needs to pass true; other code
-   *                       should generally pass the the pres context's
-   *                       IsProcessingAnimationStyleChange() value
-   *                       (which is the default value).
-   */
-  void PostRestyleEventCommon(Element* aElement,
-                              nsRestyleHint aRestyleHint,
-                              nsChangeHint aMinChangeHint,
-                              bool aForAnimation);
-  void PostRestyleEventInternal(bool aForLazyConstruction);
-public:
-
-  /**
-   * Asynchronously clear style data from the root frame downwards and ensure
-   * it will all be rebuilt. This is safe to call anytime; it will schedule
-   * a restyle and take effect next time style changes are flushed.
-   * This method is used to recompute the style data when some change happens
-   * outside of any style rules, like a color preference change or a change
-   * in a system font size, or to fix things up when an optimization in the
-   * style data has become invalid. We assume that the root frame will not
-   * need to be reframed.
-   */
-  void PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint);
-
   // Request to create a continuing frame.  This method never returns null.
   nsIFrame* CreateContinuingFrame(nsPresContext* aPresContext,
                                   nsIFrame*       aFrame,
                                   nsIFrame*       aParentFrame,
                                   bool            aIsFluid = true);
 
   // Copy over fixed frames from aParentFrame's prev-in-flow
   nsresult ReplicateFixedFrames(nsPageContentFrame* aParentFrame);
@@ -380,36 +253,26 @@ public:
   // have a psuedo-element style
   nsIFrame* GetRootElementStyleFrame() { return mRootElementStyleFrame; }
   nsIFrame* GetPageSequenceFrame() { return mPageSequenceFrame; }
 
   // Get the frame that is the parent of the root element.
   nsIFrame* GetDocElementContainingBlock()
     { return mDocElementContainingBlock; }
 
-  void SetPromoteReflowsToReframeRoot(bool aPromote) { mPromoteReflowsToReframeRoot = aPromote; }
-
 private:
   struct FrameConstructionItem;
   class FrameConstructionItemList;
 
   nsIFrame* ConstructPageFrame(nsIPresShell*  aPresShell, 
                                nsPresContext* aPresContext,
                                nsIFrame*      aParentFrame,
                                nsIFrame*      aPrevPageFrame,
                                nsIFrame*&     aCanvasFrame);
 
-  /* aMinHint is the minimal change that should be made to the element */
-  // XXXbz do we really need the aPrimaryFrame argument here?
-  void RestyleElement(Element* aElement,
-                      nsIFrame*       aPrimaryFrame,
-                      nsChangeHint    aMinHint,
-                      RestyleTracker& aRestyleTracker,
-                      bool            aRestyleDescendants);
-
   void InitAndRestoreFrame (const nsFrameConstructorState& aState,
                             nsIContent*                    aContent,
                             nsIFrame*                      aParentFrame,
                             nsIFrame*                      aNewFrame,
                             bool                           aAllowCounters = true);
 
   // aState can be null if not available; it's used as an optimization.
   // XXXbz IsValidSibling is the only caller that doesn't pass a state here!
@@ -1649,23 +1512,16 @@ private:
                              nsIFrame*                aContainingBlock,
                              nsIFrame*                aFrame,
                              FrameConstructionItemList& aItems,
                              bool                     aIsAppend,
                              nsIFrame*                aPrevSibling);
 
   nsresult ReframeContainingBlock(nsIFrame* aFrame);
 
-  nsresult StyleChangeReflow(nsIFrame* aFrame, nsChangeHint aHint);
-
-  // Returns true if this function managed to successfully move a frame, and
-  // false if it could not process the position change, and a reflow should
-  // be performed instead.
-  bool RecomputePosition(nsIFrame* aFrame);
-
   //----------------------------------------
 
   // Methods support :first-letter style
 
   void CreateFloatingLetterFrame(nsFrameConstructorState& aState,
                                  nsIFrame*                aBlockFrame,
                                  nsIContent*              aTextContent,
                                  nsIFrame*                aTextFrame,
@@ -1875,33 +1731,15 @@ private:
   nsQuoteList         mQuoteList;
   nsCounterManager    mCounterManager;
   // Current ProcessChildren depth.
   uint16_t            mCurrentDepth;
   uint16_t            mUpdateCount;
   bool                mQuotesDirty : 1;
   bool                mCountersDirty : 1;
   bool                mIsDestroyingFrameTree : 1;
-  bool                mRebuildAllStyleData : 1;
   // This is true if mDocElementContainingBlock supports absolute positioning
   bool                mHasRootAbsPosContainingBlock : 1;
-  // True if we're already waiting for a refresh notification
-  bool                mObservingRefreshDriver : 1;
-  // True if we're in the middle of a nsRefreshDriver refresh
-  bool                mInStyleRefresh : 1;
-  // True if reflows/frame reconstruction should be promoted to reframe the root element
-  bool                mPromoteReflowsToReframeRoot : 1;
-  uint32_t            mHoverGeneration;
-  nsChangeHint        mRebuildAllExtraHint;
 
   nsCOMPtr<nsILayoutHistoryState> mTempFrameTreeState;
-
-  OverflowChangedTracker mOverflowChangedTracker;
-
-  // The total number of animation flushes by this frame constructor.
-  // Used to keep the layer and animation manager in sync.
-  uint64_t mAnimationGeneration;
-
-  RestyleTracker mPendingRestyles;
-  RestyleTracker mPendingAnimationRestyles;
 };
 
 #endif /* nsCSSFrameConstructor_h___ */
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -5071,17 +5071,17 @@ void
 nsLayoutUtils::PostRestyleEvent(Element* aElement,
                                 nsRestyleHint aRestyleHint,
                                 nsChangeHint aMinChangeHint)
 {
   nsIDocument* doc = aElement->GetCurrentDoc();
   if (doc) {
     nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
     if (presShell) {
-      presShell->FrameConstructor()->PostRestyleEvent(
+      presShell->GetPresContext()->RestyleManager()->PostRestyleEvent(
         aElement, aRestyleHint, aMinChangeHint);
     }
   }
 }
 
 nsSetAttrRunnable::nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName,
                                      const nsAString& aValue)
   : mContent(aContent),
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -38,17 +38,17 @@
 #include "nsCSSRendering.h"
 #include "prprf.h"
 #include "nsAutoPtr.h"
 #include "nsEventStateManager.h"
 #include "nsThreadUtils.h"
 #include "nsFrameManager.h"
 #include "nsLayoutUtils.h"
 #include "nsViewManager.h"
-#include "nsCSSFrameConstructor.h"
+#include "RestyleManager.h"
 #include "nsCSSRuleProcessor.h"
 #include "nsStyleChangeList.h"
 #include "nsRuleNode.h"
 #include "nsEventDispatcher.h"
 #include "gfxUserFontSet.h"
 #include "gfxPlatform.h"
 #include "nsCSSRules.h"
 #include "nsFontFaceLoader.h"
@@ -1732,27 +1732,27 @@ nsPresContext::RebuildAllStyleData(nsCha
     return;
   }
 
   mUsesRootEMUnits = false;
   mUsesViewportUnits = false;
   RebuildUserFontSet();
   AnimationManager()->KeyframesListIsDirty();
 
-  mShell->FrameConstructor()->RebuildAllStyleData(aExtraHint);
+  RestyleManager()->RebuildAllStyleData(aExtraHint);
 }
 
 void
 nsPresContext::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint)
 {
   if (!mShell) {
     // We must have been torn down. Nothing to do here.
     return;
   }
-  mShell->FrameConstructor()->PostRebuildAllStyleDataEvent(aExtraHint);
+  RestyleManager()->PostRebuildAllStyleDataEvent(aExtraHint);
 }
 
 void
 nsPresContext::MediaFeatureValuesChanged(StyleRebuildType aShouldRebuild,
                                          nsChangeHint aChangeHint)
 {
   NS_ASSERTION(aShouldRebuild == eAlwaysRebuildStyle || aChangeHint == 0,
                "If you don't know if we need a rebuild, how can you provide a hint?");
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -237,20 +237,23 @@ public:
   {
       NS_ASSERTION(!mShell || !mShell->GetDocument() ||
                    mShell->GetDocument() == mDocument,
                    "nsPresContext doesn't have the same document as nsPresShell!");
       return mDocument;
   }
 
 #ifdef _IMPL_NS_LAYOUT
-  nsStyleSet* StyleSet() { return GetPresShell()->StyleSet(); }
+  nsStyleSet* StyleSet() { return PresShell()->StyleSet(); }
 
   nsFrameManager* FrameManager()
-    { return GetPresShell()->FrameManager(); }
+    { return PresShell()->FrameManager(); }
+
+  nsCSSFrameConstructor* FrameConstructor()
+    { return PresShell()->FrameConstructor(); }
 
   nsTransitionManager* TransitionManager() { return mTransitionManager; }
   nsAnimationManager* AnimationManager() { return mAnimationManager; }
 
   nsRefreshDriver* RefreshDriver() { return mRefreshDriver; }
 
   mozilla::RestyleManager* RestyleManager() { return mRestyleManager; }
 #endif
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -1715,17 +1715,17 @@ PresShell::Initialize(nscoord aWidth, ns
     // Constructors may have killed us too
     NS_ENSURE_STATE(!mHaveShutDown);
 
     // Now flush out pending restyles before we actually reflow, in
     // case XBL constructors changed styles somewhere.
     {
       nsAutoScriptBlocker scriptBlocker;
       mFrameConstructor->CreateNeededFrames();
-      mFrameConstructor->ProcessPendingRestyles();
+      mPresContext->RestyleManager()->ProcessPendingRestyles();
     }
 
     // And that might have run _more_ XBL constructors
     NS_ENSURE_STATE(!mHaveShutDown);
   }
 
   NS_ASSERTION(rootFrame, "How did that happen?");
 
@@ -1857,17 +1857,17 @@ PresShell::ResizeReflowIgnoreOverride(ns
     // Have to make sure that the content notifications are flushed before we
     // start messing with the frame model; otherwise we can get content doubling.
     mDocument->FlushPendingNotifications(Flush_ContentAndNotify);
 
     // Make sure style is up to date
     {
       nsAutoScriptBlocker scriptBlocker;
       mFrameConstructor->CreateNeededFrames();
-      mFrameConstructor->ProcessPendingRestyles();
+      mPresContext->RestyleManager()->ProcessPendingRestyles();
     }
 
     rootFrame = mFrameConstructor->GetRootFrame();
     if (!mIsDestroying && rootFrame) {
       // XXX Do a full invalidate at the beginning so that invalidates along
       // the way don't have region accumulation issues?
 
       {
@@ -2687,35 +2687,36 @@ PresShell::RecreateFramesFor(nsIContent*
 
   nsAutoScriptBlocker scriptBlocker;
 
   nsStyleChangeList changeList;
   changeList.AppendChange(nullptr, aContent, nsChangeHint_ReconstructFrame);
 
   // Mark ourselves as not safe to flush while we're doing frame construction.
   ++mChangeNestCount;
-  nsresult rv = mFrameConstructor->ProcessRestyledFrames(changeList);
-  mFrameConstructor->FlushOverflowChangedTracker();
+  RestyleManager* restyleManager = mPresContext->RestyleManager();
+  nsresult rv = restyleManager->ProcessRestyledFrames(changeList);
+  restyleManager->FlushOverflowChangedTracker();
   --mChangeNestCount;
-  
+
   return rv;
 }
 
 void
 nsIPresShell::PostRecreateFramesFor(Element* aElement)
 {
-  FrameConstructor()->PostRestyleEvent(aElement, nsRestyleHint(0),
-                                       nsChangeHint_ReconstructFrame);
+  mPresContext->RestyleManager()->PostRestyleEvent(aElement, nsRestyleHint(0),
+                                                   nsChangeHint_ReconstructFrame);
 }
 
 void
 nsIPresShell::RestyleForAnimation(Element* aElement, nsRestyleHint aHint)
 {
-  FrameConstructor()->PostAnimationRestyleEvent(aElement, aHint,
-                                                NS_STYLE_HINT_NONE);
+  mPresContext->RestyleManager()->PostAnimationRestyleEvent(aElement, aHint,
+                                                            NS_STYLE_HINT_NONE);
 }
 
 void
 PresShell::ClearFrameRefs(nsIFrame* aFrame)
 {
   mPresContext->EventStateManager()->ClearFrameRefs(aFrame);
 
   nsWeakFrame* weakFrame = mWeakFrames;
@@ -3421,24 +3422,25 @@ PresShell::ScheduleViewManagerFlush()
     mDocument->SetNeedLayoutFlush();
   }
 }
 
 void
 PresShell::DispatchSynthMouseMove(nsGUIEvent *aEvent,
                                   bool aFlushOnHoverChange)
 {
-  uint32_t hoverGenerationBefore = mFrameConstructor->GetHoverGeneration();
+  RestyleManager* restyleManager = mPresContext->RestyleManager();
+  uint32_t hoverGenerationBefore = restyleManager->GetHoverGeneration();
   nsEventStatus status;
   nsView* targetView = nsView::GetViewFor(aEvent->widget);
   if (!targetView)
     return;
   targetView->GetViewManager()->DispatchEvent(aEvent, targetView, &status);
   if (aFlushOnHoverChange &&
-      hoverGenerationBefore != mFrameConstructor->GetHoverGeneration()) {
+      hoverGenerationBefore != restyleManager->GetHoverGeneration()) {
     // Flush so that the resulting reflow happens now so that our caller
     // can suppress any synthesized mouse moves caused by that reflow.
     FlushPendingNotifications(Flush_Layout);
   }
 }
 
 void
 PresShell::ClearMouseCaptureOnView(nsView* aView)
@@ -3849,17 +3851,17 @@ PresShell::FlushPendingNotifications(moz
           FlushTransitions(CommonAnimationManager::Cannot_Throttle);
         mPresContext->TickLastStyleUpdateForAllAnimations();
       }
 
       // The FlushResampleRequests() above flushed style changes.
       if (!mIsDestroying) {
         nsAutoScriptBlocker scriptBlocker;
         mFrameConstructor->CreateNeededFrames();
-        mFrameConstructor->ProcessPendingRestyles();
+        mPresContext->RestyleManager()->ProcessPendingRestyles();
       }
     }
 
     // Dispatch any 'animationstart' events those (or earlier) restyles
     // queued up.
     if (!mIsDestroying) {
       mPresContext->AnimationManager()->DispatchEvents();
     }
@@ -3876,17 +3878,17 @@ PresShell::FlushPendingNotifications(moz
     // In particular, reflow depends on style being completely up to
     // date.  If it's not, then style context reparenting, which can
     // happen during reflow, might suddenly pick up the new rules and
     // we'll end up with frames whose style doesn't match the frame
     // type.
     if (!mIsDestroying) {
       nsAutoScriptBlocker scriptBlocker;
       mFrameConstructor->CreateNeededFrames();
-      mFrameConstructor->ProcessPendingRestyles();
+      mPresContext->RestyleManager()->ProcessPendingRestyles();
     }
 
 
     // There might be more pending constructors now, but we're not going to
     // worry about them.  They can't be triggered during reflow, so we should
     // be good.
 
     if (flushType >= (mSuppressInterruptibleReflows ? Flush_Layout : Flush_InterruptibleLayout) &&
@@ -3953,53 +3955,54 @@ PresShell::CharacterDataChanged(nsIDocum
   // not cases when the frame constructor calls its own methods to force
   // frame reconstruction.
   nsIContent *container = aContent->GetParent();
   uint32_t selectorFlags =
     container ? (container->GetFlags() & NODE_ALL_SELECTOR_FLAGS) : 0;
   if (selectorFlags != 0 && !aContent->IsRootOfAnonymousSubtree()) {
     Element* element = container->AsElement();
     if (aInfo->mAppend && !aContent->GetNextSibling())
-      mFrameConstructor->RestyleForAppend(element, aContent);
+      mPresContext->RestyleManager()->RestyleForAppend(element, aContent);
     else
-      mFrameConstructor->RestyleForInsertOrChange(element, aContent);
+      mPresContext->RestyleManager()->RestyleForInsertOrChange(element, aContent);
   }
 
   mFrameConstructor->CharacterDataChanged(aContent, aInfo);
   VERIFY_STYLE_TREE;
 }
 
 void
 PresShell::ContentStateChanged(nsIDocument* aDocument,
                                nsIContent* aContent,
                                nsEventStates aStateMask)
 {
   NS_PRECONDITION(!mIsDocumentGone, "Unexpected ContentStateChanged");
   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
 
   if (mDidInitialize) {
     nsAutoCauseReflowNotifier crNotifier(this);
-    mFrameConstructor->ContentStateChanged(aContent, aStateMask);
+    mPresContext->RestyleManager()->ContentStateChanged(aContent, aStateMask);
     VERIFY_STYLE_TREE;
   }
 }
 
 void
 PresShell::DocumentStatesChanged(nsIDocument* aDocument,
                                  nsEventStates aStateMask)
 {
   NS_PRECONDITION(!mIsDocumentGone, "Unexpected DocumentStatesChanged");
   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
 
   if (mDidInitialize &&
       mStyleSet->HasDocumentStateDependentStyle(mPresContext,
                                                 mDocument->GetRootElement(),
                                                 aStateMask)) {
-    mFrameConstructor->PostRestyleEvent(mDocument->GetRootElement(),
-                                        eRestyle_Subtree, NS_STYLE_HINT_NONE);
+    mPresContext->RestyleManager()->PostRestyleEvent(mDocument->GetRootElement(),
+                                                     eRestyle_Subtree,
+                                                     NS_STYLE_HINT_NONE);
     VERIFY_STYLE_TREE;
   }
 
   if (aStateMask.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) {
     nsIFrame* root = mFrameConstructor->GetRootFrame();
     if (root) {
       FrameLayerBuilder::InvalidateAllLayersForFrame(root);
       if (root->HasView()) {
@@ -4020,18 +4023,18 @@ PresShell::AttributeWillChange(nsIDocume
   NS_PRECONDITION(!mIsDocumentGone, "Unexpected AttributeWillChange");
   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
 
   // XXXwaterson it might be more elegant to wait until after the
   // initial reflow to begin observing the document. That would
   // squelch any other inappropriate notifications as well.
   if (mDidInitialize) {
     nsAutoCauseReflowNotifier crNotifier(this);
-    mFrameConstructor->AttributeWillChange(aElement, aNameSpaceID,
-                                           aAttribute, aModType);
+    mPresContext->RestyleManager()->AttributeWillChange(aElement, aNameSpaceID,
+                                                        aAttribute, aModType);
     VERIFY_STYLE_TREE;
   }
 }
 
 void
 PresShell::AttributeChanged(nsIDocument* aDocument,
                             Element*     aElement,
                             int32_t      aNameSpaceID,
@@ -4041,18 +4044,18 @@ PresShell::AttributeChanged(nsIDocument*
   NS_PRECONDITION(!mIsDocumentGone, "Unexpected AttributeChanged");
   NS_PRECONDITION(aDocument == mDocument, "Unexpected aDocument");
 
   // XXXwaterson it might be more elegant to wait until after the
   // initial reflow to begin observing the document. That would
   // squelch any other inappropriate notifications as well.
   if (mDidInitialize) {
     nsAutoCauseReflowNotifier crNotifier(this);
-    mFrameConstructor->AttributeChanged(aElement, aNameSpaceID,
-                                        aAttribute, aModType);
+    mPresContext->RestyleManager()->AttributeChanged(aElement, aNameSpaceID,
+                                                     aAttribute, aModType);
     VERIFY_STYLE_TREE;
   }
 }
 
 void
 PresShell::ContentAppended(nsIDocument *aDocument,
                            nsIContent* aContainer,
                            nsIContent* aFirstNewContent,
@@ -4066,17 +4069,18 @@ PresShell::ContentAppended(nsIDocument *
     return;
   }
   
   nsAutoCauseReflowNotifier crNotifier(this);
 
   // Call this here so it only happens for real content mutations and
   // not cases when the frame constructor calls its own methods to force
   // frame reconstruction.
-  mFrameConstructor->RestyleForAppend(aContainer->AsElement(), aFirstNewContent);
+  mPresContext->RestyleManager()->
+    RestyleForAppend(aContainer->AsElement(), aFirstNewContent);
 
   mFrameConstructor->ContentAppended(aContainer, aFirstNewContent, true);
 
   if (static_cast<nsINode*>(aContainer) == static_cast<nsINode*>(aDocument) &&
       aFirstNewContent->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE) {
     NotifyFontSizeInflationEnabledIsDirty();
   }
 
@@ -4096,18 +4100,20 @@ PresShell::ContentInserted(nsIDocument* 
     return;
   }
   
   nsAutoCauseReflowNotifier crNotifier(this);
 
   // Call this here so it only happens for real content mutations and
   // not cases when the frame constructor calls its own methods to force
   // frame reconstruction.
-  if (aContainer)
-    mFrameConstructor->RestyleForInsertOrChange(aContainer->AsElement(), aChild);
+  if (aContainer) {
+    mPresContext->RestyleManager()->
+      RestyleForInsertOrChange(aContainer->AsElement(), aChild);
+  }
 
   mFrameConstructor->ContentInserted(aContainer, aChild, nullptr, true);
 
   if (((!aContainer && aDocument) ||
       (static_cast<nsINode*>(aContainer) == static_cast<nsINode*>(aDocument))) &&
       aChild->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE) {
     NotifyFontSizeInflationEnabledIsDirty();
   }
@@ -4148,18 +4154,18 @@ PresShell::ContentRemoved(nsIDocument *a
   nsIContent* oldNextSibling;
   if (aContainer) {
     oldNextSibling = aContainer->GetChildAt(aIndexInContainer);
   } else {
     oldNextSibling = nullptr;
   }
   
   if (aContainer && aContainer->IsElement()) {
-    mFrameConstructor->RestyleForRemove(aContainer->AsElement(), aChild,
-                                        oldNextSibling);
+    mPresContext->RestyleManager()->
+      RestyleForRemove(aContainer->AsElement(), aChild, oldNextSibling);
   }
 
   bool didReconstruct;
   mFrameConstructor->ContentRemoved(aContainer, aChild, oldNextSibling,
                                     nsCSSFrameConstructor::REMOVE_CONTENT,
                                     &didReconstruct);
 
 
@@ -4226,28 +4232,29 @@ nsIPresShell::ReconstructStyleDataIntern
     // Nothing to do here, since we have no frames yet
     return;
   }
 
   if (!root) {
     // No content to restyle
     return;
   }
-  
+
+  RestyleManager* restyleManager = mPresContext->RestyleManager();
   if (scopeRoots.IsEmpty()) {
     // If scopeRoots is empty, we know that mStylesHaveChanged was true at
     // the beginning of this function, and that we need to restyle the whole
     // document.
-    mFrameConstructor->PostRestyleEvent(root, eRestyle_Subtree,
-                                        NS_STYLE_HINT_NONE);
+    restyleManager->PostRestyleEvent(root, eRestyle_Subtree,
+                                     NS_STYLE_HINT_NONE);
   } else {
     for (uint32_t i = 0; i < scopeRoots.Length(); i++) {
       Element* scopeRoot = scopeRoots[i];
-      mFrameConstructor->PostRestyleEvent(scopeRoot, eRestyle_Subtree,
-                                          NS_STYLE_HINT_NONE);
+      restyleManager->PostRestyleEvent(scopeRoot, eRestyle_Subtree,
+                                       NS_STYLE_HINT_NONE);
     }
   }
 }
 
 void
 nsIPresShell::ReconstructStyleDataExternal()
 {
   ReconstructStyleDataInternal();
@@ -8148,18 +8155,19 @@ PresShell::Observe(nsISupports* aSubject
         nsStyleChangeList changeList;
         WalkFramesThroughPlaceholders(mPresContext, rootFrame,
                                       ReframeImageBoxes, &changeList);
         // Mark ourselves as not safe to flush while we're doing frame
         // construction.
         {
           nsAutoScriptBlocker scriptBlocker;
           ++mChangeNestCount;
-          mFrameConstructor->ProcessRestyledFrames(changeList);
-          mFrameConstructor->FlushOverflowChangedTracker();
+          RestyleManager* restyleManager = mPresContext->RestyleManager();
+          restyleManager->ProcessRestyledFrames(changeList);
+          restyleManager->FlushOverflowChangedTracker();
           --mChangeNestCount;
         }
       }
     }
     return NS_OK;
   }
 #endif
 
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -31,29 +31,29 @@ typedef HRESULT (WINAPI*DwmGetCompositio
 
 #include "nsRefreshDriver.h"
 #include "nsITimer.h"
 #include "nsLayoutUtils.h"
 #include "nsPresContext.h"
 #include "nsComponentManagerUtils.h"
 #include "prlog.h"
 #include "nsAutoPtr.h"
-#include "nsCSSFrameConstructor.h"
 #include "nsIDocument.h"
 #include "nsGUIEvent.h"
 #include "nsEventDispatcher.h"
 #include "jsapi.h"
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
 #include "mozilla/Preferences.h"
 #include "nsViewManager.h"
 #include "GeckoProfiler.h"
 #include "nsNPAPIPluginInstance.h"
 #include "nsPerformance.h"
 #include "mozilla/dom/WindowBinding.h"
+#include "RestyleManager.h"
 
 using mozilla::TimeStamp;
 using mozilla::TimeDuration;
 
 using namespace mozilla;
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo *gLog = nullptr;
@@ -1154,17 +1154,17 @@ nsRefreshDriver::Tick(int64_t aNowEpoch,
              j && mPresContext && mPresContext->GetPresShell(); --j) {
           // Make sure to not process observers which might have been removed
           // during previous iterations.
           nsIPresShell* shell = observers[j - 1];
           if (!mStyleFlushObservers.Contains(shell))
             continue;
           NS_ADDREF(shell);
           mStyleFlushObservers.RemoveElement(shell);
-          shell->FrameConstructor()->mObservingRefreshDriver = false;
+          shell->GetPresContext()->RestyleManager()->mObservingRefreshDriver = false;
           shell->FlushPendingNotifications(ChangesToFlush(Flush_Style, false));
           NS_RELEASE(shell);
         }
       }
     } else if  (i == 1) {
       // This is the Flush_Layout case.
       if (mPresContext && mPresContext->GetPresShell()) {
         nsAutoTArray<nsIPresShell*, 16> observers;
--- a/layout/generic/nsImageMap.cpp
+++ b/layout/generic/nsImageMap.cpp
@@ -837,19 +837,19 @@ nsImageMap::AddArea(nsIContent* aArea)
 
   //Add focus listener to track area focus changes
   aArea->AddSystemEventListener(NS_LITERAL_STRING("focus"), this, false,
                                 false);
   aArea->AddSystemEventListener(NS_LITERAL_STRING("blur"), this, false,
                                 false);
 
   // This is a nasty hack.  It needs to go away: see bug 135040.  Once this is
-  // removed, the code added to nsCSSFrameConstructor::RestyleElement,
+  // removed, the code added to RestyleManager::RestyleElement,
   // nsCSSFrameConstructor::ContentRemoved (both hacks there), and
-  // nsCSSFrameConstructor::ProcessRestyledFrames to work around this issue can
+  // RestyleManager::ProcessRestyledFrames to work around this issue can
   // be removed.
   aArea->SetPrimaryFrame(mImageFrame);
 
   nsAutoString coords;
   aArea->GetAttr(kNameSpaceID_None, nsGkAtoms::coords, coords);
   area->ParseCoords(coords);
   mAreas.AppendElement(area);
   return NS_OK;
--- a/layout/mathml/nsMathMLTokenFrame.cpp
+++ b/layout/mathml/nsMathMLTokenFrame.cpp
@@ -246,17 +246,17 @@ nsMathMLTokenFrame::MarkIntrinsicWidthsD
 void
 nsMathMLTokenFrame::ProcessTextData()
 {
   // see if the style changes from normal to italic or vice-versa
   if (!SetTextStyle())
     return;
 
   // explicitly request a re-resolve to pick up the change of style
-  PresContext()->PresShell()->FrameConstructor()->
+  PresContext()->RestyleManager()->
     PostRestyleEvent(mContent->AsElement(), eRestyle_Subtree, NS_STYLE_HINT_NONE);
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // For <mi>, if the content is not a single character, turn the font to
 // normal (this function will also query attributes from the mstyle hierarchy)
 // Returns true if there is a style change.
 //
--- a/layout/mathml/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/nsMathMLmtableFrame.cpp
@@ -497,17 +497,17 @@ nsMathMLmtableOuterFrame::AttributeChang
             MapColAttributesIntoCSS(tableFrame, rowFrame, cellFrame);
           }
         }
       }
     }
   }
 
   // Explicitly request a re-resolve and reflow in our subtree to pick up any changes
-  presContext->PresShell()->FrameConstructor()->
+  presContext->RestyleManager()->
     PostRestyleEvent(mContent->AsElement(), eRestyle_Subtree,
                      nsChangeHint_AllReflowHints);
 
   return NS_OK;
 }
 
 nsIFrame*
 nsMathMLmtableOuterFrame::GetRowFrameAt(nsPresContext* aPresContext,
@@ -678,17 +678,17 @@ nsMathMLmtableFrame::SetInitialChildList
 
 void
 nsMathMLmtableFrame::RestyleTable()
 {
   // re-sync MathML specific style data that may have changed
   MapAllAttributesIntoCSS(this);
 
   // Explicitly request a re-resolve and reflow in our subtree to pick up any changes
-  PresContext()->PresShell()->FrameConstructor()->
+  PresContext()->RestyleManager()->
     PostRestyleEvent(mContent->AsElement(), eRestyle_Subtree,
                      nsChangeHint_AllReflowHints);
 }
 
 // --------
 // implementation of nsMathMLmtrFrame
 
 nsIFrame*
@@ -706,17 +706,17 @@ nsMathMLmtrFrame::~nsMathMLmtrFrame()
 NS_IMETHODIMP
 nsMathMLmtrFrame::AttributeChanged(int32_t  aNameSpaceID,
                                    nsIAtom* aAttribute,
                                    int32_t  aModType)
 {
   // Attributes specific to <mtr>:
   // groupalign  : Not yet supported.
   // rowalign    : Fully specified in mathml.css, and so HasAttributeDependentStyle() will
-  //               pick it up and nsCSSFrameConstructor will issue a PostRestyleEvent().
+  //               pick it up and RestyleManager will issue a PostRestyleEvent().
   // columnalign : Need an explicit re-style call.
 
   if (aAttribute == nsGkAtoms::rowalign_) {
     // unset any _moz attribute that we may have set earlier, and re-sync
     mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_math_rowalign_,
                         false);
     MapRowAttributesIntoCSS(nsTableFrame::GetTableFrame(this), this);
     // That's all - see comment above.
@@ -739,17 +739,17 @@ nsMathMLmtrFrame::AttributeChanged(int32
       cellFrame->GetContent()->
         UnsetAttr(kNameSpaceID_None, nsGkAtoms::_moz_math_columnalign_,
                   false);
       MapColAttributesIntoCSS(tableFrame, this, cellFrame);
     }
   }
 
   // Explicitly request a re-resolve and reflow in our subtree to pick up any changes
-  presContext->PresShell()->FrameConstructor()->
+  presContext->RestyleManager()->
     PostRestyleEvent(mContent->AsElement(), eRestyle_Subtree,
                      nsChangeHint_AllReflowHints);
 
   return NS_OK;
 }
 
 // --------
 // implementation of nsMathMLmtdFrame
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -2354,17 +2354,17 @@ nsPrintEngine::CalcNumPrintablePages(int
 
 void
 nsPrintEngine::PromoteReflowsToReframeRoot()
 {
   for (uint32_t i=0; i<mPrt->mPrintDocList.Length(); i++) {
     nsPrintObject* po = mPrt->mPrintDocList.ElementAt(i);
     NS_ASSERTION(po, "nsPrintObject can't be null!");
     if (po->mPresContext) {
-      po->mPresContext->PresShell()->FrameConstructor()->SetPromoteReflowsToReframeRoot(true);
+      po->mPresContext->RestyleManager()->SetPromoteReflowsToReframeRoot(true);
     }
   }
 }
 
 //-----------------------------------------------------------------
 //-- Done: Reflow Methods
 //-----------------------------------------------------------------
 
--- a/layout/style/AnimationCommon.cpp
+++ b/layout/style/AnimationCommon.cpp
@@ -377,13 +377,13 @@ CommonElementAnimationData::CanThrottleA
 
   return CanThrottleTransformChanges(aTime);
 }
 
 void 
 CommonElementAnimationData::UpdateAnimationGeneration(nsPresContext* aPresContext)
 {
   mAnimationGeneration =
-    aPresContext->PresShell()->FrameConstructor()->GetAnimationGeneration();
+    aPresContext->RestyleManager()->GetAnimationGeneration();
 }
 
 }
 }
--- a/layout/style/nsHTMLStyleSheet.cpp
+++ b/layout/style/nsHTMLStyleSheet.cpp
@@ -436,17 +436,17 @@ nsHTMLStyleSheet::ImplLinkColorSetter(ns
     return NS_ERROR_OUT_OF_MEMORY;
 
   aRule->mColor = aColor;
   // Now make sure we restyle any links that might need it.  This
   // shouldn't happen often, so just rebuilding everything is ok.
   if (mDocument && mDocument->GetShell()) {
     Element* root = mDocument->GetRootElement();
     if (root) {
-      mDocument->GetShell()->FrameConstructor()->
+      mDocument->GetShell()->GetPresContext()->RestyleManager()->
         PostRestyleEvent(root, eRestyle_Subtree, NS_STYLE_HINT_NONE);
     }
   }
   return NS_OK;
 }
 
 nsresult
 nsHTMLStyleSheet::SetLinkColor(nscolor aColor)
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -425,20 +425,19 @@ nsTransitionManager::UpdateAllThrottledS
     nsIFrame* primaryFrame;
     if (element &&
         (primaryFrame = nsLayoutUtils::GetStyleFrame(element))) {
       UpdateThrottledStylesForSubtree(element,
         primaryFrame->StyleContext()->GetParent(), changeList);
     }
   }
 
-  mPresContext->PresShell()->FrameConstructor()->
-    ProcessRestyledFrames(changeList);
-  mPresContext->PresShell()->FrameConstructor()->
-    FlushOverflowChangedTracker();
+  RestyleManager* restyleManager = mPresContext->RestyleManager();
+  restyleManager->ProcessRestyledFrames(changeList);
+  restyleManager->FlushOverflowChangedTracker();
 }
 
 void
 nsTransitionManager::ElementDataRemoved()
 {
   // If we have no transitions or animations left, remove ourselves from
   // the refresh driver.
   if (PR_CLIST_IS_EMPTY(&mElementData)) {
--- a/layout/svg/nsSVGContainerFrame.cpp
+++ b/layout/svg/nsSVGContainerFrame.cpp
@@ -154,17 +154,17 @@ nsSVGDisplayContainerFrame::RemoveFrame(
                                         nsIFrame* aOldFrame)
 {
   nsSVGEffects::InvalidateRenderingObservers(aOldFrame);
 
   // nsSVGContainerFrame::RemoveFrame doesn't call down into
   // nsContainerFrame::RemoveFrame, so it doesn't call FrameNeedsReflow. We
   // need to schedule a repaint and schedule an update to our overflow rects.
   SchedulePaint();
-  PresContext()->PresShell()->FrameConstructor()->PostRestyleEvent(
+  PresContext()->RestyleManager()->PostRestyleEvent(
     mContent->AsElement(), nsRestyleHint(0), nsChangeHint_UpdateOverflow);
 
   nsresult rv = nsSVGContainerFrame::RemoveFrame(aListID, aOldFrame);
 
   if (!(GetStateBits() & (NS_FRAME_IS_NONDISPLAY | NS_STATE_IS_OUTER_SVG))) {
     nsSVGUtils::NotifyAncestorsOfFilterRegionChange(this);
   }
 
--- a/layout/svg/nsSVGEffects.cpp
+++ b/layout/svg/nsSVGEffects.cpp
@@ -254,17 +254,17 @@ nsSVGFilterProperty::DoUpdate()
   // Repaint asynchronously in case the filter frame is being torn down
   nsChangeHint changeHint =
     nsChangeHint(nsChangeHint_RepaintFrame);
 
   // Don't need to request UpdateOverflow if we're being reflowed.
   if (!(mFrame->GetStateBits() & NS_FRAME_IN_REFLOW)) {
     NS_UpdateHint(changeHint, nsChangeHint_UpdateOverflow);
   }
-  mFramePresShell->FrameConstructor()->PostRestyleEvent(
+  mFramePresShell->GetPresContext()->RestyleManager()->PostRestyleEvent(
     mFrame->GetContent()->AsElement(), nsRestyleHint(0), changeHint);
 }
 
 void
 nsSVGMarkerProperty::DoUpdate()
 {
   nsSVGIDRenderingObserver::DoUpdate();
   if (!mFrame)
@@ -279,17 +279,17 @@ nsSVGMarkerProperty::DoUpdate()
   // Don't need to request ReflowFrame if we're being reflowed.
   if (!(mFrame->GetStateBits() & NS_FRAME_IN_REFLOW)) {
     // XXXjwatt: We need to unify SVG into standard reflow so we can just use
     // nsChangeHint_NeedReflow | nsChangeHint_NeedDirtyReflow here.
     nsSVGEffects::InvalidateRenderingObservers(mFrame);
     // XXXSDL KILL THIS!!!
     nsSVGUtils::ScheduleReflowSVG(mFrame);
   }
-  mFramePresShell->FrameConstructor()->PostRestyleEvent(
+  mFramePresShell->GetPresContext()->RestyleManager()->PostRestyleEvent(
     mFrame->GetContent()->AsElement(), nsRestyleHint(0), changeHint);
 }
 
 bool
 nsSVGTextPathProperty::TargetIsValid()
 {
   Element* target = GetTarget();
   return target && target->IsSVG(nsGkAtoms::path);
@@ -320,17 +320,17 @@ nsSVGTextPathProperty::DoUpdate()
     // Just return if we were previously invalid, and are still invalid.
     return;
   }
   mValid = nowValid;
 
   // Repaint asynchronously in case the path frame is being torn down
   nsChangeHint changeHint =
     nsChangeHint(nsChangeHint_RepaintFrame | nsChangeHint_UpdateTextPath);
-  mFramePresShell->FrameConstructor()->PostRestyleEvent(
+  mFramePresShell->GetPresContext()->RestyleManager()->PostRestyleEvent(
     mFrame->GetContent()->AsElement(), nsRestyleHint(0), changeHint);
 }
 
 void
 nsSVGPaintingProperty::DoUpdate()
 {
   nsSVGIDRenderingObserver::DoUpdate();
   if (!mFrame)