Bug 1355769 - Avoid malloc for nsHtml5ElementName when processing a non-interned element name. r=wchen

MozReview-Commit-ID: 4In5wo0flOB

--HG--
extra : rebase_source : 912c5be12ab9ef96bacdf4ef84905f7056addecb
This commit is contained in:
Henri Sivonen 2017-04-12 13:21:03 +03:00
parent c4783f92b9
commit 8de02e50f5
14 changed files with 317 additions and 320 deletions

View File

@ -28,7 +28,6 @@ import nu.validator.htmlparser.annotation.Inline;
import nu.validator.htmlparser.annotation.Local;
import nu.validator.htmlparser.annotation.NoLength;
import nu.validator.htmlparser.annotation.Unsigned;
import nu.validator.htmlparser.annotation.Virtual;
import nu.validator.htmlparser.common.Interner;
public final class ElementName
@ -45,7 +44,7 @@ public final class ElementName
* Indicates that the element is not a pre-interned element. Forbidden
* on preinterned elements.
*/
public static final int CUSTOM = (1 << 30);
public static final int NOT_INTERNED = (1 << 30);
/**
* Indicates that the element is in the "special" category. This bit
@ -85,17 +84,23 @@ public final class ElementName
*/
public static final int OPTIONAL_END_TAG = (1 << 23);
public static final ElementName NULL_ELEMENT_NAME = new ElementName(null);
private @Local String name;
public final @Local String name;
public final @Local String camelCaseName;
private @Local String camelCaseName;
/**
* The lowest 7 bits are the dispatch group. The high bits are flags.
*/
public final int flags;
@Inline public @Local String getName() {
return name;
}
@Inline public @Local String getCamelCaseName() {
return camelCaseName;
}
@Inline public int getFlags() {
return flags;
}
@ -104,21 +109,20 @@ public final class ElementName
return flags & GROUP_MASK;
}
public boolean isCustom() {
return (flags & CUSTOM) != 0;
public boolean isInterned() {
return (flags & NOT_INTERNED) == 0;
}
static ElementName elementNameByBuffer(@NoLength char[] buf, int offset, int length, Interner interner) {
@Unsigned int hash = ElementName.bufToHash(buf, length);
int index = Arrays.binarySearch(ElementName.ELEMENT_HASHES, hash);
if (index < 0) {
return new ElementName(Portability.newLocalNameFromBuffer(buf, offset, length, interner));
return null;
} else {
ElementName elementName = ElementName.ELEMENT_NAMES[index];
@Local String name = elementName.name;
if (!Portability.localEqualsBuffer(name, buf, offset, length)) {
return new ElementName(Portability.newLocalNameFromBuffer(buf,
offset, length, interner));
return null;
}
return elementName;
}
@ -168,23 +172,22 @@ public final class ElementName
this.flags = flags;
}
protected ElementName(@Local String name) {
public ElementName() {
this.name = null;
this.camelCaseName = null;
this.flags = TreeBuilder.OTHER | NOT_INTERNED;
}
public void destructor() {
// The translator adds refcount debug code here.
}
public void setNameForNonInterned(@Local String name) {
// No need to worry about refcounting the local name, because in the
// C++ case the scoped atom table remembers its own atoms.
this.name = name;
this.camelCaseName = name;
this.flags = TreeBuilder.OTHER | CUSTOM;
}
@Virtual void release() {
// No-op in Java.
// Implement as delete this in subclass.
// Be sure to release the local name
}
@SuppressWarnings("unused") @Virtual private void destructor() {
}
@Virtual public ElementName cloneElementName(Interner interner) {
return this;
assert this.flags == (TreeBuilder.OTHER | NOT_INTERNED);
}
// START CODE ONLY USED FOR GENERATING CODE uncomment and run to regenerate

View File

@ -127,13 +127,13 @@ final class StackNode<T> {
// ]NOCPP]
) {
this.flags = elementName.getFlags();
this.name = elementName.name;
this.popName = elementName.name;
this.name = elementName.getName();
this.popName = elementName.getName();
this.ns = "http://www.w3.org/1999/xhtml";
this.node = node;
this.attributes = null;
this.refcount = 1;
assert !elementName.isCustom() : "Don't use this constructor for custom elements.";
assert elementName.isInterned() : "Don't use this constructor for custom elements.";
// [NOCPP[
this.locator = locator;
// ]NOCPP]
@ -152,13 +152,13 @@ final class StackNode<T> {
// ]NOCPP]
) {
this.flags = elementName.getFlags();
this.name = elementName.name;
this.popName = elementName.name;
this.name = elementName.getName();
this.popName = elementName.getName();
this.ns = "http://www.w3.org/1999/xhtml";
this.node = node;
this.attributes = attributes;
this.refcount = 1;
assert !elementName.isCustom() : "Don't use this constructor for custom elements.";
assert elementName.isInterned() : "Don't use this constructor for custom elements.";
// [NOCPP[
this.locator = locator;
// ]NOCPP]
@ -177,7 +177,7 @@ final class StackNode<T> {
// ]NOCPP]
) {
this.flags = elementName.getFlags();
this.name = elementName.name;
this.name = elementName.getName();
this.popName = popName;
this.ns = "http://www.w3.org/1999/xhtml";
this.node = node;
@ -204,7 +204,7 @@ final class StackNode<T> {
// ]NOCPP]
) {
this.flags = prepareSvgFlags(elementName.getFlags());
this.name = elementName.name;
this.name = elementName.getName();
this.popName = popName;
this.ns = "http://www.w3.org/2000/svg";
this.node = node;
@ -231,7 +231,7 @@ final class StackNode<T> {
) {
this.flags = prepareMathFlags(elementName.getFlags(),
markAsIntegrationPoint);
this.name = elementName.name;
this.name = elementName.getName();
this.popName = popName;
this.ns = "http://www.w3.org/1998/Math/MathML";
this.node = node;

View File

@ -415,10 +415,18 @@ public class Tokenizer implements Locator {
protected boolean endTag;
/**
* The current tag token name.
* The current tag token name. One of
* 1) null,
* 2) non-owning reference to nonInternedTagName
* 3) non-owning reference to a pre-interned ElementName
*/
private ElementName tagName = null;
/**
* The recycled ElementName instance for the non-pre-interned cases.
*/
private ElementName nonInternedTagName = null;
/**
* The current attribute name.
*/
@ -518,6 +526,7 @@ public class Tokenizer implements Locator {
this.bmpChar = new char[1];
this.astralChar = new char[2];
this.tagName = null;
this.nonInternedTagName = new ElementName();
this.attributeName = null;
this.doctypeName = null;
this.publicIdentifier = null;
@ -547,6 +556,7 @@ public class Tokenizer implements Locator {
this.bmpChar = new char[1];
this.astralChar = new char[2];
this.tagName = null;
this.nonInternedTagName = new ElementName();
this.attributeName = null;
this.doctypeName = null;
this.publicIdentifier = null;
@ -692,6 +702,7 @@ public class Tokenizer implements Locator {
@Auto char[] asArray = Portability.newCharArrayFromLocal(endTagExpectation);
this.endTagExpectation = ElementName.elementNameByBuffer(asArray, 0,
asArray.length, interner);
assert this.endTagExpectation != null;
endTagExpectationToArray();
}
@ -1092,6 +1103,11 @@ public class Tokenizer implements Locator {
private void strBufToElementNameString() {
tagName = ElementName.elementNameByBuffer(strBuf, 0, strBufLen,
interner);
if (tagName == null) {
nonInternedTagName.setNameForNonInterned(Portability.newLocalNameFromBuffer(strBuf, 0, strBufLen,
interner));
tagName = nonInternedTagName;
}
clearStrBufAfterUse();
}
@ -1124,7 +1140,6 @@ public class Tokenizer implements Locator {
tokenHandler.startTag(tagName, attrs, selfClosing);
// CPPONLY: }
}
tagName.release();
tagName = null;
if (newAttributesEachTime) {
attributes = null;
@ -6637,10 +6652,8 @@ public class Tokenizer implements Locator {
Portability.releaseString(publicIdentifier);
publicIdentifier = null;
}
if (tagName != null) {
tagName.release();
tagName = null;
}
nonInternedTagName.setNameForNonInterned(null);
if (attributeName != null) {
attributeName.release();
attributeName = null;
@ -6722,7 +6735,6 @@ public class Tokenizer implements Locator {
shouldSuspend = false;
initDoctypeFields();
if (tagName != null) {
tagName.release();
tagName = null;
}
if (attributeName != null) {
@ -6788,13 +6800,17 @@ public class Tokenizer implements Locator {
publicIdentifier = Portability.newStringFromString(other.publicIdentifier);
}
if (tagName != null) {
tagName.release();
}
if (other.tagName == null) {
tagName = null;
} else if (other.tagName.isInterned()) {
tagName = other.tagName;
} else {
tagName = other.tagName.cloneElementName(interner);
// In the C++ case, We might be loading state from another
// tokenizer that has atoms from a different tokenizer-scoped
// atom table. Therefore, we have to obtain the correspoding
// atom from our own atom table.
nonInternedTagName.setNameForNonInterned(Portability.newLocalFromLocal(other.tagName.getName(), interner));
tagName = nonInternedTagName;
}
if (attributeName != null) {
@ -7045,6 +7061,8 @@ public class Tokenizer implements Locator {
}
void destructor() {
Portability.delete(nonInternedTagName);
nonInternedTagName = null;
// The translator will write refcount tracing stuff here
Portability.delete(attributes);
attributes = null;

View File

@ -632,7 +632,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
}
// This is the SVG variant of the StackNode constructor.
StackNode<T> node = new StackNode<T>(elementName,
elementName.camelCaseName, elt
elementName.getCamelCaseName(), elt
// [NOCPP[
, errorHandler == null ? null
: new TaintableLocatorImpl(tokenizer)
@ -663,7 +663,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
}
// This is the MathML variant of the StackNode constructor.
StackNode<T> node = new StackNode<T>(elementName, elt,
elementName.name, false
elementName.getName(), false
// [NOCPP[
, errorHandler == null ? null
: new TaintableLocatorImpl(tokenizer)
@ -1670,7 +1670,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
needToDropLF = false;
starttagloop: for (;;) {
int group = elementName.getGroup();
@Local String name = elementName.name;
@Local String name = elementName.getName();
if (isInForeign()) {
StackNode<T> currentNode = stack[currentPtr];
@NsUri String currNs = currentNode.ns;
@ -2229,7 +2229,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
case FONT:
reconstructTheActiveFormattingElements();
maybeForgetEarlierDuplicateFormattingElement(elementName.name, attributes);
maybeForgetEarlierDuplicateFormattingElement(elementName.getName(), attributes);
appendToCurrentNodeAndPushFormattingElementMayFoster(
elementName,
attributes);
@ -3381,7 +3381,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
needToDropLF = false;
int eltPos;
int group = elementName.getGroup();
@Local String name = elementName.name;
@Local String name = elementName.getName();
endtagloop: for (;;) {
if (isInForeign()) {
if (stack[currentPtr].name != name) {
@ -5306,9 +5306,9 @@ public abstract class TreeBuilder<T> implements TokenHandler,
StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) {
fatal();
elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.name, attributes);
elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes);
} else {
elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes, current.node);
elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes, current.node);
appendElement(elt, current.node);
}
StackNode<T> node = new StackNode<T>(elementName, elt, clone
@ -5329,7 +5329,7 @@ public abstract class TreeBuilder<T> implements TokenHandler,
// ]NOCPP]
// This method can't be called for custom elements
T currentNode = stack[currentPtr].node;
T elt = createElement("http://www.w3.org/1999/xhtml", elementName.name, attributes, currentNode);
T elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes, currentNode);
appendElement(elt, currentNode);
if (ElementName.TEMPLATE == elementName) {
elt = getDocumentFragmentForTemplate(elt);
@ -5345,10 +5345,10 @@ public abstract class TreeBuilder<T> implements TokenHandler,
private void appendToCurrentNodeAndPushElementMayFoster(ElementName elementName,
HtmlAttributes attributes)
throws SAXException {
@Local String popName = elementName.name;
@Local String popName = elementName.getName();
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
if (elementName.isCustom()) {
if (!elementName.isInterned()) {
popName = checkPopName(popName);
}
// ]NOCPP]
@ -5372,10 +5372,10 @@ public abstract class TreeBuilder<T> implements TokenHandler,
private void appendToCurrentNodeAndPushElementMayFosterMathML(
ElementName elementName, HtmlAttributes attributes)
throws SAXException {
@Local String popName = elementName.name;
@Local String popName = elementName.getName();
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1998/Math/MathML");
if (elementName.isCustom()) {
if (!elementName.isInterned()) {
popName = checkPopName(popName);
}
// ]NOCPP]
@ -5428,10 +5428,10 @@ public abstract class TreeBuilder<T> implements TokenHandler,
private void appendToCurrentNodeAndPushElementMayFosterSVG(
ElementName elementName, HtmlAttributes attributes)
throws SAXException {
@Local String popName = elementName.camelCaseName;
@Local String popName = elementName.getCamelCaseName();
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/2000/svg");
if (elementName.isCustom()) {
if (!elementName.isInterned()) {
popName = checkPopName(popName);
}
// ]NOCPP]
@ -5464,10 +5464,10 @@ public abstract class TreeBuilder<T> implements TokenHandler,
StackNode<T> current = stack[currentPtr];
if (current.isFosterParenting()) {
fatal();
elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.name,
elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.getName(),
attributes, formOwner);
} else {
elt = createElement("http://www.w3.org/1999/xhtml", elementName.name,
elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(),
attributes, formOwner, current.node);
appendElement(elt, current.node);
}
@ -5504,10 +5504,10 @@ public abstract class TreeBuilder<T> implements TokenHandler,
private void appendVoidElementToCurrentMayFoster(
ElementName elementName, HtmlAttributes attributes)
throws SAXException {
@Local String popName = elementName.name;
@Local String popName = elementName.getName();
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
if (elementName.isCustom()) {
if (!elementName.isInterned()) {
popName = checkPopName(popName);
}
// ]NOCPP]
@ -5527,10 +5527,10 @@ public abstract class TreeBuilder<T> implements TokenHandler,
private void appendVoidElementToCurrentMayFosterSVG(
ElementName elementName, HtmlAttributes attributes)
throws SAXException {
@Local String popName = elementName.camelCaseName;
@Local String popName = elementName.getCamelCaseName();
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/2000/svg");
if (elementName.isCustom()) {
if (!elementName.isInterned()) {
popName = checkPopName(popName);
}
// ]NOCPP]
@ -5550,10 +5550,10 @@ public abstract class TreeBuilder<T> implements TokenHandler,
private void appendVoidElementToCurrentMayFosterMathML(
ElementName elementName, HtmlAttributes attributes)
throws SAXException {
@Local String popName = elementName.name;
@Local String popName = elementName.getName();
// [NOCPP[
checkAttributes(attributes, "http://www.w3.org/1998/Math/MathML");
if (elementName.isCustom()) {
if (!elementName.isInterned()) {
popName = checkPopName(popName);
}
// ]NOCPP]

View File

@ -72,7 +72,6 @@ UNIFIED_SOURCES += [
'nsHtml5PlainTextUtils.cpp',
'nsHtml5Portability.cpp',
'nsHtml5ReleasableAttributeName.cpp',
'nsHtml5ReleasableElementName.cpp',
'nsHtml5Speculation.cpp',
'nsHtml5SpeculativeLoad.cpp',
'nsHtml5StackNode.cpp',

View File

@ -53,9 +53,7 @@
#include "nsHtml5Portability.h"
#include "nsHtml5ElementName.h"
#include "nsHtml5ReleasableElementName.h"
nsHtml5ElementName* nsHtml5ElementName::ELT_NULL_ELEMENT_NAME = nullptr;
int32_t
nsHtml5ElementName::getGroup()
{
@ -63,9 +61,9 @@ nsHtml5ElementName::getGroup()
}
bool
nsHtml5ElementName::isCustom()
nsHtml5ElementName::isInterned()
{
return (flags & NS_HTML5ELEMENT_NAME_CUSTOM);
return !(flags & NS_HTML5ELEMENT_NAME_NOT_INTERNED);
}
nsHtml5ElementName*
@ -74,12 +72,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;
}
@ -94,30 +92,27 @@ nsHtml5ElementName::nsHtml5ElementName(nsIAtom* name, nsIAtom* camelCaseName, in
MOZ_COUNT_CTOR(nsHtml5ElementName);
}
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_BIG = nullptr;
@ -367,7 +362,6 @@ staticJArray<int32_t,int32_t> nsHtml5ElementName::ELEMENT_HASHES = { ELEMENT_HAS
void
nsHtml5ElementName::initializeStatics()
{
ELT_NULL_ELEMENT_NAME = new nsHtml5ElementName(nullptr);
ELT_BIG = new nsHtml5ElementName(nsHtml5Atoms::big, nsHtml5Atoms::big, NS_HTML5TREE_BUILDER_B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U);
ELT_BDO = new nsHtml5ElementName(nsHtml5Atoms::bdo, nsHtml5Atoms::bdo, NS_HTML5TREE_BUILDER_OTHER);
ELT_COL = new nsHtml5ElementName(nsHtml5Atoms::col, nsHtml5Atoms::col, NS_HTML5TREE_BUILDER_COL | NS_HTML5ELEMENT_NAME_SPECIAL);
@ -1184,7 +1178,6 @@ nsHtml5ElementName::initializeStatics()
void
nsHtml5ElementName::releaseStatics()
{
delete ELT_NULL_ELEMENT_NAME;
delete ELT_BIG;
delete ELT_BDO;
delete ELT_COL;

View File

@ -57,20 +57,26 @@ class nsHtml5Portability;
class nsHtml5ElementName
{
public:
static nsHtml5ElementName* ELT_NULL_ELEMENT_NAME;
private:
nsIAtom* name;
nsIAtom* camelCaseName;
public:
int32_t flags;
inline int32_t getFlags()
{
return flags;
}
inline nsIAtom* getName() { return name; }
inline nsIAtom* getCamelCaseName() { return camelCaseName; }
inline int32_t getFlags() { return flags; }
int32_t getGroup();
bool isCustom();
static nsHtml5ElementName* elementNameByBuffer(char16_t* buf, int32_t offset, int32_t length, nsHtml5AtomTable* interner);
private:
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)
{
uint32_t len = length;
@ -102,12 +108,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_BIG;
static nsHtml5ElementName* ELT_BDO;
static nsHtml5ElementName* ELT_COL;
@ -313,7 +317,6 @@ class nsHtml5ElementName
static nsHtml5ElementName* ELT_RUBY;
static nsHtml5ElementName* ELT_SUMMARY;
static nsHtml5ElementName* ELT_TBODY;
private:
static nsHtml5ElementName** ELEMENT_NAMES;
static staticJArray<int32_t,int32_t> ELEMENT_HASHES;
@ -323,7 +326,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)

View File

@ -1,30 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsHtml5ReleasableElementName.h"
nsHtml5ReleasableElementName::nsHtml5ReleasableElementName(nsIAtom* name)
: nsHtml5ElementName(name)
{
}
void
nsHtml5ReleasableElementName::release()
{
delete this;
}
nsHtml5ElementName*
nsHtml5ReleasableElementName::cloneElementName(nsHtml5AtomTable* aInterner)
{
nsIAtom* l = name;
if (aInterner) {
if (!l->IsStaticAtom()) {
nsAutoString str;
l->ToString(str);
l = aInterner->GetAtom(str);
}
}
return new nsHtml5ReleasableElementName(l);
}

View File

@ -1,19 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsHtml5ReleasableElementName_h
#define nsHtml5ReleasableElementName_h
#include "nsHtml5ElementName.h"
#include "mozilla/Attributes.h"
class nsHtml5ReleasableElementName final : public nsHtml5ElementName
{
public:
explicit nsHtml5ReleasableElementName(nsIAtom* name);
virtual void release();
virtual nsHtml5ElementName* cloneElementName(nsHtml5AtomTable* interner);
};
#endif // nsHtml5ReleasableElementName_h

View File

@ -98,69 +98,76 @@ nsHtml5StackNode::nsHtml5StackNode(int32_t flags, int32_t ns, nsIAtom* name, nsI
MOZ_COUNT_CTOR(nsHtml5StackNode);
}
nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node)
: flags(elementName->getFlags()),
name(elementName->name),
popName(elementName->name),
ns(kNameSpaceID_XHTML),
node(node),
attributes(nullptr),
refcount(1)
nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName,
nsIContentHandle* node)
: flags(elementName->getFlags())
, 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),
ns(kNameSpaceID_XHTML),
node(node),
attributes(attributes),
refcount(1)
nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName,
nsIContentHandle* node,
nsHtml5HtmlAttributes* attributes)
: flags(elementName->getFlags())
, 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),
popName(popName),
ns(kNameSpaceID_XHTML),
node(node),
attributes(nullptr),
refcount(1)
nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName,
nsIContentHandle* node,
nsIAtom* popName)
: flags(elementName->getFlags())
, name(elementName->getName())
, popName(popName)
, ns(kNameSpaceID_XHTML)
, node(node)
, attributes(nullptr)
, refcount(1)
{
MOZ_COUNT_CTOR(nsHtml5StackNode);
}
nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIAtom* popName, nsIContentHandle* node)
: flags(prepareSvgFlags(elementName->getFlags())),
name(elementName->name),
popName(popName),
ns(kNameSpaceID_SVG),
node(node),
attributes(nullptr),
refcount(1)
nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName,
nsIAtom* popName,
nsIContentHandle* node)
: flags(prepareSvgFlags(elementName->getFlags()))
, name(elementName->getName())
, popName(popName)
, ns(kNameSpaceID_SVG)
, node(node)
, attributes(nullptr)
, refcount(1)
{
MOZ_COUNT_CTOR(nsHtml5StackNode);
}
nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName, bool markAsIntegrationPoint)
: flags(prepareMathFlags(elementName->getFlags(), markAsIntegrationPoint)),
name(elementName->name),
popName(popName),
ns(kNameSpaceID_MathML),
node(node),
attributes(nullptr),
refcount(1)
nsHtml5StackNode::nsHtml5StackNode(nsHtml5ElementName* elementName,
nsIContentHandle* node,
nsIAtom* popName,
bool markAsIntegrationPoint)
: flags(prepareMathFlags(elementName->getFlags(), markAsIntegrationPoint))
, name(elementName->getName())
, popName(popName)
, ns(kNameSpaceID_MathML)
, node(node)
, attributes(nullptr)
, refcount(1)
{
MOZ_COUNT_CTOR(nsHtml5StackNode);
}

View File

@ -88,20 +88,23 @@ staticJArray<char16_t,int32_t> nsHtml5Tokenizer::NOSCRIPT_ARR = { NOSCRIPT_ARR_D
static char16_t const NOFRAMES_ARR_DATA[] = { 'n', 'o', 'f', 'r', 'a', 'm', 'e', 's' };
staticJArray<char16_t,int32_t> nsHtml5Tokenizer::NOFRAMES_ARR = { NOFRAMES_ARR_DATA, MOZ_ARRAY_LENGTH(NOFRAMES_ARR_DATA) };
nsHtml5Tokenizer::nsHtml5Tokenizer(nsHtml5TreeBuilder* tokenHandler, bool viewingXmlSource)
: tokenHandler(tokenHandler),
encodingDeclarationHandler(nullptr),
charRefBuf(jArray<char16_t,int32_t>::newJArray(32)),
bmpChar(jArray<char16_t,int32_t>::newJArray(1)),
astralChar(jArray<char16_t,int32_t>::newJArray(2)),
tagName(nullptr),
attributeName(nullptr),
doctypeName(nullptr),
publicIdentifier(nullptr),
systemIdentifier(nullptr),
attributes(tokenHandler->HasBuilder() ? new nsHtml5HtmlAttributes(0) : nullptr),
newAttributesEachTime(!tokenHandler->HasBuilder()),
viewingXmlSource(viewingXmlSource)
nsHtml5Tokenizer::nsHtml5Tokenizer(nsHtml5TreeBuilder* tokenHandler,
bool viewingXmlSource)
: tokenHandler(tokenHandler)
, encodingDeclarationHandler(nullptr)
, charRefBuf(jArray<char16_t, int32_t>::newJArray(32))
, bmpChar(jArray<char16_t, int32_t>::newJArray(1))
, astralChar(jArray<char16_t, int32_t>::newJArray(2))
, tagName(nullptr)
, nonInternedTagName(new nsHtml5ElementName())
, attributeName(nullptr)
, doctypeName(nullptr)
, publicIdentifier(nullptr)
, systemIdentifier(nullptr)
, attributes(tokenHandler->HasBuilder() ? new nsHtml5HtmlAttributes(0)
: nullptr)
, newAttributesEachTime(!tokenHandler->HasBuilder())
, viewingXmlSource(viewingXmlSource)
{
MOZ_COUNT_CTOR(nsHtml5Tokenizer);
}
@ -135,6 +138,7 @@ nsHtml5Tokenizer::setStateAndEndTagExpectation(int32_t specialTokenizerState, ns
}
autoJArray<char16_t,int32_t> asArray = nsHtml5Portability::newCharArrayFromLocal(endTagExpectation);
this->endTagExpectation = nsHtml5ElementName::elementNameByBuffer(asArray, 0, asArray.length, interner);
MOZ_ASSERT(!!this->endTagExpectation);
endTagExpectationToArray();
}
@ -283,6 +287,12 @@ void
nsHtml5Tokenizer::strBufToElementNameString()
{
tagName = nsHtml5ElementName::elementNameByBuffer(strBuf, 0, strBufLen, interner);
if (!tagName) {
nonInternedTagName->setNameForNonInterned(
nsHtml5Portability::newLocalNameFromBuffer(
strBuf, 0, strBufLen, interner));
tagName = nonInternedTagName;
}
clearStrBufAfterUse();
}
@ -311,7 +321,6 @@ nsHtml5Tokenizer::emitCurrentTagToken(bool selfClosing, int32_t pos)
tokenHandler->startTag(tagName, attrs, selfClosing);
}
}
tagName->release();
tagName = nullptr;
if (newAttributesEachTime) {
attributes = nullptr;
@ -3947,10 +3956,8 @@ nsHtml5Tokenizer::end()
publicIdentifier.Release();
publicIdentifier = nullptr;
}
if (tagName) {
tagName->release();
tagName = nullptr;
}
nonInternedTagName->setNameForNonInterned(nullptr);
if (attributeName) {
attributeName->release();
attributeName = nullptr;
@ -3995,7 +4002,6 @@ nsHtml5Tokenizer::resetToDataState()
shouldSuspend = false;
initDoctypeFields();
if (tagName) {
tagName->release();
tagName = nullptr;
}
if (attributeName) {
@ -4055,13 +4061,15 @@ 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();
@ -4099,6 +4107,8 @@ nsHtml5Tokenizer::setEncodingDeclarationHandler(nsHtml5StreamParser* encodingDec
nsHtml5Tokenizer::~nsHtml5Tokenizer()
{
MOZ_COUNT_DTOR(nsHtml5Tokenizer);
delete nonInternedTagName;
nonInternedTagName = nullptr;
delete attributes;
attributes = nullptr;
}

View File

@ -122,6 +122,8 @@ class nsHtml5Tokenizer
bool endTag;
private:
nsHtml5ElementName* tagName;
nsHtml5ElementName* nonInternedTagName;
protected:
nsHtml5AttributeName* attributeName;
private:

View File

@ -102,7 +102,8 @@ 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->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_DATA, contextName);
@ -114,7 +115,8 @@ 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->setStateAndEndTagExpectation(NS_HTML5TOKENIZER_DATA, contextName);
@ -610,7 +612,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;
@ -1144,7 +1146,8 @@ 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);
@ -2226,7 +2229,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) {
@ -4002,9 +4005,11 @@ 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);
@ -4017,7 +4022,8 @@ 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);
@ -4029,7 +4035,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()) {
@ -4046,7 +4052,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;
@ -4078,7 +4084,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()) {
@ -4100,9 +4106,14 @@ 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);
@ -4129,7 +4140,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()) {
@ -4146,7 +4157,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()) {
@ -4163,7 +4174,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()) {