Bug 1333183 - Prime the root element cache before the servo traversal. r=emilio
authorBobby Holley <bobbyholley@gmail.com>
Thu, 02 Feb 2017 14:03:46 -0800
changeset 341547 ed7112dfd38530f84a4f4be833181eedd2945b86
parent 341546 fadf7c2a257fbd6ae3f68bde9a9c679b15e391e2
child 341548 ec0c052396622afa2b54476fb4df20b49b921a52
push id86731
push userbholley@mozilla.com
push dateThu, 09 Feb 2017 01:05:07 +0000
treeherdermozilla-inbound@ed7112dfd385 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1333183
milestone54.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 1333183 - Prime the root element cache before the servo traversal. r=emilio
dom/base/nsDocument.cpp
layout/style/ServoStyleSet.cpp
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -4032,16 +4032,20 @@ nsIDocument::GetRootElement() const
 {
   return (mCachedRootElement && mCachedRootElement->GetParentNode() == this) ?
          mCachedRootElement : GetRootElementInternal();
 }
 
 Element*
 nsDocument::GetRootElementInternal() const
 {
+  // We invoke GetRootElement() immediately before the servo traversal, so we
+  // should always have a cache hit from Servo.
+  MOZ_ASSERT(NS_IsMainThread());
+
   // Loop backwards because any non-elements, such as doctypes and PIs
   // are likely to appear before the root element.
   uint32_t i;
   for (i = mChildren.ChildCount(); i > 0; --i) {
     nsIContent* child = mChildren.ChildAt(i - 1);
     if (child->IsElement()) {
       const_cast<nsDocument*>(this)->mCachedRootElement = child->AsElement();
       return child->AsElement();
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -187,16 +187,21 @@ ServoStyleSet::ResolveMappedAttrDeclarat
   }
 }
 
 void
 ServoStyleSet::PrepareAndTraverseSubtree(RawGeckoElementBorrowed aRoot,
                                          mozilla::TraversalRootBehavior aRootBehavior) {
   ResolveMappedAttrDeclarationBlocks();
 
+  // Get the Document's root element to ensure that the cache is valid before
+  // calling into the (potentially-parallel) Servo traversal, where a cache hit
+  // is necessary to avoid a data race when updating the cache.
+  mozilla::Unused << aRoot->OwnerDoc()->GetRootElement();
+
   MOZ_ASSERT(!sInServoTraversal);
   sInServoTraversal = true;
   Servo_TraverseSubtree(aRoot, mRawSet.get(), aRootBehavior);
   sInServoTraversal = false;
 }
 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ResolveStyleFor(Element* aElement,