Bug 1382078 Part 4 - Avoid unneeded restyle when XBL styleset is utilized by different PresContext. r=emilio
authorTing-Yu Lin <tlin@mozilla.com>
Mon, 04 Sep 2017 17:57:00 +0800
changeset 428302 b58e786853341e5b280d6c0212bde732f447681d
parent 428301 e06654eaa8c755d6eceef8003d91b5bdb0d01a28
child 428303 a7e16582c59b49efddc4b197637541fbb5317fc6
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1382078
milestone57.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 1382078 Part 4 - Avoid unneeded restyle when XBL styleset is utilized by different PresContext. r=emilio 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;