Bug 1512256 - Move FragmentOrElement::mAttrs to Element, r=ehsan
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Thu, 06 Dec 2018 15:58:40 +0200
changeset 508754 10320b5096c2407df1919a55a37d7d7f26db10e2
parent 508717 f7895b06b74299a13bba51e3de50c8eaa9729e10
child 508755 7dee627d2f740f0190ae1be201ac3bf9eaaa5659
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1512256
milestone65.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 1512256 - Move FragmentOrElement::mAttrs to Element, r=ehsan
dom/base/Element.cpp
dom/base/Element.h
dom/base/FragmentOrElement.cpp
dom/base/FragmentOrElement.h
servo/components/style/gecko/wrapper.rs
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -3129,16 +3129,34 @@ nsDOMTokenList* Element::GetTokenList(
   if (!list) {
     list = new nsDOMTokenList(this, aAtom, aSupportedTokens);
     NS_ADDREF(list);
     SetProperty(aAtom, list, nsDOMTokenListPropertyDestructor);
   }
   return list;
 }
 
+nsresult Element::CopyInnerTo(Element* aDst) {
+  nsresult rv = aDst->mAttrs.EnsureCapacityToClone(mAttrs);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  uint32_t i, count = mAttrs.AttrCount();
+  for (i = 0; i < count; ++i) {
+    const nsAttrName* name = mAttrs.AttrNameAt(i);
+    const nsAttrValue* value = mAttrs.AttrAt(i);
+    nsAutoString valStr;
+    value->ToString(valStr);
+    rv = aDst->SetAttr(name->NamespaceID(), name->LocalName(),
+                       name->GetPrefix(), valStr, false);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  return NS_OK;
+}
+
 Element* Element::Closest(const nsAString& aSelector, ErrorResult& aResult) {
   const RawServoSelectorList* list = ParseSelectorList(aSelector, aResult);
   if (!list) {
     return nullptr;
   }
 
   return const_cast<Element*>(Servo_SelectorList_Closest(this, list));
 }
@@ -3914,16 +3932,17 @@ void Element::SetCustomElementDefinition
 }
 
 MOZ_DEFINE_MALLOC_SIZE_OF(ServoElementMallocSizeOf)
 MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(ServoElementMallocEnclosingSizeOf)
 
 void Element::AddSizeOfExcludingThis(nsWindowSizes& aSizes,
                                      size_t* aNodeSize) const {
   FragmentOrElement::AddSizeOfExcludingThis(aSizes, aNodeSize);
+  *aNodeSize += mAttrs.SizeOfExcludingThis(aSizes.mState.mMallocSizeOf);
 
   if (HasServoData()) {
     // Measure the ElementData object itself.
     aSizes.mLayoutElementDataObjects +=
         aSizes.mState.mMallocSizeOf(mServoData.Get());
 
     // Measure mServoData, excluding the ComputedValues. This measurement
     // counts towards the element's size. We use ServoElementMallocSizeOf and
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -875,16 +875,23 @@ class Element : public FragmentOrElement
    * @note    The pointer returned by this function is only valid until the
    *          next call of either GetAttrNameAt or SetAttr on the element.
    */
   const nsAttrName* GetAttrNameAt(uint32_t aIndex) const {
     return mAttrs.GetSafeAttrNameAt(aIndex);
   }
 
   /**
+   * Same as above, but does not do out-of-bounds checks!
+   */
+  const nsAttrName* GetUnsafeAttrNameAt(uint32_t aIndex) const {
+    return mAttrs.AttrNameAt(aIndex);
+  }
+
+  /**
    * Gets the attribute info (name and value) for this element at a given index.
    */
   BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const {
     if (aIndex >= mAttrs.AttrCount()) {
       return BorrowedAttrInfo(nullptr, nullptr);
     }
 
     return mAttrs.AttrInfoAt(aIndex);
@@ -1846,16 +1853,22 @@ class Element : public FragmentOrElement
    * (e.g. _blank).
    */
   virtual void GetLinkTarget(nsAString& aTarget);
 
   nsDOMTokenList* GetTokenList(
       nsAtom* aAtom,
       const DOMTokenListSupportedTokenArray aSupportedTokens = nullptr);
 
+  /**
+   * Copy attributes and state to another element
+   * @param aDest the object to copy to
+   */
+  nsresult CopyInnerTo(Element* aDest);
+
  private:
   /**
    * Slow path for GetClasses, this should only be called for SVG elements.
    */
   const nsAttrValue* GetSVGAnimatedClass() const;
 
   /**
    * Get this element's client area rect in app units.
@@ -1878,16 +1891,20 @@ class Element : public FragmentOrElement
 
   // Data members
   EventStates mState;
   // Per-node data managed by Servo.
   //
   // There should not be data on nodes that are in the flattened tree, or
   // descendants of display: none elements.
   mozilla::RustCell<ServoNodeData*> mServoData;
+
+protected:
+  // Array containing all attributes for this element
+  AttrArray mAttrs;
 };
 
 class RemoveFromBindingManagerRunnable : public mozilla::Runnable {
  public:
   RemoveFromBindingManagerRunnable(nsBindingManager* aManager,
                                    nsIContent* aContent, nsIDocument* aDoc);
 
   NS_IMETHOD Run() override;
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -1903,54 +1903,37 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
             effectSet->Traverse(cb);
           }
         }
       }
     }
   }
 
   // Traverse attribute names.
-  {
+  if (tmp->IsElement()) {
+    Element* element = tmp->AsElement();
     uint32_t i;
-    uint32_t attrs = tmp->mAttrs.AttrCount();
+    uint32_t attrs = element->GetAttrCount();
     for (i = 0; i < attrs; i++) {
-      const nsAttrName* name = tmp->mAttrs.AttrNameAt(i);
+      const nsAttrName* name = element->GetUnsafeAttrNameAt(i);
       if (!name->IsAtom()) {
         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mAttrs[i]->NodeInfo()");
         cb.NoteNativeChild(name->NodeInfo(),
                            NS_CYCLE_COLLECTION_PARTICIPANT(NodeInfo));
       }
     }
   }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN(FragmentOrElement)
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(FragmentOrElement)
 NS_INTERFACE_MAP_END_INHERITING(nsIContent)
 
 //----------------------------------------------------------------------
 
-nsresult FragmentOrElement::CopyInnerTo(FragmentOrElement* aDst) {
-  nsresult rv = aDst->mAttrs.EnsureCapacityToClone(mAttrs);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  uint32_t i, count = mAttrs.AttrCount();
-  for (i = 0; i < count; ++i) {
-    const nsAttrName* name = mAttrs.AttrNameAt(i);
-    const nsAttrValue* value = mAttrs.AttrAt(i);
-    nsAutoString valStr;
-    value->ToString(valStr);
-    rv = aDst->AsElement()->SetAttr(name->NamespaceID(), name->LocalName(),
-                                    name->GetPrefix(), valStr, false);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  return NS_OK;
-}
-
 const nsTextFragment* FragmentOrElement::GetText() { return nullptr; }
 
 uint32_t FragmentOrElement::TextLength() const {
   // We can remove this assertion if it turns out to be useful to be able
   // to depend on this returning 0
   MOZ_ASSERT_UNREACHABLE("called FragmentOrElement::TextLength");
 
   return 0;
@@ -2162,15 +2145,14 @@ void FragmentOrElement::FireNodeRemovedF
        child = child->GetNextSibling()) {
     nsContentUtils::MaybeFireNodeRemoved(child, this);
   }
 }
 
 void FragmentOrElement::AddSizeOfExcludingThis(nsWindowSizes& aSizes,
                                                size_t* aNodeSize) const {
   nsIContent::AddSizeOfExcludingThis(aSizes, aNodeSize);
-  *aNodeSize += mAttrs.SizeOfExcludingThis(aSizes.mState.mMallocSizeOf);
 
   nsDOMSlots* slots = GetExistingDOMSlots();
   if (slots) {
     *aNodeSize += slots->SizeOfIncludingThis(aSizes.mState.mMallocSizeOf);
   }
 }
--- a/dom/base/FragmentOrElement.h
+++ b/dom/base/FragmentOrElement.h
@@ -11,17 +11,16 @@
  */
 
 #ifndef FragmentOrElement_h___
 #define FragmentOrElement_h___
 
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/UniquePtr.h"
-#include "AttrArray.h"                     // member
 #include "nsCycleCollectionParticipant.h"  // NS_DECL_CYCLE_*
 #include "nsIContent.h"                    // base class
 #include "nsNodeUtils.h"  // class member nsNodeUtils::CloneNodeImpl
 #include "nsIHTMLCollection.h"
 #include "nsDataHashtable.h"
 #include "nsXBLBinding.h"
 
 class ContentUnbinder;
@@ -139,20 +138,20 @@ class FragmentOrElement : public nsICont
    * Is the HTML local name a void element?
    */
   static bool IsHTMLVoid(nsAtom* aLocalName);
 
  protected:
   virtual ~FragmentOrElement();
 
   /**
-   * Copy attributes and state to another element
-   * @param aDest the object to copy to
+   * Dummy CopyInnerTo so that we can use the same macros for
+   * Elements and DocumentFragments.
    */
-  nsresult CopyInnerTo(FragmentOrElement* aDest);
+  nsresult CopyInnerTo(FragmentOrElement* aDest) { return NS_OK; }
 
  public:
   /**
    * There are a set of DOM- and scripting-specific instance variables
    * that may only be instantiated when a content object is accessed
    * through the DOM. Rather than burn actual slots in the content
    * objects for each of these instance variables, we put them off
    * in a side structure that's only allocated when the content is
@@ -300,20 +299,16 @@ class FragmentOrElement : public nsICont
         GetExistingExtendedContentSlots());
   }
 
   nsExtendedDOMSlots* GetExistingExtendedDOMSlots() {
     return static_cast<nsExtendedDOMSlots*>(GetExistingExtendedContentSlots());
   }
 
   friend class ::ContentUnbinder;
-  /**
-   * Array containing all attributes for this element
-   */
-  AttrArray mAttrs;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #define NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE               \
   if (NS_SUCCEEDED(rv)) return rv;                            \
                                                               \
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -576,17 +576,17 @@ impl<'le> fmt::Debug for GeckoElement<'l
         write!(f, "> ({:#x})", self.as_node().opaque().0)
     }
 }
 
 impl<'le> GeckoElement<'le> {
     #[inline(always)]
     fn attrs(&self) -> &[structs::AttrArray_InternalAttr] {
         unsafe {
-            let attrs = match self.0._base.mAttrs.mImpl.mPtr.as_ref() {
+            let attrs = match self.0.mAttrs.mImpl.mPtr.as_ref() {
                 Some(attrs) => attrs,
                 None => return &[],
             };
 
             attrs.mBuffer.as_slice(attrs.mAttrCount as usize)
         }
     }