Reduce a shadow root object's size by not inheriting DoublyLinkedList Using DoublyLinkedList increases a shadow root object's size by adding two pointers, m_prev and m_next. Because these pointers are only required for multiple shadow roots, these pointers can be moved to ShadowRootRareDataV0. - Maintain a doubly linked list manually, instead of inheriting DoublyLinkedList. - ElementShadow has only one shadowRoot object, instead of having DoublyLinkedList<ShadowRoot>. - ElementShadow::m_shadowRoot acts as the oldest shadow root in case for multiple shadow roots. BUG=531990 Review URL: https://codereview.chromium.org/1904923002 Cr-Commit-Position: refs/heads/master@{#389013}
diff --git a/third_party/WebKit/Source/core/dom/shadow/ElementShadow.cpp b/third_party/WebKit/Source/core/dom/shadow/ElementShadow.cpp index b4e93ba..393a0ea 100644 --- a/third_party/WebKit/Source/core/dom/shadow/ElementShadow.cpp +++ b/third_party/WebKit/Source/core/dom/shadow/ElementShadow.cpp
@@ -144,23 +144,35 @@ { } +ShadowRoot& ElementShadow::youngestShadowRoot() const +{ + ShadowRoot* current = m_shadowRoot; + DCHECK(current); + while (current->youngerShadowRoot()) + current = current->youngerShadowRoot(); + return *current; +} + ShadowRoot& ElementShadow::addShadowRoot(Element& shadowHost, ShadowRootType type) { EventDispatchForbiddenScope assertNoEventDispatch; ScriptForbiddenScope forbidScript; - if (type == ShadowRootType::V0 && !m_shadowRoots.isEmpty()) { - DCHECK_NE(ShadowRootType::UserAgent, m_shadowRoots.head()->type()); + if (type == ShadowRootType::V0 && m_shadowRoot) { + DCHECK_EQ(m_shadowRoot->type(), ShadowRootType::V0); Deprecation::countDeprecation(shadowHost.document(), UseCounter::ElementCreateShadowRootMultiple); } - for (ShadowRoot* root = m_shadowRoots.head(); root; root = root->olderShadowRoot()) - root->lazyReattachIfAttached(); + if (m_shadowRoot) { + // TODO(hayato): Is the order, from the youngest to the oldest, important? + for (ShadowRoot* root = &youngestShadowRoot(); root; root = root->olderShadowRoot()) + root->lazyReattachIfAttached(); + } ShadowRoot* shadowRoot = ShadowRoot::create(shadowHost.document(), type); shadowRoot->setParentOrShadowHostNode(&shadowHost); shadowRoot->setParentTreeScope(shadowHost.treeScope()); - m_shadowRoots.push(shadowRoot); + appendShadowRoot(*shadowRoot); setNeedsDistributionRecalc(); shadowRoot->insertedInto(&shadowHost); @@ -172,6 +184,19 @@ return *shadowRoot; } +void ElementShadow::appendShadowRoot(ShadowRoot& shadowRoot) +{ + if (!m_shadowRoot) { + m_shadowRoot = &shadowRoot; + return; + } + ShadowRoot& youngest = youngestShadowRoot(); + DCHECK(shadowRoot.type() == ShadowRootType::V0); + DCHECK(youngest.type() == ShadowRootType::V0); + youngest.setYoungerShadowRoot(shadowRoot); + shadowRoot.setOlderShadowRoot(youngest); +} + void ElementShadow::attach(const Node::AttachContext& context) { Node::AttachContext childrenContext(context); @@ -354,10 +379,7 @@ { visitor->trace(m_nodeToInsertionPoints); visitor->trace(m_selectFeatures); - // Shadow roots are linked with previous and next pointers which are traced. - // It is therefore enough to trace one of the shadow roots here and the - // rest will be traced from there. - visitor->trace(m_shadowRoots.head()); + visitor->trace(m_shadowRoot); } } // namespace blink
diff --git a/third_party/WebKit/Source/core/dom/shadow/ElementShadow.h b/third_party/WebKit/Source/core/dom/shadow/ElementShadow.h index 7725df6..a8aa549 100644 --- a/third_party/WebKit/Source/core/dom/shadow/ElementShadow.h +++ b/third_party/WebKit/Source/core/dom/shadow/ElementShadow.h
@@ -32,7 +32,6 @@ #include "core/dom/shadow/SelectRuleFeatureSet.h" #include "core/dom/shadow/ShadowRoot.h" #include "platform/heap/Handle.h" -#include "wtf/DoublyLinkedList.h" #include "wtf/HashMap.h" #include "wtf/Noncopyable.h" @@ -45,8 +44,8 @@ ~ElementShadow(); Element* host() const; - ShadowRoot& youngestShadowRoot() const { DCHECK(m_shadowRoots.head()); return *m_shadowRoots.head(); } - ShadowRoot* oldestShadowRoot() const { return m_shadowRoots.tail(); } + ShadowRoot& youngestShadowRoot() const; + ShadowRoot* oldestShadowRoot() const { return m_shadowRoot; } ElementShadow* containingShadow() const; ShadowRoot& addShadowRoot(Element& shadowHost, ShadowRootType); @@ -76,6 +75,8 @@ private: ElementShadow(); + void appendShadowRoot(ShadowRoot&); + void distribute(); void clearDistribution(); @@ -92,16 +93,15 @@ NodeToDestinationInsertionPoints m_nodeToInsertionPoints; SelectRuleFeatureSet m_selectFeatures; - // TODO(Oilpan): add a heap-based version of DoublyLinkedList<>. - DoublyLinkedList<ShadowRoot> m_shadowRoots; + Member<ShadowRoot> m_shadowRoot; bool m_needsDistributionRecalc; bool m_needsSelectFeatureSet; }; inline Element* ElementShadow::host() const { - DCHECK(!m_shadowRoots.isEmpty()); - return youngestShadowRoot().host(); + DCHECK(m_shadowRoot); + return m_shadowRoot->host(); } inline ShadowRoot* Node::youngestShadowRoot() const
diff --git a/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.cpp b/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.cpp index 76797f1..cb6536b 100644 --- a/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.cpp +++ b/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.cpp
@@ -43,9 +43,9 @@ namespace blink { -struct SameSizeAsShadowRoot : public DocumentFragment, public TreeScope, public DoublyLinkedListNode<ShadowRoot> { +struct SameSizeAsShadowRoot : public DocumentFragment, public TreeScope { char emptyClassFieldsDueToGCMixinMarker[1]; - Member<void*> willbeMember[5]; + Member<void*> willbeMember[3]; unsigned countersAndFlags[1]; }; @@ -54,9 +54,6 @@ ShadowRoot::ShadowRoot(Document& document, ShadowRootType type) : DocumentFragment(0, CreateShadowRoot) , TreeScope(*this, document) - , m_prev(nullptr) - , m_next(nullptr) - , m_slotAssignment(nullptr) , m_numberOfStyles(0) , m_type(static_cast<unsigned>(type)) , m_registeredWithParentShadowRoot(false) @@ -70,6 +67,20 @@ { } +ShadowRoot* ShadowRoot::youngerShadowRoot() const +{ + if (type() == ShadowRootType::V0 && m_shadowRootRareDataV0) + return m_shadowRootRareDataV0->youngerShadowRoot(); + return nullptr; +} + +ShadowRoot* ShadowRoot::olderShadowRoot() const +{ + if (type() == ShadowRootType::V0 && m_shadowRootRareDataV0) + return m_shadowRootRareDataV0->olderShadowRoot(); + return nullptr; +} + ShadowRoot* ShadowRoot::olderShadowRootForBindings() const { ShadowRoot* older = olderShadowRoot(); @@ -79,6 +90,18 @@ return older; } +void ShadowRoot::setYoungerShadowRoot(ShadowRoot& root) +{ + DCHECK_EQ(type(), ShadowRootType::V0); + ensureShadowRootRareDataV0().setYoungerShadowRoot(root); +} + +void ShadowRoot::setOlderShadowRoot(ShadowRoot& root) +{ + DCHECK_EQ(type(), ShadowRootType::V0); + ensureShadowRootRareDataV0().setOlderShadowRoot(root); +} + Node* ShadowRoot::cloneNode(bool, ExceptionState& exceptionState) { exceptionState.throwDOMException(NotSupportedError, "ShadowRoot nodes are not clonable."); @@ -186,22 +209,22 @@ --m_numberOfStyles; } -ShadowRootRareData* ShadowRoot::ensureShadowRootRareData() +ShadowRootRareData& ShadowRoot::ensureShadowRootRareData() { if (m_shadowRootRareData) - return m_shadowRootRareData.get(); + return *m_shadowRootRareData; m_shadowRootRareData = new ShadowRootRareData; - return m_shadowRootRareData.get(); + return *m_shadowRootRareData; } -ShadowRootRareDataV0* ShadowRoot::ensureShadowRootRareDataV0() +ShadowRootRareDataV0& ShadowRoot::ensureShadowRootRareDataV0() { if (m_shadowRootRareDataV0) - return m_shadowRootRareDataV0.get(); + return *m_shadowRootRareDataV0; m_shadowRootRareDataV0 = new ShadowRootRareDataV0; - return m_shadowRootRareDataV0.get(); + return *m_shadowRootRareDataV0; } bool ShadowRoot::containsShadowElements() const @@ -233,12 +256,12 @@ { if (!m_shadowRootRareDataV0 && !shadowInsertionPoint) return; - ensureShadowRootRareDataV0()->setShadowInsertionPointOfYoungerShadowRoot(shadowInsertionPoint); + ensureShadowRootRareDataV0().setShadowInsertionPointOfYoungerShadowRoot(shadowInsertionPoint); } void ShadowRoot::didAddInsertionPoint(InsertionPoint* insertionPoint) { - ensureShadowRootRareDataV0()->didAddInsertionPoint(insertionPoint); + ensureShadowRootRareDataV0().didAddInsertionPoint(insertionPoint); invalidateDescendantInsertionPoints(); } @@ -250,7 +273,7 @@ void ShadowRoot::addChildShadowRoot() { - ensureShadowRootRareData()->didAddChildShadowRoot(); + ensureShadowRootRareData().didAddChildShadowRoot(); } void ShadowRoot::removeChildShadowRoot() @@ -287,14 +310,14 @@ for (InsertionPoint& insertionPoint : Traversal<InsertionPoint>::descendantsOf(*this)) insertionPoints.append(&insertionPoint); - ensureShadowRootRareDataV0()->setDescendantInsertionPoints(insertionPoints); + ensureShadowRootRareDataV0().setDescendantInsertionPoints(insertionPoints); return m_shadowRootRareDataV0->descendantInsertionPoints(); } StyleSheetList* ShadowRoot::styleSheets() { - if (!ensureShadowRootRareData()->styleSheets()) + if (!ensureShadowRootRareData().styleSheets()) m_shadowRootRareData->setStyleSheets(StyleSheetList::create(this)); return m_shadowRootRareData->styleSheets(); @@ -302,7 +325,7 @@ void ShadowRoot::didAddSlot() { - ensureShadowRootRareData()->didAddSlot(); + ensureShadowRootRareData().didAddSlot(); invalidateDescendantSlots(); } @@ -353,8 +376,6 @@ DEFINE_TRACE(ShadowRoot) { - visitor->trace(m_prev); - visitor->trace(m_next); visitor->trace(m_shadowRootRareData); visitor->trace(m_shadowRootRareDataV0); visitor->trace(m_slotAssignment);
diff --git a/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.h b/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.h index b1d3653..9060e14c 100644 --- a/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.h +++ b/third_party/WebKit/Source/core/dom/shadow/ShadowRoot.h
@@ -33,8 +33,6 @@ #include "core/dom/Element.h" #include "core/dom/TreeScope.h" #include "core/dom/shadow/SlotAssignment.h" -#include "wtf/DoublyLinkedList.h" -#include <iosfwd> namespace blink { @@ -54,10 +52,9 @@ Closed }; -class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope, public DoublyLinkedListNode<ShadowRoot> { +class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope { DEFINE_WRAPPERTYPEINFO(); USING_GARBAGE_COLLECTED_MIXIN(ShadowRoot); - friend class WTF::DoublyLinkedListNode<ShadowRoot>; public: // FIXME: Current implementation does not work well if a shadow root is dynamically created. // So multiple shadow subtrees in several elements are prohibited. @@ -78,10 +75,13 @@ Element* host() const { return toElement(parentOrShadowHostNode()); } ElementShadow* owner() const { return host() ? host()->shadow() : 0; } - ShadowRoot* youngerShadowRoot() const { return prev(); } - + ShadowRoot* youngerShadowRoot() const; + ShadowRoot* olderShadowRoot() const; ShadowRoot* olderShadowRootForBindings() const; + void setYoungerShadowRoot(ShadowRoot&); + void setOlderShadowRoot(ShadowRoot&); + String mode() const { return (type() == ShadowRootType::V0 || type() == ShadowRootType::Open) ? "open" : "closed"; }; bool isOpenOrV0() const { return type() == ShadowRootType::V0 || type() == ShadowRootType::Open; } @@ -135,11 +135,8 @@ using TreeScope::setDocument; using TreeScope::setParentTreeScope; -public: Element* activeElement() const; - ShadowRoot* olderShadowRoot() const { return next(); } - String innerHTML() const; void setInnerHTML(const String&, ExceptionState&); @@ -158,8 +155,8 @@ void childrenChanged(const ChildrenChange&) override; - ShadowRootRareData* ensureShadowRootRareData(); - ShadowRootRareDataV0* ensureShadowRootRareDataV0(); + ShadowRootRareData& ensureShadowRootRareData(); + ShadowRootRareDataV0& ensureShadowRootRareDataV0(); void addChildShadowRoot(); void removeChildShadowRoot(); @@ -174,11 +171,8 @@ void invalidateDescendantSlots(); unsigned descendantSlotCount() const; - Member<ShadowRoot> m_prev; - Member<ShadowRoot> m_next; Member<ShadowRootRareData> m_shadowRootRareData; Member<ShadowRootRareDataV0> m_shadowRootRareDataV0; - Member<SlotAssignment> m_slotAssignment; unsigned m_numberOfStyles : 26; unsigned m_type : 2;
diff --git a/third_party/WebKit/Source/core/dom/shadow/ShadowRootRareDataV0.h b/third_party/WebKit/Source/core/dom/shadow/ShadowRootRareDataV0.h index c0f62d2..6c7e033 100644 --- a/third_party/WebKit/Source/core/dom/shadow/ShadowRootRareDataV0.h +++ b/third_party/WebKit/Source/core/dom/shadow/ShadowRootRareDataV0.h
@@ -59,13 +59,23 @@ void setDescendantInsertionPoints(HeapVector<Member<InsertionPoint>>& list) { m_descendantInsertionPoints.swap(list); } void clearDescendantInsertionPoints() { m_descendantInsertionPoints.clear(); } + void setYoungerShadowRoot(ShadowRoot& youngerShadowRoot) { m_youngerShadowRoot = &youngerShadowRoot; } + void setOlderShadowRoot(ShadowRoot& olderShadowRoot) { m_olderShadowRoot = &olderShadowRoot; } + + ShadowRoot* youngerShadowRoot() const { return m_youngerShadowRoot; } + ShadowRoot* olderShadowRoot() const { return m_olderShadowRoot; } + DEFINE_INLINE_TRACE() { + visitor->trace(m_youngerShadowRoot); + visitor->trace(m_olderShadowRoot); visitor->trace(m_shadowInsertionPointOfYoungerShadowRoot); visitor->trace(m_descendantInsertionPoints); } private: + Member<ShadowRoot> m_youngerShadowRoot; + Member<ShadowRoot> m_olderShadowRoot; Member<HTMLShadowElement> m_shadowInsertionPointOfYoungerShadowRoot; unsigned m_descendantShadowElementCount; unsigned m_descendantContentElementCount;