Bug 1355441 - Reuse StackNode in HTML parser TreeBuilder to avoid malloc. r=hsivonen

This commit is contained in:
William Chen
2017-05-01 17:25:05 -07:00
parent d7a4653ab7
commit b396a8a419
10 changed files with 486 additions and 192 deletions

View File

@@ -28,24 +28,27 @@ import nu.validator.htmlparser.annotation.Local;
import nu.validator.htmlparser.annotation.NsUri;
final class StackNode<T> {
final int flags;
// Index where this stack node is stored in the tree builder's list of stack nodes.
final int idxInTreeBuilder;
final @Local String name;
int flags;
final @Local String popName;
@Local String name;
final @NsUri String ns;
@Local String popName;
final T node;
@NsUri String ns;
T node;
// Only used on the list of formatting elements
HtmlAttributes attributes;
private int refcount = 1;
private int refcount = 0;
// [NOCPP[
private final TaintableLocatorImpl locator;
private TaintableLocatorImpl locator;
public TaintableLocatorImpl getLocator() {
return locator;
@@ -85,9 +88,14 @@ final class StackNode<T> {
// ]NOCPP]
StackNode(int idxInTreeBuilder) {
this.idxInTreeBuilder = idxInTreeBuilder;
this.refcount = 0;
}
/**
* Constructor for copying. This doesn't take another <code>StackNode</code>
* because in C++ the caller is reponsible for reobtaining the local names
* Setter for copying. This doesn't take another <code>StackNode</code>
* because in C++ the caller is responsible for reobtaining the local names
* from another interner.
*
* @param flags
@@ -97,12 +105,13 @@ final class StackNode<T> {
* @param popName
* @param attributes
*/
StackNode(int flags, @NsUri String ns, @Local String name, T node,
void setValues(int flags, @NsUri String ns, @Local String name, T node,
@Local String popName, HtmlAttributes attributes
// [NOCPP[
, TaintableLocatorImpl locator
// ]NOCPP]
// ]NOCPP]
) {
assert isUnused();
this.flags = flags;
this.name = name;
this.popName = popName;
@@ -121,11 +130,12 @@ final class StackNode<T> {
* @param elementName
* @param node
*/
StackNode(ElementName elementName, T node
// [NOCPP[
void setValues(ElementName elementName, T node
// [NOCPP[
, TaintableLocatorImpl locator
// ]NOCPP]
// ]NOCPP]
) {
assert isUnused();
this.flags = elementName.getFlags();
this.name = elementName.getName();
this.popName = elementName.getName();
@@ -140,17 +150,18 @@ final class StackNode<T> {
}
/**
* Constructor for HTML formatting elements.
* Setter for HTML formatting elements.
*
* @param elementName
* @param node
* @param attributes
*/
StackNode(ElementName elementName, T node, HtmlAttributes attributes
// [NOCPP[
void setValues(ElementName elementName, T node, HtmlAttributes attributes
// [NOCPP[
, TaintableLocatorImpl locator
// ]NOCPP]
// ]NOCPP]
) {
assert isUnused();
this.flags = elementName.getFlags();
this.name = elementName.getName();
this.popName = elementName.getName();
@@ -165,17 +176,18 @@ final class StackNode<T> {
}
/**
* The common-case HTML constructor.
* The common-case HTML setter.
*
* @param elementName
* @param node
* @param popName
*/
StackNode(ElementName elementName, T node, @Local String popName
// [NOCPP[
void setValues(ElementName elementName, T node, @Local String popName
// [NOCPP[
, TaintableLocatorImpl locator
// ]NOCPP]
// ]NOCPP]
) {
assert isUnused();
this.flags = elementName.getFlags();
this.name = elementName.getName();
this.popName = popName;
@@ -189,8 +201,8 @@ final class StackNode<T> {
}
/**
* Constructor for SVG elements. Note that the order of the arguments is
* what distinguishes this from the HTML constructor. This is ugly, but
* Setter for SVG elements. Note that the order of the arguments is
* what distinguishes this from the HTML setter. This is ugly, but
* AFAICT the least disruptive way to make this work with Java's generics
* and without unnecessary branches. :-(
*
@@ -198,11 +210,12 @@ final class StackNode<T> {
* @param popName
* @param node
*/
StackNode(ElementName elementName, @Local String popName, T node
// [NOCPP[
void setValues(ElementName elementName, @Local String popName, T node
// [NOCPP[
, TaintableLocatorImpl locator
// ]NOCPP]
// ]NOCPP]
) {
assert isUnused();
this.flags = prepareSvgFlags(elementName.getFlags());
this.name = elementName.getName();
this.popName = popName;
@@ -216,19 +229,20 @@ final class StackNode<T> {
}
/**
* Constructor for MathML.
* Setter for MathML.
*
* @param elementName
* @param node
* @param popName
* @param markAsIntegrationPoint
*/
StackNode(ElementName elementName, T node, @Local String popName,
void setValues(ElementName elementName, T node, @Local String popName,
boolean markAsIntegrationPoint
// [NOCPP[
, TaintableLocatorImpl locator
// ]NOCPP]
// ]NOCPP]
) {
assert isUnused();
this.flags = prepareMathFlags(elementName.getFlags(),
markAsIntegrationPoint);
this.name = elementName.getName();
@@ -265,7 +279,7 @@ final class StackNode<T> {
}
@SuppressWarnings("unused") private void destructor() {
Portability.delete(attributes);
// The translator adds refcount debug code here.
}
public void dropAttributes() {
@@ -286,10 +300,16 @@ final class StackNode<T> {
refcount++;
}
public void release() {
public void release(TreeBuilder<T> owningTreeBuilder) {
refcount--;
assert refcount >= 0;
if (refcount == 0) {
Portability.delete(this);
Portability.delete(attributes);
owningTreeBuilder.notifyUnusedStackNode(idxInTreeBuilder);
}
}
boolean isUnused() {
return refcount == 0;
}
}