From 016a21c414f35e0d1af6ee2ffcc17224aab77637 Mon Sep 17 00:00:00 2001 From: Gaming4JC Date: Sat, 18 Jan 2020 13:20:59 -0500 Subject: Bug 1355769 - Avoid malloc for nsHtml5ElementName when processing a non-interned element name. HTML Regen. Tag UXP Issue #1344 --- parser/html/nsHtml5ElementName.cpp | 33 +++++++++++++-------------------- parser/html/nsHtml5ElementName.h | 26 +++++++++++++++++--------- parser/html/nsHtml5StackNode.cpp | 18 +++++++++--------- parser/html/nsHtml5Tokenizer.cpp | 23 +++++++++++++---------- parser/html/nsHtml5Tokenizer.h | 1 + parser/html/nsHtml5TreeBuilder.cpp | 32 ++++++++++++++++---------------- 6 files changed, 69 insertions(+), 64 deletions(-) (limited to 'parser') diff --git a/parser/html/nsHtml5ElementName.cpp b/parser/html/nsHtml5ElementName.cpp index b75d5db6b..6b829dfe3 100644 --- a/parser/html/nsHtml5ElementName.cpp +++ b/parser/html/nsHtml5ElementName.cpp @@ -55,9 +55,7 @@ #include "nsHtml5Portability.h" #include "nsHtml5ElementName.h" -#include "nsHtml5ReleasableElementName.h" -nsHtml5ElementName* nsHtml5ElementName::ELT_NULL_ELEMENT_NAME = nullptr; int32_t nsHtml5ElementName::getGroup() { @@ -65,9 +63,9 @@ nsHtml5ElementName::getGroup() } bool -nsHtml5ElementName::isCustom() +nsHtml5ElementName::isInterned() { - return (flags & NS_HTML5ELEMENT_NAME_CUSTOM); + return !(flags & NS_HTML5ELEMENT_NAME_NOT_INTERNED); } nsHtml5ElementName* @@ -76,12 +74,12 @@ nsHtml5ElementName::elementNameByBuffer(char16_t* buf, int32_t offset, int32_t l uint32_t hash = nsHtml5ElementName::bufToHash(buf, length); int32_t index = nsHtml5ElementName::ELEMENT_HASHES.binarySearch(hash); if (index < 0) { - return new nsHtml5ReleasableElementName(nsHtml5Portability::newLocalNameFromBuffer(buf, offset, length, interner)); + return nullptr; } else { nsHtml5ElementName* elementName = nsHtml5ElementName::ELEMENT_NAMES[index]; nsIAtom* name = elementName->name; if (!nsHtml5Portability::localEqualsBuffer(name, buf, offset, length)) { - return new nsHtml5ReleasableElementName(nsHtml5Portability::newLocalNameFromBuffer(buf, offset, length, interner)); + return nullptr; } return elementName; } @@ -97,29 +95,26 @@ nsHtml5ElementName::nsHtml5ElementName(nsIAtom* name, nsIAtom* camelCaseName, in } -nsHtml5ElementName::nsHtml5ElementName(nsIAtom* name) - : name(name), - camelCaseName(name), - flags(NS_HTML5TREE_BUILDER_OTHER | NS_HTML5ELEMENT_NAME_CUSTOM) +nsHtml5ElementName::nsHtml5ElementName() + : name(nullptr), + camelCaseName(nullptr), + flags(NS_HTML5TREE_BUILDER_OTHER | NS_HTML5ELEMENT_NAME_NOT_INTERNED) { MOZ_COUNT_CTOR(nsHtml5ElementName); } -void -nsHtml5ElementName::release() -{ -} - nsHtml5ElementName::~nsHtml5ElementName() { MOZ_COUNT_DTOR(nsHtml5ElementName); } -nsHtml5ElementName* -nsHtml5ElementName::cloneElementName(nsHtml5AtomTable* interner) +void +nsHtml5ElementName::setNameForNonInterned(nsIAtom* name) { - return this; + this->name = name; + this->camelCaseName = name; + MOZ_ASSERT(this->flags == (NS_HTML5TREE_BUILDER_OTHER | NS_HTML5ELEMENT_NAME_NOT_INTERNED)); } nsHtml5ElementName* nsHtml5ElementName::ELT_AND = nullptr; @@ -526,7 +521,6 @@ staticJArray nsHtml5ElementName::ELEMENT_HASHES = { ELEMENT_HAS void nsHtml5ElementName::initializeStatics() { - ELT_NULL_ELEMENT_NAME = new nsHtml5ElementName(nullptr); ELT_AND = new nsHtml5ElementName(nsHtml5Atoms::and_, nsHtml5Atoms::and_, NS_HTML5TREE_BUILDER_OTHER); ELT_ARG = new nsHtml5ElementName(nsHtml5Atoms::arg, nsHtml5Atoms::arg, NS_HTML5TREE_BUILDER_OTHER); ELT_ABS = new nsHtml5ElementName(nsHtml5Atoms::abs, nsHtml5Atoms::abs, NS_HTML5TREE_BUILDER_OTHER); @@ -1329,7 +1323,6 @@ nsHtml5ElementName::initializeStatics() void nsHtml5ElementName::releaseStatics() { - delete ELT_NULL_ELEMENT_NAME; delete ELT_AND; delete ELT_ARG; delete ELT_ABS; diff --git a/parser/html/nsHtml5ElementName.h b/parser/html/nsHtml5ElementName.h index 3bf2ed92b..50415225a 100644 --- a/parser/html/nsHtml5ElementName.h +++ b/parser/html/nsHtml5ElementName.h @@ -59,18 +59,28 @@ class nsHtml5Portability; class nsHtml5ElementName { - public: - static nsHtml5ElementName* ELT_NULL_ELEMENT_NAME; + private: nsIAtom* name; nsIAtom* camelCaseName; + public: int32_t flags; + inline nsIAtom* getName() + { + return name; + } + + inline nsIAtom* getCamelCaseName() + { + return camelCaseName; + } + inline int32_t getFlags() { return flags; } int32_t getGroup(); - bool isCustom(); + bool isInterned(); static nsHtml5ElementName* elementNameByBuffer(char16_t* buf, int32_t offset, int32_t length, nsHtml5AtomTable* interner); private: inline static uint32_t bufToHash(char16_t* buf, int32_t length) @@ -104,12 +114,10 @@ class nsHtml5ElementName } nsHtml5ElementName(nsIAtom* name, nsIAtom* camelCaseName, int32_t flags); - protected: - explicit nsHtml5ElementName(nsIAtom* name); public: - virtual void release(); - virtual ~nsHtml5ElementName(); - virtual nsHtml5ElementName* cloneElementName(nsHtml5AtomTable* interner); + nsHtml5ElementName(); + ~nsHtml5ElementName(); + void setNameForNonInterned(nsIAtom* name); static nsHtml5ElementName* ELT_AND; static nsHtml5ElementName* ELT_ARG; static nsHtml5ElementName* ELT_ABS; @@ -517,7 +525,7 @@ class nsHtml5ElementName }; #define NS_HTML5ELEMENT_NAME_GROUP_MASK 127 -#define NS_HTML5ELEMENT_NAME_CUSTOM (1 << 30) +#define NS_HTML5ELEMENT_NAME_NOT_INTERNED (1 << 30) #define NS_HTML5ELEMENT_NAME_SPECIAL (1 << 29) #define NS_HTML5ELEMENT_NAME_FOSTER_PARENTING (1 << 28) #define NS_HTML5ELEMENT_NAME_SCOPING (1 << 27) diff --git a/parser/html/nsHtml5StackNode.cpp b/parser/html/nsHtml5StackNode.cpp index a29fb85d4..10b0192c0 100644 --- a/parser/html/nsHtml5StackNode.cpp +++ b/parser/html/nsHtml5StackNode.cpp @@ -103,35 +103,35 @@ nsHtml5StackNode::nsHtml5StackNode(int32_t flags, int32_t ns, nsIAtom* name, nsI nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node) : flags(elementName->getFlags()), - name(elementName->name), - popName(elementName->name), + name(elementName->getName()), + popName(elementName->getName()), ns(kNameSpaceID_XHTML), node(node), attributes(nullptr), refcount(1) { MOZ_COUNT_CTOR(nsHtml5StackNode); - MOZ_ASSERT(!elementName->isCustom(), "Don't use this constructor for custom elements."); + MOZ_ASSERT(elementName->isInterned(), "Don't use this constructor for custom elements."); } nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsHtml5HtmlAttributes* attributes) : flags(elementName->getFlags()), - name(elementName->name), - popName(elementName->name), + name(elementName->getName()), + popName(elementName->getName()), ns(kNameSpaceID_XHTML), node(node), attributes(attributes), refcount(1) { MOZ_COUNT_CTOR(nsHtml5StackNode); - MOZ_ASSERT(!elementName->isCustom(), "Don't use this constructor for custom elements."); + MOZ_ASSERT(elementName->isInterned(), "Don't use this constructor for custom elements."); } nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName) : flags(elementName->getFlags()), - name(elementName->name), + name(elementName->getName()), popName(popName), ns(kNameSpaceID_XHTML), node(node), @@ -144,7 +144,7 @@ nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHa nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIAtom* popName, nsIContentHandle* node) : flags(prepareSvgFlags(elementName->getFlags())), - name(elementName->name), + name(elementName->getName()), popName(popName), ns(kNameSpaceID_SVG), node(node), @@ -157,7 +157,7 @@ nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIAtom* pop nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName, bool markAsIntegrationPoint) : flags(prepareMathFlags(elementName->getFlags(), markAsIntegrationPoint)), - name(elementName->name), + name(elementName->getName()), popName(popName), ns(kNameSpaceID_MathML), node(node), diff --git a/parser/html/nsHtml5Tokenizer.cpp b/parser/html/nsHtml5Tokenizer.cpp index 73c6d986f..aa5b3df28 100644 --- a/parser/html/nsHtml5Tokenizer.cpp +++ b/parser/html/nsHtml5Tokenizer.cpp @@ -97,6 +97,7 @@ nsHtml5Tokenizer::nsHtml5Tokenizer(nsHtml5TreeBuilder* tokenHandler, bool viewin bmpChar(jArray::newJArray(1)), astralChar(jArray::newJArray(2)), tagName(nullptr), + nonInternedTagName(new nsHtml5ElementName()), attributeName(nullptr), doctypeName(nullptr), publicIdentifier(nullptr), @@ -279,6 +280,10 @@ void nsHtml5Tokenizer::strBufToElementNameString() { tagName = nsHtml5ElementName::elementNameByBuffer(strBuf, 0, strBufLen, interner); + if (!tagName) { + nonInternedTagName->setNameForNonInterned(nsHtml5Portability::newLocalNameFromBuffer(strBuf, 0, strBufLen, interner)); + tagName = nonInternedTagName; + } clearStrBufAfterUse(); } @@ -307,7 +312,6 @@ nsHtml5Tokenizer::emitCurrentTagToken(bool selfClosing, int32_t pos) tokenHandler->startTag(tagName, attrs, selfClosing); } } - tagName->release(); tagName = nullptr; if (newAttributesEachTime) { attributes = nullptr; @@ -3935,10 +3939,8 @@ nsHtml5Tokenizer::end() publicIdentifier.Release(); publicIdentifier = nullptr; } - if (tagName) { - tagName->release(); - tagName = nullptr; - } + tagName = nullptr; + nonInternedTagName->setNameForNonInterned(nullptr); if (attributeName) { attributeName->release(); attributeName = nullptr; @@ -3983,7 +3985,6 @@ nsHtml5Tokenizer::resetToDataState() shouldSuspend = false; initDoctypeFields(); if (tagName) { - tagName->release(); tagName = nullptr; } if (attributeName) { @@ -4043,13 +4044,13 @@ nsHtml5Tokenizer::loadState(nsHtml5Tokenizer* other) } else { publicIdentifier = nsHtml5Portability::newStringFromString(other->publicIdentifier); } - if (tagName) { - tagName->release(); - } if (!other->tagName) { tagName = nullptr; + } else if (other->tagName->isInterned()) { + tagName = other->tagName; } else { - tagName = other->tagName->cloneElementName(interner); + nonInternedTagName->setNameForNonInterned(nsHtml5Portability::newLocalFromLocal(other->tagName->getName(), interner)); + tagName = nonInternedTagName; } if (attributeName) { attributeName->release(); @@ -4087,6 +4088,8 @@ nsHtml5Tokenizer::setEncodingDeclarationHandler(nsHtml5StreamParser* encodingDec nsHtml5Tokenizer::~nsHtml5Tokenizer() { MOZ_COUNT_DTOR(nsHtml5Tokenizer); + delete nonInternedTagName; + nonInternedTagName = nullptr; delete attributes; attributes = nullptr; } diff --git a/parser/html/nsHtml5Tokenizer.h b/parser/html/nsHtml5Tokenizer.h index 101cd1618..121d355de 100644 --- a/parser/html/nsHtml5Tokenizer.h +++ b/parser/html/nsHtml5Tokenizer.h @@ -124,6 +124,7 @@ class nsHtml5Tokenizer bool endTag; private: nsHtml5ElementName* tagName; + nsHtml5ElementName* nonInternedTagName; protected: nsHtml5AttributeName* attributeName; private: diff --git a/parser/html/nsHtml5TreeBuilder.cpp b/parser/html/nsHtml5TreeBuilder.cpp index cea78839c..23e874d96 100644 --- a/parser/html/nsHtml5TreeBuilder.cpp +++ b/parser/html/nsHtml5TreeBuilder.cpp @@ -104,7 +104,7 @@ nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self) if (nsHtml5Atoms::title == contextName || nsHtml5Atoms::desc == contextName || nsHtml5Atoms::foreignObject == contextName) { elementName = nsHtml5ElementName::ELT_FOREIGNOBJECT; } - nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elementName->camelCaseName, elt); + nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elementName->getCamelCaseName(), elt); currentPtr++; stack[currentPtr] = node; tokenizer->setState(NS_HTML5TOKENIZER_DATA); @@ -116,7 +116,7 @@ nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self) } else if (nsHtml5Atoms::annotation_xml == contextName) { elementName = nsHtml5ElementName::ELT_ANNOTATION_XML; } - nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, elementName->name, false); + nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, elementName->getName(), false); currentPtr++; stack[currentPtr] = node; tokenizer->setState(NS_HTML5TOKENIZER_DATA); @@ -609,7 +609,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu needToDropLF = false; starttagloop: for (; ; ) { int32_t group = elementName->getGroup(); - nsIAtom* name = elementName->name; + nsIAtom* name = elementName->getName(); if (isInForeign()) { nsHtml5StackNode* currentNode = stack[currentPtr]; int32_t currNs = currentNode->ns; @@ -1143,7 +1143,7 @@ nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttribu case NS_HTML5TREE_BUILDER_B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U: case NS_HTML5TREE_BUILDER_FONT: { reconstructTheActiveFormattingElements(); - maybeForgetEarlierDuplicateFormattingElement(elementName->name, attributes); + maybeForgetEarlierDuplicateFormattingElement(elementName->getName(), attributes); appendToCurrentNodeAndPushFormattingElementMayFoster(elementName, attributes); attributes = nullptr; NS_HTML5_BREAK(starttagloop); @@ -2220,7 +2220,7 @@ nsHtml5TreeBuilder::endTag(nsHtml5ElementName* elementName) needToDropLF = false; int32_t eltPos; int32_t group = elementName->getGroup(); - nsIAtom* name = elementName->name; + nsIAtom* name = elementName->getName(); for (; ; ) { if (isInForeign()) { if (stack[currentPtr]->name != name) { @@ -3988,9 +3988,9 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(nsHtml5 nsHtml5StackNode* current = stack[currentPtr]; if (current->isFosterParenting()) { - elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, elementName->name, attributes); + elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, elementName->getName(), attributes); } else { - elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, current->node); + elt = createElement(kNameSpaceID_XHTML, elementName->getName(), attributes, current->node); appendElement(elt, current->node); } nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, clone); @@ -4003,7 +4003,7 @@ void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { nsIContentHandle* currentNode = stack[currentPtr]->node; - nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, currentNode); + nsIContentHandle* elt = createElement(kNameSpaceID_XHTML, elementName->getName(), attributes, currentNode); appendElement(elt, currentNode); if (nsHtml5ElementName::ELT_TEMPLATE == elementName) { elt = getDocumentFragmentForTemplate(elt); @@ -4015,7 +4015,7 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(nsHtml5ElementName* elemen void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { - nsIAtom* popName = elementName->name; + nsIAtom* popName = elementName->getName(); nsIContentHandle* elt; nsHtml5StackNode* current = stack[currentPtr]; if (current->isFosterParenting()) { @@ -4032,7 +4032,7 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementNam void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { - nsIAtom* popName = elementName->name; + nsIAtom* popName = elementName->getName(); bool markAsHtmlIntegrationPoint = false; if (nsHtml5ElementName::ELT_ANNOTATION_XML == elementName && annotationXmlEncodingPermitsHtml(attributes)) { markAsHtmlIntegrationPoint = true; @@ -4063,7 +4063,7 @@ nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml(nsHtml5HtmlAttributes* attr void nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { - nsIAtom* popName = elementName->camelCaseName; + nsIAtom* popName = elementName->getCamelCaseName(); nsIContentHandle* elt; nsHtml5StackNode* current = stack[currentPtr]; if (current->isFosterParenting()) { @@ -4085,9 +4085,9 @@ nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementNam nsHtml5StackNode* current = stack[currentPtr]; if (current->isFosterParenting()) { - elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, elementName->name, attributes, formOwner); + elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, elementName->getName(), attributes, formOwner); } else { - elt = createElement(kNameSpaceID_XHTML, elementName->name, attributes, formOwner, current->node); + elt = createElement(kNameSpaceID_XHTML, elementName->getName(), attributes, formOwner, current->node); appendElement(elt, current->node); } nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt); @@ -4114,7 +4114,7 @@ nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsIAtom* name, nsHtml5Ht void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { - nsIAtom* popName = elementName->name; + nsIAtom* popName = elementName->getName(); nsIContentHandle* elt; nsHtml5StackNode* current = stack[currentPtr]; if (current->isFosterParenting()) { @@ -4131,7 +4131,7 @@ nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsHtml5ElementName* elem void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { - nsIAtom* popName = elementName->camelCaseName; + nsIAtom* popName = elementName->getCamelCaseName(); nsIContentHandle* elt; nsHtml5StackNode* current = stack[currentPtr]; if (current->isFosterParenting()) { @@ -4148,7 +4148,7 @@ nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterSVG(nsHtml5ElementName* e void nsHtml5TreeBuilder::appendVoidElementToCurrentMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes) { - nsIAtom* popName = elementName->name; + nsIAtom* popName = elementName->getName(); nsIContentHandle* elt; nsHtml5StackNode* current = stack[currentPtr]; if (current->isFosterParenting()) { -- cgit v1.2.3