Bug 1031149 - Consistently pass correct aRelevantLinkVisited to nsStyleContext::FindChildWithRules. r=heycam
authorL. David Baron <dbaron@dbaron.org>
Sat, 02 Aug 2014 19:37:42 -0700
changeset 197476 9fc64f0449016bc147da8f336b6ab635de672038
parent 197475 2bdb11379d0f31febb6f55c7b1af9a510e5785a0
child 197477 96186774f07c087a05c6798966ddef2440c1350e
push id47142
push userdbaron@mozilla.com
push dateSun, 03 Aug 2014 02:38:23 +0000
treeherdermozilla-inbound@1636ae2d7b53 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1031149
milestone34.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 1031149 - Consistently pass correct aRelevantLinkVisited to nsStyleContext::FindChildWithRules. r=heycam I believe this will fix some cache misses in the FindChildWithRules lookup when restyling. I don't think it will fix any correctness bugs because the RelevantLinkVisited() bit will always end up set to true anyway as the non-link descendant of a visited link style context, and link descendants shouldn't be able to share styles with non-link descendants due to matching rules in the UA style sheet.
layout/style/nsStyleSet.cpp
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -783,21 +783,25 @@ nsStyleSet::GetContext(nsStyleContext* a
 
   if (aFlags & eIsLink) {
     // If this node is a link, we want its visited's style context's
     // parent to be the regular style context of its parent, because
     // only the visitedness of the relevant link should influence style.
     parentIfVisited = aParentContext;
   }
 
+  bool relevantLinkVisited = (aFlags & eIsLink) ?
+    (aFlags & eIsVisitedLink) :
+    (aParentContext && aParentContext->RelevantLinkVisited());
+
   nsRefPtr<nsStyleContext> result;
   if (aParentContext)
     result = aParentContext->FindChildWithRules(aPseudoTag, aRuleNode,
                                                 aVisitedRuleNode,
-                                                aFlags & eIsVisitedLink);
+                                                relevantLinkVisited);
 
 #ifdef NOISY_DEBUG
   if (result)
     fprintf(stdout, "--- SharedSC %d ---\n", ++gSharedCount);
   else
     fprintf(stdout, "+++ NewSC %d +++\n", ++gNewCount);
 #endif
 
@@ -811,20 +815,16 @@ nsStyleSet::GetContext(nsStyleContext* a
                            aVisitedRuleNode,
                            aFlags & eSkipParentDisplayBasedStyleFixup);
       if (!parentIfVisited) {
         mRoots.AppendElement(resultIfVisited);
       }
       resultIfVisited->SetIsStyleIfVisited();
       result->SetStyleIfVisited(resultIfVisited.forget());
 
-      bool relevantLinkVisited = (aFlags & eIsLink) ?
-        (aFlags & eIsVisitedLink) :
-        (aParentContext && aParentContext->RelevantLinkVisited());
-
       if (relevantLinkVisited) {
         result->AddStyleBit(NS_STYLE_RELEVANT_LINK_VISITED);
       }
     }
     if (!aParentContext) {
       mRoots.AppendElement(result);
     }
   }
@@ -1301,19 +1301,23 @@ nsStyleSet::ResolveStyleByAddingRules(ns
       ruleWalker.ForwardOnPossiblyCSSRule(aRules.ObjectAt(i));
     }
     visitedRuleNode = ruleWalker.CurrentNode();
   }
 
   uint32_t flags = eNoFlags;
   if (aBaseContext->IsLinkContext()) {
     flags |= eIsLink;
-  }
-  if (aBaseContext->RelevantLinkVisited()) {
-    flags |= eIsVisitedLink;
+
+    // GetContext handles propagating RelevantLinkVisited state from the
+    // parent in non-link cases; all we need to pass in is if this link
+    // is visited.
+    if (aBaseContext->RelevantLinkVisited()) {
+      flags |= eIsVisitedLink;
+    }
   }
   return GetContext(aBaseContext->GetParent(), ruleNode, visitedRuleNode,
                     aBaseContext->GetPseudo(),
                     aBaseContext->GetPseudoType(),
                     nullptr, flags);
 }
 
 already_AddRefed<nsStyleContext>
@@ -1864,27 +1868,23 @@ nsStyleSet::ReparentStyleContext(nsStyle
                             pseudoType !=
                               nsCSSPseudoElements::ePseudo_NotPseudoElement);
      }
   }
 
   uint32_t flags = eNoFlags;
   if (aStyleContext->IsLinkContext()) {
     flags |= eIsLink;
-  }
 
-  // If we're a style context for a link, then we already know whether
-  // our relevant link is visited, since that does not depend on our
-  // parent.  Otherwise, we need to match aNewParentContext.
-  bool relevantLinkVisited = aStyleContext->IsLinkContext() ?
-    aStyleContext->RelevantLinkVisited() :
-    aNewParentContext->RelevantLinkVisited();
-
-  if (relevantLinkVisited) {
-    flags |= eIsVisitedLink;
+    // GetContext handles propagating RelevantLinkVisited state from the
+    // parent in non-link cases; all we need to pass in is if this link
+    // is visited.
+    if (aStyleContext->RelevantLinkVisited()) {
+      flags |= eIsVisitedLink;
+    }
   }
 
   if (pseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement ||
       pseudoType == nsCSSPseudoElements::ePseudo_before ||
       pseudoType == nsCSSPseudoElements::ePseudo_after) {
     flags |= eDoAnimation;
   }