Skip to content

Commit

Permalink
Inline NodeType in C++ side
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=266829

Reviewed by Chris Dumez.

This PR inlines Node::nodeType in Node.h by using the remaining bits in m_typeFlags.
To do this optimization, we take the advantage of the fact nodeType is now fast to obtain,
and replace two of the existing TypeFlags (IsDocumentFragment and IsText) in favor of
checking nodeType instead.

* Source/WebCore/dom/Attr.cpp:
(WebCore::Attr::Attr):
* Source/WebCore/dom/Attr.h:
* Source/WebCore/dom/CDATASection.cpp:
(WebCore::CDATASection::CDATASection):
(WebCore::CDATASection::nodeType const): Deleted.
* Source/WebCore/dom/CDATASection.h:
* Source/WebCore/dom/CharacterData.h:
(WebCore::CharacterData::CharacterData):
* Source/WebCore/dom/Comment.cpp:
(WebCore::Comment::Comment):
(WebCore::Comment::nodeType const): Deleted.
* Source/WebCore/dom/Comment.h:
* Source/WebCore/dom/ContainerNode.h:
(WebCore::ContainerNode::ContainerNode):
* Source/WebCore/dom/Document.cpp:
(WebCore::Document::Document):
(WebCore::Document::nodeType const): Deleted.
* Source/WebCore/dom/Document.h:
* Source/WebCore/dom/DocumentFragment.cpp:
(WebCore::DocumentFragment::DocumentFragment):
(WebCore::DocumentFragment::create):
(WebCore::DocumentFragment::createForInnerOuterHTML):
(WebCore::DocumentFragment::nodeType const): Deleted.
* Source/WebCore/dom/DocumentFragment.h:
* Source/WebCore/dom/DocumentType.cpp:
(WebCore::DocumentType::DocumentType):
(WebCore::DocumentType::nodeType const): Deleted.
* Source/WebCore/dom/DocumentType.h:
* Source/WebCore/dom/Element.cpp:
(WebCore::Element::Element):
(WebCore::Element::nodeType const): Deleted.
* Source/WebCore/dom/Element.h:
* Source/WebCore/dom/Node.cpp:
(WebCore::Node::Node):
* Source/WebCore/dom/Node.h:
(WebCore::Node::nodeType const):
(WebCore::Node::isDocumentNode const):
(WebCore::Node::isTreeScope const):
(WebCore::Node::isDocumentFragment const):
(WebCore::Node::typeFlagsMemoryOffset):
(WebCore::Node::constructBitFieldsFromNodeTypeAndFlags):
(WebCore::Node::nodeTypeFromBitFields):
(WebCore::Node::hasTypeFlag const):
* Source/WebCore/dom/ProcessingInstruction.cpp:
(WebCore::ProcessingInstruction::ProcessingInstruction):
(WebCore::ProcessingInstruction::nodeType const): Deleted.
* Source/WebCore/dom/ProcessingInstruction.h:
* Source/WebCore/dom/TemplateContentDocumentFragment.h:
* Source/WebCore/dom/Text.cpp:
(WebCore::Text::create):
(WebCore::Text::createEditingText):
(WebCore::Text::nodeType const): Deleted.
* Source/WebCore/dom/Text.h:
(WebCore::Text::Text):

Canonical link: https://commits.webkit.org/272482@main
  • Loading branch information
rniwa committed Dec 23, 2023
1 parent 97b4d91 commit 8718235
Show file tree
Hide file tree
Showing 23 changed files with 45 additions and 92 deletions.
4 changes: 2 additions & 2 deletions Source/WebCore/dom/Attr.cpp
Expand Up @@ -44,14 +44,14 @@ WTF_MAKE_ISO_ALLOCATED_IMPL(Attr);
using namespace HTMLNames;

Attr::Attr(Element& element, const QualifiedName& name)
: Node(element.document(), CreateAttr)
: Node(element.document(), ATTRIBUTE_NODE, CreateAttr)
, m_element(element)
, m_name(name)
{
}

