Bug 1382078 Part 4 - Avoid unneeded restyle when XBL styleset is utilized by different PresContext. draft
authorTing-Yu Lin <tlin@mozilla.com>
Mon, 04 Sep 2017 17:57:00 +0800
changeset 658692 54baa95de1eb35a3f59fab9d6a6e8f5a8377f972
parent 658691 cf3bf901963a27356b16dcb15dff19cdf26d1e10
child 729720 4faf3db7952991573cb47ec80e1fb0d77289cd4a
push id77838
push userbmo:tlin@mozilla.com
push dateMon, 04 Sep 2017 14:13:04 +0000
bugs1382078
milestone57.0a1
Bug 1382078 Part 4 - Avoid unneeded restyle when XBL styleset is utilized by different PresContext. This fixed layout/style/test/test_media_queries_dynamic.html after Part 3 is added. MozReview-Commit-ID: 7ZpSunCnkIc
dom/xbl/nsBindingManager.cpp
layout/style/ServoBindingList.h
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
--- a/dom/xbl/nsBindingManager.cpp
+++ b/dom/xbl/nsBindingManager.cpp
@@ -750,17 +750,17 @@ nsBindingManager::MediumFeaturesChanged(
 
   EnumerateBoundContentBindings([=, &rulesChanged](nsXBLBinding* aBinding) {
     if (isStyledByServo) {
       ServoStyleSet* styleSet = aBinding->PrototypeBinding()->GetServoStyleSet();
       if (styleSet) {
         bool styleSetChanged = false;
 
         if (styleSet->IsPresContextChanged(presContext)) {
-          styleSetChanged = true;
+          styleSetChanged = styleSet->SetPresContext(presContext);
         } else {
           // PresContext is not changed. This means aPresContext is still
           // alive since the last time it initialized this XBL styleset.
           // It's safe to check whether medium features changed.
           bool viewportUnitsUsed = false;
           styleSetChanged =
             styleSet->MediumFeaturesChangedRules(&viewportUnitsUsed);
           MOZ_ASSERT(!viewportUnitsUsed,
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -69,16 +69,21 @@ SERVO_BINDING_FUNC(Servo_StyleSheet_GetO
 SERVO_BINDING_FUNC(Servo_StyleSet_Init, RawServoStyleSet*, RawGeckoPresContextOwned pres_context)
 SERVO_BINDING_FUNC(Servo_StyleSet_RebuildCachedData, void,
                    RawServoStyleSetBorrowed set)
 // We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
 // work as return values with the Linux 32-bit ABI at the moment because
 // they wrap the value in a struct.
 SERVO_BINDING_FUNC(Servo_StyleSet_MediumFeaturesChanged, uint8_t,
                    RawServoStyleSetBorrowed set, bool* viewport_units_used)
+// We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
+// work as return values with the Linux 32-bit ABI at the moment because
+// they wrap the value in a struct.
+SERVO_BINDING_FUNC(Servo_StyleSet_SetDevice, uint8_t,
+                   RawServoStyleSetBorrowed set, RawGeckoPresContextOwned pres_context)
 SERVO_BINDING_FUNC(Servo_StyleSet_Drop, void, RawServoStyleSetOwned set)
 SERVO_BINDING_FUNC(Servo_StyleSet_CompatModeChanged, void,
                    RawServoStyleSetBorrowed raw_data)
 SERVO_BINDING_FUNC(Servo_StyleSet_AppendStyleSheet, void,
                    RawServoStyleSetBorrowed set,
                    const mozilla::ServoStyleSheet* gecko_sheet)
 SERVO_BINDING_FUNC(Servo_StyleSet_PrependStyleSheet, void,
                    RawServoStyleSetBorrowed set,
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -104,17 +104,17 @@ ServoStyleSet::~ServoStyleSet()
     }
   }
 }
 
 void
 ServoStyleSet::Init(nsPresContext* aPresContext, nsBindingManager* aBindingManager)
 {
   mPresContext = aPresContext;
-  mPresContextInitXBLStyleSet = aPresContext;
+  mLastPresContextUsesXBLStyleSet = aPresContext;
 
   mRawSet.reset(Servo_StyleSet_Init(aPresContext));
   mBindingManager = aBindingManager;
 
   mPresContext->DeviceContext()->InitFontCache();
 
   // Now that we have an mRawSet, go ahead and notify about whatever stylesheets
   // we have so far.
@@ -161,16 +161,34 @@ ServoStyleSet::Shutdown()
 
 void
 ServoStyleSet::InvalidateStyleForCSSRuleChanges()
 {
   MOZ_ASSERT(StylistNeedsUpdate());
   mPresContext->RestyleManager()->AsServo()->PostRestyleEventForCSSRuleChanges();
 }
 
+bool
+ServoStyleSet::SetPresContext(nsPresContext* aPresContext)
+{
+  MOZ_ASSERT(IsForXBL(), "Only XBL styleset can set PresContext!");
+
+  mLastPresContextUsesXBLStyleSet = aPresContext;
+
+  const OriginFlags rulesChanged = static_cast<OriginFlags>(
+    Servo_StyleSet_SetDevice(mRawSet.get(), aPresContext));
+
+  if (rulesChanged != OriginFlags(0)) {
+    MarkOriginsDirty(rulesChanged);
+    return true;
+  }
+
+  return false;
+}
+
 nsRestyleHint
 ServoStyleSet::MediumFeaturesChanged(bool aViewportChanged)
 {
   bool viewportUnitsUsed = false;
   bool rulesChanged = MediumFeaturesChangedRules(&viewportUnitsUsed);
 
   if (mBindingManager &&
       mBindingManager->MediumFeaturesChanged(mPresContext)) {
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -435,21 +435,25 @@ public:
   // Returns the style rule map.
   ServoStyleRuleMap* StyleRuleMap();
 
   // Clear mPresContext. This is needed after XBL ServoStyleSet is created.
   void ClearPresContext() {
     mPresContext = nullptr;
   }
 
-  // Return whether this is the PresContext that initialized us.
+  // Return whether this is the last PresContext which uses this XBL styleset.
   bool IsPresContextChanged(nsPresContext* aPresContext) const {
-    return aPresContext != mPresContextInitXBLStyleSet;
+    return aPresContext != mLastPresContextUsesXBLStyleSet;
   }
 
+  // Set PresContext (i.e. Device) for mRawSet. This should be called only
+  // by XBL stylesets. Returns true if there is any rule changing.
+  bool SetPresContext(nsPresContext* aPresContext);
+
   /**
    * Returns true if a modification to an an attribute with the specified
    * 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.
    */
@@ -582,19 +586,19 @@ private:
                          ServoStyleSheet* aSheet);
 
   const Kind mKind;
 
   // Nullptr if this is an XBL style set.
   nsPresContext* MOZ_NON_OWNING_REF mPresContext = nullptr;
 
   // Because XBL style set could be used by multiple PresContext, we need to
-  // store the PresContext pointer which initializes this style set for
+  // store the last PresContext pointer which uses this XBL styleset for
   // computing medium rule changes.
-  void* MOZ_NON_OWNING_REF mPresContextInitXBLStyleSet = nullptr;
+  void* MOZ_NON_OWNING_REF mLastPresContextUsesXBLStyleSet = nullptr;
 
   UniquePtr<RawServoStyleSet> mRawSet;
   EnumeratedArray<SheetType, SheetType::Count,
                   nsTArray<RefPtr<ServoStyleSheet>>> mSheets;
   bool mAuthorStyleDisabled;
   StylistState mStylistState;
   uint64_t mUserFontSetUpdateGeneration;
   uint32_t mUserFontCacheUpdateGeneration;