Bug 1326167 - Hook ServoStyleSheet and ServoCSSRuleList into cycle collection. r=bz draft
authorXidorn Quan <me@upsuper.org>
Fri, 06 Jan 2017 15:14:28 +1100
changeset 456806 8bab3247e2ef101c190881ec4d19a8bb543587e0
parent 456805 4f8edfeee4a83ac37e7ccf4abfec8e0d25d528d7
child 541322 a5afb8b5fdca87f5ea7c73412f2251d435ca1c82
push id40603
push userxquan@mozilla.com
push dateFri, 06 Jan 2017 07:30:42 +0000
reviewersbz
bugs1326167
milestone53.0a1
Bug 1326167 - Hook ServoStyleSheet and ServoCSSRuleList into cycle collection. r=bz MozReview-Commit-ID: 6n1rjB8aMqp
layout/style/ServoCSSRuleList.cpp
layout/style/ServoCSSRuleList.h
layout/style/ServoStyleSheet.cpp
layout/style/ServoStyleSheet.h
--- a/layout/style/ServoCSSRuleList.cpp
+++ b/layout/style/ServoCSSRuleList.cpp
@@ -19,16 +19,43 @@ ServoCSSRuleList::ServoCSSRuleList(Servo
   , mRawRules(aRawRules)
 {
   Servo_CssRules_ListTypes(mRawRules, &mRules);
   // XXX We may want to eagerly create object for import rule, so that
   //     we don't lose the reference to child stylesheet when our own
   //     stylesheet goes away.
 }
 
+// QueryInterface implementation for ServoCSSRuleList
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoCSSRuleList)
+NS_INTERFACE_MAP_END_INHERITING(dom::CSSRuleList)
+
+NS_IMPL_ADDREF_INHERITED(ServoCSSRuleList, dom::CSSRuleList)
+NS_IMPL_RELEASE_INHERITED(ServoCSSRuleList, dom::CSSRuleList)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(ServoCSSRuleList)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ServoCSSRuleList)
+  for (uintptr_t& rule : tmp->mRules) {
+    if (rule > kMaxRuleType) {
+      CastToPtr(rule)->Release();
+      // Safest to set it to zero, in case someone else pokes at it
+      // during their own unlinking process.
+      rule = 0;
+    }
+  }
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(dom::CSSRuleList)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoCSSRuleList,
+                                                  dom::CSSRuleList)
+  tmp->EnumerateInstantiatedRules([&](css::Rule* aRule) {
+    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRules[i]");
+    cb.NoteXPCOMChild(aRule->GetExistingDOMRule());
+  });
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
 css::Rule*
 ServoCSSRuleList::GetRule(uint32_t aIndex)
 {
   uintptr_t rule = mRules[aIndex];
   if (rule <= kMaxRuleType) {
     RefPtr<css::Rule> ruleObj = nullptr;
     switch (rule) {
       case nsIDOMCSSRule::STYLE_RULE: {
--- a/layout/style/ServoCSSRuleList.h
+++ b/layout/style/ServoCSSRuleList.h
@@ -20,16 +20,19 @@ class Rule;
 } // namespace css
 
 class ServoCSSRuleList final : public dom::CSSRuleList
 {
 public:
   ServoCSSRuleList(ServoStyleSheet* aStyleSheet,
                    already_AddRefed<ServoCssRules> aRawRules);
 
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServoCSSRuleList, dom::CSSRuleList)
+
   ServoStyleSheet* GetParentObject() final { return mStyleSheet; }
 
   nsIDOMCSSRule* IndexedGetter(uint32_t aIndex, bool& aFound) final;
   uint32_t Length() final { return mRules.Length(); }
 
   void DropReference();
 
   css::Rule* GetRule(uint32_t aIndex);
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -25,21 +25,34 @@ ServoStyleSheet::ServoStyleSheet(css::Sh
   : StyleSheet(StyleBackendType::Servo, aParsingMode)
   , mSheetInfo(aCORSMode, aReferrerPolicy, aIntegrity)
 {
 }
 
 ServoStyleSheet::~ServoStyleSheet()
 {
   DropSheet();
-  if (mRuleList) {
-    mRuleList->DropReference();
-  }
 }
 
+// QueryInterface implementation for ServoStyleSheet
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoStyleSheet)
+NS_INTERFACE_MAP_END_INHERITING(StyleSheet)
+
+NS_IMPL_ADDREF_INHERITED(ServoStyleSheet, StyleSheet)
+NS_IMPL_RELEASE_INHERITED(ServoStyleSheet, StyleSheet)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(ServoStyleSheet)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ServoStyleSheet)
+  tmp->DropRuleList();
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(StyleSheet)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoStyleSheet, StyleSheet)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRuleList)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
 bool
 ServoStyleSheet::HasRules() const
 {
   return mSheet && Servo_StyleSheet_HasRules(mSheet);
 }
 
 void
 ServoStyleSheet::SetOwningDocument(nsIDocument* aDocument)
@@ -101,16 +114,26 @@ ServoStyleSheet::LoadFailed()
 {
   mSheet = Servo_StyleSheet_Empty(mParsingMode).Consume();
 }
 
 void
 ServoStyleSheet::DropSheet()
 {
   mSheet = nullptr;
+  DropRuleList();
+}
+
+void
+ServoStyleSheet::DropRuleList()
+{
+  if (mRuleList) {
+    mRuleList->DropReference();
+    mRuleList = nullptr;
+  }
 }
 
 size_t
 ServoStyleSheet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   MOZ_CRASH("stylo: not implemented");
 }
 
--- a/layout/style/ServoStyleSheet.h
+++ b/layout/style/ServoStyleSheet.h
@@ -28,16 +28,19 @@ class Loader;
 class ServoStyleSheet : public StyleSheet
 {
 public:
   ServoStyleSheet(css::SheetParsingMode aParsingMode,
                   CORSMode aCORSMode,
                   net::ReferrerPolicy aReferrerPolicy,
                   const dom::SRIMetadata& aIntegrity);
 
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServoStyleSheet, StyleSheet)
+
   bool HasRules() const;
 
   void SetOwningDocument(nsIDocument* aDocument);
 
   ServoStyleSheet* GetParentSheet() const;
   void AppendStyleSheet(ServoStyleSheet* aSheet);
 
   MOZ_MUST_USE nsresult ParseSheet(css::Loader* aLoader,
@@ -84,16 +87,17 @@ protected:
   // Internal methods which do not have security check and completeness check.
   dom::CSSRuleList* GetCssRulesInternal(ErrorResult& aRv);
   uint32_t InsertRuleInternal(const nsAString& aRule,
                               uint32_t aIndex, ErrorResult& aRv);
   void DeleteRuleInternal(uint32_t aIndex, ErrorResult& aRv);
 
 private:
   void DropSheet();
+  void DropRuleList();
 
   RefPtr<RawServoStyleSheet> mSheet;
   RefPtr<ServoCSSRuleList> mRuleList;
   StyleSheetInfo mSheetInfo;
 
   friend class StyleSheet;
 };