Attr::Attr(Document& document, const QualifiedName& name, const AtomString& standaloneValue)
: Node(document, CreateAttr)
: Node(document, ATTRIBUTE_NODE, CreateAttr)
, m_name(name)
, m_standaloneValue(standaloneValue)
{
Expand Down
1 change: 0 additions & 1 deletion Source/WebCore/dom/Attr.h
Expand Up @@ -63,7 +63,6 @@ class Attr final : public Node {
Attr(Document&, const QualifiedName&, const AtomString& value);

String nodeName() const final { return name(); }
NodeType nodeType() const final { return ATTRIBUTE_NODE; }

String nodeValue() const final { return value(); }
void setNodeValue(const String&) final;
Expand Down
7 changes: 1 addition & 6 deletions Source/WebCore/dom/CDATASection.cpp
Expand Up @@ -31,7 +31,7 @@ namespace WebCore {
WTF_MAKE_ISO_ALLOCATED_IMPL(CDATASection);

inline CDATASection::CDATASection(Document& document, String&& data)
: Text(document, WTFMove(data), CreateText)
: Text(document, WTFMove(data), CDATA_SECTION_NODE, CreateText)
{
}

Expand All @@ -45,11 +45,6 @@ String CDATASection::nodeName() const
return "#cdata-section"_s;
}

Node::NodeType CDATASection::nodeType() const
{
return CDATA_SECTION_NODE;
}

Ref<Node> CDATASection::cloneNodeInternal(Document& targetDocument, CloningOperation)
{
return create(targetDocument, String { data() });
Expand Down
1 change: 0 additions & 1 deletion Source/WebCore/dom/CDATASection.h
Expand Up @@ -35,7 +35,6 @@ class CDATASection final : public Text {
CDATASection(Document&, String&&);

String nodeName() const override;
NodeType nodeType() const override;
Ref<Node> cloneNodeInternal(Document&, CloningOperation) override;
Ref<Text> virtualCreate(String&&) override;
};
Expand Down
6 changes: 3 additions & 3 deletions Source/WebCore/dom/CharacterData.h
Expand Up @@ -44,11 +44,11 @@ class CharacterData : public Node {
void parserAppendData(StringView);

protected:
CharacterData(Document& document, String&& text, OptionSet<TypeFlag> type = CreateCharacterData)
: Node(document, type)
CharacterData(Document& document, String&& text, NodeType type, OptionSet<TypeFlag> typeFlags = CreateCharacterData)
: Node(document, type, typeFlags)
, m_data(!text.isNull() ? WTFMove(text) : emptyString())
{
ASSERT(type == CreateCharacterData || type == CreateText || type == CreateEditingText);
ASSERT(typeFlags == CreateCharacterData || typeFlags == CreateText || typeFlags == CreateEditingText);
}

~CharacterData();
Expand Down
7 changes: 1 addition & 6 deletions Source/WebCore/dom/Comment.cpp
Expand Up @@ -30,7 +30,7 @@ namespace WebCore {
WTF_MAKE_ISO_ALLOCATED_IMPL(Comment);

inline Comment::Comment(Document& document, String&& text)
: CharacterData(document, WTFMove(text))
: CharacterData(document, WTFMove(text), COMMENT_NODE)
{
}

Expand All @@ -44,11 +44,6 @@ String Comment::nodeName() const
return "#comment"_s;
}

Node::NodeType Comment::nodeType() const
{
return COMMENT_NODE;
}

Ref<Node> Comment::cloneNodeInternal(Document& targetDocument, CloningOperation)
{
return create(targetDocument, String { data() });
Expand Down
1 change: 0 additions & 1 deletion Source/WebCore/dom/Comment.h
Expand Up @@ -35,7 +35,6 @@ class Comment final : public CharacterData {
Comment(Document&, String&&);

String nodeName() const override;
NodeType nodeType() const override;
Ref<Node> cloneNodeInternal(Document&, CloningOperation) override;
};

Expand Down
7 changes: 4 additions & 3 deletions Source/WebCore/dom/ContainerNode.h
Expand Up @@ -144,7 +144,7 @@ class ContainerNode : public Node {
ExceptionOr<void> ensurePreInsertionValidity(Node& newChild, Node* refChild);

protected:
explicit ContainerNode(Document&, OptionSet<TypeFlag> = CreateContainer);
explicit ContainerNode(Document&, NodeType, OptionSet<TypeFlag> = CreateContainer);

friend void removeDetachedChildrenInContainer(ContainerNode&);

Expand Down Expand Up @@ -175,9 +175,10 @@ class ContainerNode : public Node {
Node* m_lastChild { nullptr };
};

inline ContainerNode::ContainerNode(Document& document, OptionSet<TypeFlag> type)
: Node(document, type)
inline ContainerNode::ContainerNode(Document& document, NodeType type, OptionSet<TypeFlag> typeFlags)
: Node(document, type, typeFlags)
{
ASSERT(typeFlags.contains(TypeFlag::IsContainerNode));
}

inline unsigned Node::countChildNodes() const
Expand Down
7 changes: 1 addition & 6 deletions Source/WebCore/dom/Document.cpp
Expand Up @@ -592,7 +592,7 @@ static Ref<CachedResourceLoader> createCachedResourceLoader(LocalFrame* frame)
}

Document::Document(LocalFrame* frame, const Settings& settings, const URL& url, DocumentClasses documentClasses, OptionSet<ConstructionFlag> constructionFlags, ScriptExecutionContextIdentifier identifier)
: ContainerNode(*this, CreateDocument)
: ContainerNode(*this, DOCUMENT_NODE)
, TreeScope(*this)
, ScriptExecutionContext(identifier)
, FrameDestructionObserver(frame)
Expand Down Expand Up @@ -2078,11 +2078,6 @@ String Document::nodeName() const
return "#document"_s;
}

Node::NodeType Document::nodeType() const
{
return DOCUMENT_NODE;
}

WakeLockManager& Document::wakeLockManager()
{
if (!m_wakeLockManager)
Expand Down
1 change: 0 additions & 1 deletion Source/WebCore/dom/Document.h
Expand Up @@ -1912,7 +1912,6 @@ class Document
void childrenChanged(const ChildChange&) final;

String nodeName() const final;
NodeType nodeType() const final;
bool childTypeAllowed(NodeType) const final;
Ref<Node> cloneNodeInternal(Document&, CloningOperation) final;
void cloneDataFromDocument(const Document&);
Expand Down
11 changes: 3 additions & 8 deletions Source/WebCore/dom/DocumentFragment.cpp
Expand Up @@ -38,30 +38,25 @@ namespace WebCore {
WTF_MAKE_ISO_ALLOCATED_IMPL(DocumentFragment);

DocumentFragment::DocumentFragment(Document& document, OptionSet<TypeFlag> constructionType)
: ContainerNode(document, constructionType)
: ContainerNode(document, DOCUMENT_FRAGMENT_NODE, constructionType)
{
}

Ref<DocumentFragment> DocumentFragment::create(Document& document)
{
return adoptRef(*new DocumentFragment(document, Node::CreateDocumentFragment));
return adoptRef(*new DocumentFragment(document));
}

Ref<DocumentFragment> DocumentFragment::createForInnerOuterHTML(Document& document)
{
return adoptRef(*new DocumentFragment(document, Node::CreateDocumentFragment | TypeFlag::IsDocumentFragmentForInnerOuterHTML));
return adoptRef(*new DocumentFragment(document, CreateContainer | TypeFlag::IsDocumentFragmentForInnerOuterHTML));
}

String DocumentFragment::nodeName() const
{
return "#document-fragment"_s;
}

Node::NodeType DocumentFragment::nodeType() const
{
return DOCUMENT_FRAGMENT_NODE;
}

bool DocumentFragment::childTypeAllowed(NodeType type) const
{
switch (type) {
Expand Down
1 change: 0 additions & 1 deletion Source/WebCore/dom/DocumentFragment.h
Expand Up @@ -48,7 +48,6 @@ class DocumentFragment : public ContainerNode {
String nodeName() const final;

private:
NodeType nodeType() const final;
Ref<Node> cloneNodeInternal(Document&, CloningOperation) override;
bool childTypeAllowed(NodeType) const override;
};
Expand Down
7 changes: 1 addition & 6 deletions Source/WebCore/dom/DocumentType.cpp
Expand Up @@ -33,7 +33,7 @@ namespace WebCore {
WTF_MAKE_ISO_ALLOCATED_IMPL(DocumentType);

DocumentType::DocumentType(Document& document, const String& name, const String& publicId, const String& systemId)
: Node(document, CreateDocumentType)
: Node(document, DOCUMENT_TYPE_NODE, CreateDocumentType)
, m_name(name)
, m_publicId(publicId.isNull() ? emptyString() : publicId)
, m_systemId(systemId.isNull() ? emptyString() : systemId)
Expand All @@ -45,11 +45,6 @@ String DocumentType::nodeName() const
return name();
}

Node::NodeType DocumentType::nodeType() const
{
return DOCUMENT_TYPE_NODE;
}

Ref<Node> DocumentType::cloneNodeInternal(Document& documentTarget, CloningOperation)
{
return create(documentTarget, m_name, m_publicId, m_systemId);
Expand Down
1 change: 0 additions & 1 deletion Source/WebCore/dom/DocumentType.h
Expand Up @@ -45,7 +45,6 @@ class DocumentType final : public Node {
DocumentType(Document&, const String& name, const String& publicId, const String& systemId);

String nodeName() const override;
NodeType nodeType() const override;
Ref<Node> cloneNodeInternal(Document&, CloningOperation) override;

void parentOrShadowHostNode() const = delete; // Call parentNode() instead.
Expand Down
7 changes: 1 addition & 6 deletions Source/WebCore/dom/Element.cpp
Expand Up @@ -246,7 +246,7 @@ Ref<Element> Element::create(const QualifiedName& tagName, Document& document)
}

Element::Element(const QualifiedName& tagName, Document& document, OptionSet<TypeFlag> type)
: ContainerNode(document, type)
: ContainerNode(document, ELEMENT_NODE, type)
, m_tagName(tagName)
{
}
Expand Down Expand Up @@ -667,11 +667,6 @@ NamedNodeMap& Element::attributes() const
return *rareData.attributeMap();
}

Node::NodeType Element::nodeType() const
{
return ELEMENT_NODE;
}

bool Element::hasAttribute(const QualifiedName& name) const
{
return hasAttributeNS(name.namespaceURI(), name.localName());
Expand Down
1 change: 0 additions & 1 deletion Source/WebCore/dom/Element.h
Expand Up @@ -834,7 +834,6 @@ class Element : public ContainerNode {

void scrollByUnits(int units, ScrollGranularity);

NodeType nodeType() const final;
bool childTypeAllowed(NodeType) const final;

void notifyAttributeChanged(const QualifiedName&, const AtomString& oldValue, const AtomString& newValue, AttributeModificationReason = AttributeModificationReason::Directly);
Expand Down
5 changes: 3 additions & 2 deletions Source/WebCore/dom/Node.cpp
Expand Up @@ -390,11 +390,12 @@ inline void NodeRareData::operator delete(NodeRareData* nodeRareData, std::destr
destroyAndFree(*nodeRareData);
}

Node::Node(Document& document, OptionSet<TypeFlag> type)
Node::Node(Document& document, NodeType type, OptionSet<TypeFlag> flags)
: EventTarget(ConstructNode)
, m_typeFlags(type)
, m_typeBitFields(constructBitFieldsFromNodeTypeAndFlags(type, flags))
, m_treeScope((isDocumentNode() || isShadowRoot()) ? nullptr : &document)
{
ASSERT(nodeType() == type);
ASSERT(isMainThread());

// Allow code to ref the Document while it is being constructed to make our life easier.
Expand Down
38 changes: 19 additions & 19 deletions Source/WebCore/dom/Node.h
Expand Up @@ -134,7 +134,7 @@ class Node : public EventTarget, public CanMakeCheckedPtr {
virtual String nodeName() const = 0;
virtual String nodeValue() const;
virtual void setNodeValue(const String&);
virtual NodeType nodeType() const = 0;
NodeType nodeType() const { return nodeTypeFromBitFields(m_typeBitFields); }
virtual size_t approximateMemoryCost() const { return sizeof(*this); }
ContainerNode* parentNode() const;
inline RefPtr<ContainerNode> protectedParentNode() const; // Defined in ContainerNode.h.
Expand Down Expand Up @@ -238,9 +238,9 @@ class Node : public EventTarget, public CanMakeCheckedPtr {
virtual bool isFrameOwnerElement() const { return false; }
virtual bool isPluginElement() const { return false; }

bool isDocumentNode() const { return hasTypeFlag(TypeFlag::IsDocumentNode); }
bool isTreeScope() const { return hasTypeFlag(TypeFlag::IsDocumentNode) || hasTypeFlag(TypeFlag::IsShadowRoot); }
bool isDocumentFragment() const { return hasTypeFlag(TypeFlag::IsDocumentFragment); }
bool isDocumentNode() const { return nodeType() == DOCUMENT_NODE; }
bool isTreeScope() const { return isDocumentNode() || hasTypeFlag(TypeFlag::IsShadowRoot); }
bool isDocumentFragment() const { return nodeType() == DOCUMENT_FRAGMENT_NODE; }
bool isShadowRoot() const { return hasTypeFlag(TypeFlag::IsShadowRoot); }
bool isUserAgentShadowRoot() const; // Defined in ShadowRoot.h

Expand Down Expand Up @@ -558,7 +558,7 @@ class Node : public EventTarget, public CanMakeCheckedPtr {
void updateAncestorConnectedSubframeCountForInsertion() const;

#if ENABLE(JIT)
static ptrdiff_t typeFlagsMemoryOffset() { return OBJECT_OFFSETOF(Node, m_typeFlags); }
static ptrdiff_t typeFlagsMemoryOffset() { return OBJECT_OFFSETOF(Node, m_typeBitFields); }
static ptrdiff_t stateFlagsMemoryOffset() { return OBJECT_OFFSETOF(Node, m_stateFlags); }
static ptrdiff_t rareDataMemoryOffset() { return OBJECT_OFFSETOF(Node, m_rareDataWithBitfields); }
#if CPU(ADDRESS64)
Expand All @@ -584,14 +584,18 @@ class Node : public EventTarget, public CanMakeCheckedPtr {
IsHTMLElement = 1 << 4,
IsSVGElement = 1 << 5,
IsMathMLElement = 1 << 6,
IsDocumentNode = 1 << 7,
IsDocumentFragment = 1 << 8,
IsShadowRoot = 1 << 9,
IsUnknownElement = 1 << 10,
IsDocumentFragmentForInnerOuterHTML = 1 << 11,
IsEditingText = 1 << 12,
HasCustomStyleResolveCallbacks = 1 << 13,
IsShadowRoot = 1 << 7,
IsUnknownElement = 1 << 8,
IsDocumentFragmentForInnerOuterHTML = 1 << 9,
IsEditingText = 1 << 10,
HasCustomStyleResolveCallbacks = 1 << 11,
};
static constexpr auto typeFlagBitCount = 12;

static uint16_t constructBitFieldsFromNodeTypeAndFlags(NodeType type, OptionSet<TypeFlag> flags) { return (type << typeFlagBitCount) | flags.toRaw(); }
static NodeType nodeTypeFromBitFields(uint16_t bitFields) { return static_cast<NodeType>((bitFields >> typeFlagBitCount) & 0xf); }
// Don't bother masking with (1 << typeFlagBitCount) - 1 since OptionSet tolerates the upper 4-bits being used for other purposes.
bool hasTypeFlag(TypeFlag flag) const { return OptionSet<TypeFlag>::fromRaw(m_typeBitFields).contains(flag); }

enum class StateFlag : uint16_t {
IsLink = 1 << 0,
Expand Down Expand Up @@ -630,8 +634,6 @@ class Node : public EventTarget, public CanMakeCheckedPtr {
uint16_t effectiveTextDirection : 1;
};

bool hasTypeFlag(TypeFlag flag) const { return m_typeFlags.contains(flag); }

bool hasStateFlag(StateFlag flag) const { return m_stateFlags.contains(flag); }
void setStateFlag(StateFlag flag, bool value = true) const { m_stateFlags.set(flag, value); }
void clearStateFlag(StateFlag flag) const { setStateFlag(flag, false); }
Expand All @@ -657,14 +659,12 @@ class Node : public EventTarget, public CanMakeCheckedPtr {
static constexpr auto CreateContainer = DefaultTypeFlags | TypeFlag::IsContainerNode;
static constexpr auto CreateElement = CreateContainer | TypeFlag::IsElement;
static constexpr auto CreatePseudoElement = CreateElement | TypeFlag::HasCustomStyleResolveCallbacks;
static constexpr auto CreateDocumentFragment = CreateContainer | TypeFlag::IsDocumentFragment;
static constexpr auto CreateShadowRoot = CreateDocumentFragment | TypeFlag::IsShadowRoot;
static constexpr auto CreateShadowRoot = CreateContainer | TypeFlag::IsShadowRoot;
static constexpr auto CreateHTMLElement = CreateElement | TypeFlag::IsHTMLElement;
static constexpr auto CreateSVGElement = CreateElement | TypeFlag::IsSVGElement | TypeFlag::HasCustomStyleResolveCallbacks;
static constexpr auto CreateMathMLElement = CreateElement | TypeFlag::IsMathMLElement;
static constexpr auto CreateDocument = CreateContainer | TypeFlag::IsDocumentNode;
static constexpr auto CreateEditingText = CreateText | TypeFlag::IsEditingText;
Node(Document&, OptionSet<TypeFlag>);
Node(Document&, NodeType, OptionSet<TypeFlag>);

static constexpr uint32_t s_refCountIncrement = 2;
static constexpr uint32_t s_refCountMask = ~static_cast<uint32_t>(1);
Expand Down Expand Up @@ -757,7 +757,7 @@ class Node : public EventTarget, public CanMakeCheckedPtr {
WEBCORE_EXPORT void notifyInspectorOfRendererChange();

mutable uint32_t m_refCountAndParentBit { s_refCountIncrement };
const OptionSet<TypeFlag> m_typeFlags;
const uint16_t m_typeBitFields;
mutable OptionSet<StateFlag> m_stateFlags;

CheckedPtr<ContainerNode> m_parentNode;
Expand Down
7 changes: 1 addition & 6 deletions Source/WebCore/dom/ProcessingInstruction.cpp
Expand Up @@ -45,7 +45,7 @@ namespace WebCore {
WTF_MAKE_ISO_ALLOCATED_IMPL(ProcessingInstruction);

inline ProcessingInstruction::ProcessingInstruction(Document& document, String&& target, String&& data)
: CharacterData(document, WTFMove(data))
: CharacterData(document, WTFMove(data), PROCESSING_INSTRUCTION_NODE)
, m_target(WTFMove(target))
{
}
Expand All @@ -72,11 +72,6 @@ String ProcessingInstruction::nodeName() const
return m_target;
}

Node::NodeType ProcessingInstruction::nodeType() const
{
return PROCESSING_INSTRUCTION_NODE;
}

Ref<Node> ProcessingInstruction::cloneNodeInternal(Document& targetDocument, CloningOperation)
{
// FIXME: Is it a problem that this does not copy m_localHref?
Expand Down
1 change: 0 additions & 1 deletion Source/WebCore/dom/ProcessingInstruction.h
Expand Up @@ -61,7 +61,6 @@ class ProcessingInstruction final : public CharacterData, private CachedStyleShe
ProcessingInstruction(Document&, String&& target, String&& data);

String nodeName() const override;
NodeType nodeType() const override;
Ref<Node> cloneNodeInternal(Document&, CloningOperation) override;

InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode&) override;
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/dom/TemplateContentDocumentFragment.h
Expand Up @@ -45,7 +45,7 @@ class TemplateContentDocumentFragment final : public DocumentFragment {

private:
TemplateContentDocumentFragment(Document& document, const Element& host)
: DocumentFragment(document, CreateDocumentFragment)
: DocumentFragment(document)
, m_host(host)
{
}
Expand Down

0 comments on commit 8718235

Please sign in to comment.