Bug 1321284 - Part 5: Process document level NAC when restyling. r=bholley
authorCameron McCormack <cam@mcc.id.au>
Thu, 01 Dec 2016 16:19:50 +0800
changeset 370158 3976b04bf08a4442eb75cace5ad4899ca0eb0ced
parent 370157 1cb9bcc84d128984a3018c9dce2378264c471ff4
child 370159 11d06cafe634dfa7981cfdca62c0b34d04a22a84
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1321284
milestone53.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 1321284 - Part 5: Process document level NAC when restyling. r=bholley MozReview-Commit-ID: GigSrTHXXte
layout/base/RestyleManagerHandleInlines.h
layout/base/ServoRestyleManager.cpp
layout/base/ServoRestyleManager.h
layout/base/ServoRestyleManagerInlines.h
layout/base/moz.build
layout/base/nsPresContext.cpp
layout/style/ServoStyleSet.cpp
--- a/layout/base/RestyleManagerHandleInlines.h
+++ b/layout/base/RestyleManagerHandleInlines.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_RestyleManagerHandleInlines_h
 #define mozilla_RestyleManagerHandleInlines_h
 
 #include "mozilla/RestyleManager.h"
 #include "mozilla/ServoRestyleManager.h"
+#include "mozilla/ServoRestyleManagerInlines.h"
 
 #define FORWARD_CONCRETE(method_, geckoargs_, servoargs_) \
   if (IsGecko()) { \
     return AsGecko()->method_ geckoargs_; \
   } else { \
     return AsServo()->method_ servoargs_; \
   }
 
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -1,16 +1,19 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ServoRestyleManager.h"
+
+#include "mozilla/DocumentStyleRootIterator.h"
 #include "mozilla/ServoBindings.h"
+#include "mozilla/ServoRestyleManagerInlines.h"
 #include "mozilla/ServoStyleSet.h"
 #include "mozilla/dom/ChildIterator.h"
 #include "nsContentUtils.h"
 #include "nsPrintfCString.h"
 #include "nsStyleChangeList.h"
 
 using namespace mozilla::dom;
 
@@ -284,37 +287,38 @@ ServoRestyleManager::ProcessPendingResty
   }
 
   if (!HasPendingRestyles()) {
     return;
   }
 
   ServoStyleSet* styleSet = StyleSet();
   nsIDocument* doc = PresContext()->Document();
-  Element* root = doc->GetRootElement();
 
   // XXXbholley: Should this be while() per bug 1316247?
   if (HasPendingRestyles()) {
-    MOZ_ASSERT(root);
     mInStyleRefresh = true;
     styleSet->StyleDocument();
 
     // First do any queued-up frame creation. (see bugs 827239 and 997506).
     //
     // XXXEmilio I'm calling this to avoid random behavior changes, since we
     // delay frame construction after styling we should re-check once our
     // model is more stable whether we can skip this call.
     //
     // Note this has to be *after* restyling, because otherwise frame
     // construction will find unstyled nodes, and that's not funny.
     PresContext()->FrameConstructor()->CreateNeededFrames();
 
     // Recreate style contexts and queue up change hints.
     nsStyleChangeList currentChanges;
-    RecreateStyleContexts(root, nullptr, styleSet, currentChanges);
+    DocumentStyleRootIterator iter(doc);
+    while (Element* root = iter.GetNextStyleRoot()) {
+      RecreateStyleContexts(root, nullptr, styleSet, currentChanges);
+    }
 
     // Process the change hints.
     //
     // Unfortunately, the frame constructor can generate new change hints while
     // processing existing ones. We redirect those into a secondary queue and
     // iterate until there's nothing left.
     ReentrantChangeList newChanges;
     mReentrantChanges = &newChanges;
--- a/layout/base/ServoRestyleManager.h
+++ b/layout/base/ServoRestyleManager.h
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_ServoRestyleManager_h
 #define mozilla_ServoRestyleManager_h
 
+#include "mozilla/DocumentStyleRootIterator.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/RestyleManagerBase.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/ServoElementSnapshot.h"
 #include "nsChangeHint.h"
 #include "nsHashKeys.h"
 #include "nsINode.h"
 #include "nsISupportsImpl.h"
@@ -73,21 +74,17 @@ public:
                            const nsAttrValue* aNewValue);
 
   void AttributeChanged(dom::Element* aElement, int32_t aNameSpaceID,
                         nsIAtom* aAttribute, int32_t aModType,
                         const nsAttrValue* aOldValue);
 
   nsresult ReparentStyleContext(nsIFrame* aFrame);
 
-  bool HasPendingRestyles()
-  {
-    Element* root = PresContext()->Document()->GetRootElement();
-    return root && root->HasDirtyDescendantsForServo();
-  }
+  inline bool HasPendingRestyles();
 
 
   /**
    * Gets the appropriate frame given a content and a pseudo-element tag.
    *
    * Right now only supports a null tag, before or after. If the pseudo-element
    * is not null, the content needs to be an element.
    */
