Bug 1352306 - Part 2: stylo: Only snapshot EventStates if there is some rule that depends on it. r=emilio draft
authorCameron McCormack <cam@mcc.id.au>
Tue, 09 May 2017 18:13:45 +0800
changeset 596234 91064f1837516c7401cbf12c6ab0b343fa7c51d0
parent 596233 149334dacb7658b46c477b5286af67453deb5961
child 633888 b2f0e3a855b8a6c31ce2f4b045fce8a5a69411a7
push id64550
push userbmo:cam@mcc.id.au
push dateMon, 19 Jun 2017 01:35:57 +0000
reviewersemilio
bugs1352306
milestone56.0a1
Bug 1352306 - Part 2: stylo: Only snapshot EventStates if there is some rule that depends on it. r=emilio MozReview-Commit-ID: J5xhdi7pGSv
layout/base/ServoRestyleManager.cpp
layout/style/ServoBindingList.h
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -777,16 +777,26 @@ ServoRestyleManager::ContentStateChanged
   // vs processing the restyle hint in-place, dirtying the nodes on
   // PostRestyleEvent.
   //
   // If we definitely take the snapshot approach, we should take rid of
   // HasStateDependentStyle, etc (though right now they're no-ops).
   ContentStateChangedInternal(aElement, aChangedBits, &changeHint,
                               &restyleHint);
 
+  // Don't bother taking a snapshot if no rules depend on these state bits.
+  //
+  // We always take a snapshot for the LTR/RTL event states, since Servo doesn't
+  // track those bits in the same way, and we know that :dir() rules are always
+  // present in UA style sheets.
+  if (!aChangedBits.HasAtLeastOneOfStates(DIRECTION_STATES) &&
+      !StyleSet()->HasStateDependency(aChangedBits)) {
+    return;
+  }
+
   ServoElementSnapshot& snapshot = SnapshotFor(aElement);
   EventStates previousState = aElement->StyleState() ^ aChangedBits;
   snapshot.AddState(previousState);
 
   if (Element* parent = aElement->GetFlattenedTreeParentElementForStyle()) {
     parent->NoteDirtyDescendantsForServo();
   }
   PostRestyleEvent(aElement, restyleHint, changeHint);
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -94,16 +94,19 @@ SERVO_BINDING_FUNC(Servo_StyleSet_GetCou
 SERVO_BINDING_FUNC(Servo_StyleSet_ResolveForDeclarations,
                    ServoComputedValuesStrong,
                    RawServoStyleSetBorrowed set,
                    ServoComputedValuesBorrowedOrNull parent_style,
                    RawServoDeclarationBlockBorrowed declarations)
 SERVO_BINDING_FUNC(Servo_StyleSet_MightHaveAttributeDependency, bool,
                    RawServoStyleSetBorrowed set,
                    nsIAtom* local_name)
+SERVO_BINDING_FUNC(Servo_StyleSet_HasStateDependency, bool,
+                   RawServoStyleSetBorrowed set,
+                   uint64_t state)
 
 // CSSRuleList
 SERVO_BINDING_FUNC(Servo_CssRules_ListTypes, void,
                    ServoCssRulesBorrowed rules,
                    nsTArrayBorrowed_uintptr_t result)
 SERVO_BINDING_FUNC(Servo_CssRules_InsertRule, nsresult,
                    ServoCssRulesBorrowed rules,
                    RawServoStyleSheetBorrowed sheet, const nsACString* rule,
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -1357,9 +1357,15 @@ ServoStyleSet::RunPostTraversalTasks()
 }
 
 bool
 ServoStyleSet::MightHaveAttributeDependency(nsIAtom* aAttribute)
 {
   return Servo_StyleSet_MightHaveAttributeDependency(mRawSet.get(), aAttribute);
 }
 
+bool
+ServoStyleSet::HasStateDependency(EventStates aState)
+{
+  return Servo_StyleSet_HasStateDependency(mRawSet.get(), aState.ServoValue());
+}
+
 ServoStyleSet* ServoStyleSet::sInServoTraversal = nullptr;
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -437,16 +437,26 @@ public:
    * local name might require us to restyle the element.
    *
    * This function allows us to skip taking a an attribute snapshot when
    * the modified attribute doesn't appear in an attribute selector in
    * a style sheet.
    */
   bool MightHaveAttributeDependency(nsIAtom* aAttribute);
 
+  /**
+   * Returns true if a change in event state on an element might require
+   * us to restyle the element.
+   *
+   * This function allows us to skip taking a state snapshot when
+   * the changed state isn't depended upon by any pseudo-class selectors
+   * in a style sheet.
+   */
+  bool HasStateDependency(EventStates aState);
+
 private:
   // On construction, sets sInServoTraversal to the given ServoStyleSet.
   // On destruction, clears sInServoTraversal and calls RunPostTraversalTasks.
   class MOZ_STACK_CLASS AutoSetInServoTraversal
   {
   public:
     explicit AutoSetInServoTraversal(ServoStyleSet* aSet)
       : mSet(aSet)