new file mode 100644
--- /dev/null
+++ b/layout/base/ServoRestyleManagerInlines.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef ServoRestyleManagerInlines_h
+#define ServoRestyleManagerInlines_h
+
+#include "ServoRestyleManager.h"
+
+#include "mozilla/dom/ElementInlines.h"
+
+namespace mozilla {
+
+using namespace dom;
+
+inline bool
+ServoRestyleManager::HasPendingRestyles()
+{
+  nsIDocument* doc = PresContext()->Document();
+  DocumentStyleRootIterator iter(doc);
+  while (Element* root = iter.GetNextStyleRoot()) {
+    if (root->ShouldTraverseForServo()) {
+      return true;
+    }
+  }
+  return false;
+}
+
+} // namespace mozilla
+
+#endif // ServoRestyleManagerInlines_h
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -73,16 +73,17 @@ EXPORTS.mozilla += [
     'OverflowChangedTracker.h',
     'PresShell.h',
     'RestyleLogging.h',
     'RestyleManager.h',
     'RestyleManagerBase.h',
     'RestyleManagerHandle.h',
     'RestyleManagerHandleInlines.h',
     'ServoRestyleManager.h',
+    'ServoRestyleManagerInlines.h',
     'StaticPresData.h',
 ]
 
 UNIFIED_SOURCES += [
     'AccessibleCaret.cpp',
     'AccessibleCaretEventHub.cpp',
     'AccessibleCaretManager.cpp',
     'FramePropertyTable.cpp',
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -71,16 +71,17 @@
 #include "nsContentUtils.h"
 #include "nsPIWindowRoot.h"
 #include "mozilla/Preferences.h"
 #include "gfxTextRun.h"
 #include "nsFontFaceUtils.h"
 #include "nsLayoutStylesheetCache.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
+#include "mozilla/ServoRestyleManagerInlines.h"
 
 #if defined(MOZ_WIDGET_GTK)
 #include "gfxPlatformGtk.h" // xxx - for UseFcFontList
 #endif
 
 
 // Needed for Start/Stop of Image Animation
 #include "imgIContainer.h"
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ServoStyleSet.h"
 
+#include "mozilla/DocumentStyleRootIterator.h"
 #include "mozilla/ServoRestyleManager.h"
 #include "mozilla/dom/ChildIterator.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsCSSPseudoElements.h"
 #include "nsIDocumentInlines.h"
 #include "nsPrintfCString.h"
 #include "nsStyleContext.h"
 #include "nsStyleSet.h"
@@ -41,17 +42,18 @@ ServoStyleSet::BeginShutdown()
   // frame tree has been destroyed, but before the script runners that delete
   // native anonymous content (which also could be holding on the RuleNodes)
   // have run.  By clearing style here, before the frame tree is destroyed,
   // the AllChildrenIterator will find the anonymous content.
   //
   // Note that this is pretty bad for performance; we should find a way to
   // get by with the ServoNodeDatas being dropped as part of the document
   // going away.
-  if (Element* root = mPresContext->Document()->GetRootElement()) {
+  DocumentStyleRootIterator iter(mPresContext->Document());
+  while (Element* root = iter.GetNextStyleRoot()) {
     ServoRestyleManager::ClearServoDataFromSubtree(root);
   }
 }
 
 void
 ServoStyleSet::Shutdown()
 {
   mRawSet = nullptr;
@@ -443,23 +445,24 @@ ServoStyleSet::HasStateDependentStyle(do
 {
   NS_WARNING("stylo: HasStateDependentStyle always returns zero!");
   return nsRestyleHint(0);
 }
 
 void
 ServoStyleSet::StyleDocument()
 {
-  // Grab the root.
-  nsIDocument* doc = mPresContext->Document();
-  Element* root = doc->GetRootElement();
-  MOZ_ASSERT(root);
-
-  // Restyle the document.
-  Servo_TraverseSubtree(root, mRawSet.get(), SkipRootBehavior::DontSkip);
+  // Restyle the document from the root element and each of the document level
+  // NAC subtree roots.
+  DocumentStyleRootIterator iter(mPresContext->Document());
+  while (Element* root = iter.GetNextStyleRoot()) {
+    if (root->ShouldTraverseForServo()) {
+      Servo_TraverseSubtree(root, mRawSet.get(), SkipRootBehavior::DontSkip);
+    }
+  }
 }
 
 void
 ServoStyleSet::StyleNewSubtree(nsIContent* aContent)
 {
   if (aContent->IsElement()) {
     Servo_TraverseSubtree(aContent->AsElement(), mRawSet.get(), SkipRootBehavior::DontSkip);
   }