Backed out changeset 2e7615b554ee (bug 1355441) for crashing at nsHtml5TreeBuilder::getUnusedStackNode() intermittent failures
authorIris Hsiao <ihsiao@mozilla.com>
Tue, 09 May 2017 17:11:28 +0800
changeset 357186 cbd10998876e204669409d940f8b177592aaa9db
parent 357185 e7d08d835dcb5a481e71b17188d8c9a9d70cc0ec
child 357187 7ede4e827120915dd8a805335add61e39dbdac71
push id90069
push userihsiao@mozilla.com
push dateTue, 09 May 2017 09:11:38 +0000
treeherdermozilla-inbound@cbd10998876e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1355441
milestone55.0a1
backs out2e7615b554ee2c24d286bc54c6cb21d47af6a3d0
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 2e7615b554ee (bug 1355441) for crashing at nsHtml5TreeBuilder::getUnusedStackNode() intermittent failures
parser/html/javasrc/StackNode.java
parser/html/javasrc/StateSnapshot.java
parser/html/javasrc/TreeBuilder.java
parser/html/nsHtml5StackNode.cpp
parser/html/nsHtml5StackNode.h
parser/html/nsHtml5StateSnapshot.cpp
parser/html/nsHtml5StateSnapshot.h
parser/html/nsHtml5StreamParser.cpp
parser/html/nsHtml5TreeBuilder.cpp
parser/html/nsHtml5TreeBuilder.h
--- a/parser/html/javasrc/StackNode.java
+++ b/parser/html/javasrc/StackNode.java
@@ -23,37 +23,34 @@
 
 package nu.validator.htmlparser.impl;
 
 import nu.validator.htmlparser.annotation.Inline;
 import nu.validator.htmlparser.annotation.Local;
 import nu.validator.htmlparser.annotation.NsUri;
 
 final class StackNode<T> {
-    // Index where this stack node is stored in the tree builder's list of stack nodes.
-    final int idxInTreeBuilder;
+    final int flags;
 
-    int flags;
+    final @Local String name;
 
-    @Local String name;
-
-    @Local String popName;
+    final @Local String popName;
 
-    @NsUri String ns;
+    final @NsUri String ns;
 
-    T node;
+    final T node;
 
     // Only used on the list of formatting elements
     HtmlAttributes attributes;
 
-    private int refcount = 0;
+    private int refcount = 1;
 
     // [NOCPP[
 
-    private TaintableLocatorImpl locator;
+    private final TaintableLocatorImpl locator;
 
     public TaintableLocatorImpl getLocator() {
         return locator;
     }
 
     // ]NOCPP]
 
     @Inline public int getFlags() {
@@ -83,40 +80,34 @@ final class StackNode<T> {
     // [NOCPP[
 
     public boolean isOptionalEndTag() {
         return (flags & ElementName.OPTIONAL_END_TAG) != 0;
     }
 
     // ]NOCPP]
 
-    StackNode(int idxInTreeBuilder) {
-        this.idxInTreeBuilder = idxInTreeBuilder;
-        this.refcount = 0;
-    }
-
     /**
-     * Setter for copying. This doesn't take another <code>StackNode</code>
-     * because in C++ the caller is responsible for reobtaining the local names
+     * Constructor for copying. This doesn't take another <code>StackNode</code>
+     * because in C++ the caller is reponsible for reobtaining the local names
      * from another interner.
      *
      * @param flags
      * @param ns
      * @param name
      * @param node
      * @param popName
      * @param attributes
      */
-    void setValues(int flags, @NsUri String ns, @Local String name, T node,
+    StackNode(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;
         this.ns = ns;
         this.node = node;
         this.attributes = attributes;
         this.refcount = 1;
         // [NOCPP[
@@ -125,129 +116,124 @@ final class StackNode<T> {
     }
 
     /**
      * Short hand for well-known HTML elements.
      *
      * @param elementName
      * @param node
      */
-    void setValues(ElementName elementName, T node
-            // [NOCPP[
+    StackNode(ElementName elementName, T node
+    // [NOCPP[
             , TaintableLocatorImpl locator
-            // ]NOCPP]
+    // ]NOCPP]
     ) {
-        assert isUnused();
         this.flags = elementName.getFlags();
         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.isInterned() : "Don't use this constructor for custom elements.";
         // [NOCPP[
         this.locator = locator;
         // ]NOCPP]
     }
 
     /**
-     * Setter for HTML formatting elements.
+     * Constructor for HTML formatting elements.
      *
      * @param elementName
      * @param node
      * @param attributes
      */
-    void setValues(ElementName elementName, T node, HtmlAttributes attributes
-            // [NOCPP[
+    StackNode(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();
         this.ns = "http://www.w3.org/1999/xhtml";
         this.node = node;
         this.attributes = attributes;
         this.refcount = 1;
         assert elementName.isInterned() : "Don't use this constructor for custom elements.";
         // [NOCPP[
         this.locator = locator;
         // ]NOCPP]
     }
 
     /**
-     * The common-case HTML setter.
+     * The common-case HTML constructor.
      *
      * @param elementName
      * @param node
      * @param popName
      */
-    void setValues(ElementName elementName, T node, @Local String popName
-            // [NOCPP[
+    StackNode(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;
         this.ns = "http://www.w3.org/1999/xhtml";
         this.node = node;
         this.attributes = null;
         this.refcount = 1;
         // [NOCPP[
         this.locator = locator;
         // ]NOCPP]
     }
 
     /**
-     * Setter for SVG elements. Note that the order of the arguments is
-     * what distinguishes this from the HTML setter. This is ugly, but
+     * Constructor for SVG elements. Note that the order of the arguments is
+     * what distinguishes this from the HTML constructor. This is ugly, but
      * AFAICT the least disruptive way to make this work with Java's generics
      * and without unnecessary branches. :-(
      *
      * @param elementName
      * @param popName
      * @param node
      */
-    void setValues(ElementName elementName, @Local String popName, T node
-            // [NOCPP[
+    StackNode(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;
         this.ns = "http://www.w3.org/2000/svg";
         this.node = node;
         this.attributes = null;
         this.refcount = 1;
         // [NOCPP[
         this.locator = locator;
         // ]NOCPP]
     }
 
     /**
-     * Setter for MathML.
+     * Constructor for MathML.
      *
      * @param elementName
      * @param node
      * @param popName
      * @param markAsIntegrationPoint
      */
-    void setValues(ElementName elementName, T node, @Local String popName,
+    StackNode(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();
         this.popName = popName;
         this.ns = "http://www.w3.org/1998/Math/MathML";
         this.node = node;
         this.attributes = null;
         this.refcount = 1;
@@ -274,17 +260,17 @@ final class StackNode<T> {
         }
         if (markAsIntegrationPoint) {
             flags |= ElementName.HTML_INTEGRATION_POINT;
         }
         return flags;
     }
 
     @SuppressWarnings("unused") private void destructor() {
-        // The translator adds refcount debug code here.
+        Portability.delete(attributes);
     }
 
     public void dropAttributes() {
         attributes = null;
     }
 
     // [NOCPP[
     /**
@@ -295,21 +281,15 @@ final class StackNode<T> {
     }
 
     // ]NOCPP]
 
     public void retain() {
         refcount++;
     }
 
-    public void release(TreeBuilder<T> owningTreeBuilder) {
+    public void release() {
         refcount--;
-        assert refcount >= 0;
         if (refcount == 0) {
-            Portability.delete(attributes);
-            owningTreeBuilder.notifyUnusedStackNode(idxInTreeBuilder);
+            Portability.delete(this);
         }
     }
-
-    boolean isUnused() {
-        return refcount == 0;
-    }
 }
--- a/parser/html/javasrc/StateSnapshot.java
+++ b/parser/html/javasrc/StateSnapshot.java
@@ -22,18 +22,16 @@
 
 package nu.validator.htmlparser.impl;
 
 import nu.validator.htmlparser.annotation.Auto;
 
 
 public class StateSnapshot<T> implements TreeBuilderState<T> {
 
-    private final TreeBuilder<T> treeBuilder;
-
     private final @Auto StackNode<T>[] stack;
 
     private final @Auto StackNode<T>[] listOfActiveFormattingElements;
 
     private final @Auto int[] templateModeStack;
 
     private final T formPointer;
 
@@ -59,21 +57,20 @@ public class StateSnapshot<T> implements
      * @param headPointer
      * @param deepTreeSurrogateParent
      * @param mode
      * @param originalMode
      * @param framesetOk
      * @param needToDropLF
      * @param quirks
      */
-    StateSnapshot(TreeBuilder<T> treeBuilder, StackNode<T>[] stack,
+    StateSnapshot(StackNode<T>[] stack,
             StackNode<T>[] listOfActiveFormattingElements, int[] templateModeStack, T formPointer,
             T headPointer, T deepTreeSurrogateParent, int mode, int originalMode,
             boolean framesetOk, boolean needToDropLF, boolean quirks) {
-        this.treeBuilder = treeBuilder;
         this.stack = stack;
         this.listOfActiveFormattingElements = listOfActiveFormattingElements;
         this.templateModeStack = templateModeStack;
         this.formPointer = formPointer;
         this.headPointer = headPointer;
         this.deepTreeSurrogateParent = deepTreeSurrogateParent;
         this.mode = mode;
         this.originalMode = originalMode;
@@ -191,17 +188,17 @@ public class StateSnapshot<T> implements
      * @see nu.validator.htmlparser.impl.TreeBuilderState#getTemplateModeStackLength()
      */
     public int getTemplateModeStackLength() {
         return templateModeStack.length;
     }
 
     @SuppressWarnings("unused") private void destructor() {
         for (int i = 0; i < stack.length; i++) {
-            stack[i].release(treeBuilder);
+            stack[i].release();
         }
         for (int i = 0; i < listOfActiveFormattingElements.length; i++) {
             if (listOfActiveFormattingElements[i] != null) {
-                listOfActiveFormattingElements[i].release(treeBuilder);
+                listOfActiveFormattingElements[i].release();                
             }
         }
     }
 }
--- a/parser/html/javasrc/TreeBuilder.java
+++ b/parser/html/javasrc/TreeBuilder.java
@@ -420,25 +420,16 @@ public abstract class TreeBuilder<T> imp
      */
     private @Auto int[] templateModeStack;
 
     /**
      * Current template mode stack pointer.
      */
     private int templateModePtr = -1;
 
-    private @Auto StackNode<T>[] stackNodes;
-
-    /**
-     * Index of the earliest possible unused or empty element in stackNodes.
-     */
-    private int stackNodesIdx = -1;
-
-    private int numStackNodes = 0;
-
     private @Auto StackNode<T>[] stack;
 
     private int currentPtr = -1;
 
     private @Auto StackNode<T>[] listOfActiveFormattingElements;
 
     private int listPtr = -1;
 
@@ -587,25 +578,22 @@ public abstract class TreeBuilder<T> imp
         SAXParseException spe = new SAXParseException(message, locator);
         errorHandler.warning(spe);
     }
 
     // ]NOCPP]
 
     @SuppressWarnings("unchecked") public final void startTokenization(Tokenizer self) throws SAXException {
         tokenizer = self;
-        stackNodes = new StackNode[64];
         stack = new StackNode[64];
         templateModeStack = new int[64];
         listOfActiveFormattingElements = new StackNode[64];
         needToDropLF = false;
         originalMode = INITIAL;
         templateModePtr = -1;
-        stackNodesIdx = 0;
-        numStackNodes = 0;
         currentPtr = -1;
         listPtr = -1;
         formPointer = null;
         headPointer = null;
         deepTreeSurrogateParent = null;
         // [NOCPP[
         html4 = false;
         idLocations.clear();
@@ -638,17 +626,17 @@ public abstract class TreeBuilder<T> imp
                 ElementName elementName = ElementName.SVG;
                 if ("title" == contextName || "desc" == contextName
                         || "foreignObject" == contextName) {
                     // These elements are all alike and we don't care about
                     // the exact name.
                     elementName = ElementName.FOREIGNOBJECT;
                 }
                 // This is the SVG variant of the StackNode constructor.
-                StackNode<T> node = createStackNode(elementName,
+                StackNode<T> node = new StackNode<T>(elementName,
                         elementName.getCamelCaseName(), elt
                         // [NOCPP[
                         , errorHandler == null ? null
                                 : new TaintableLocatorImpl(tokenizer)
                 // ]NOCPP]
                 );
                 currentPtr++;
                 stack[currentPtr] = node;
@@ -669,32 +657,32 @@ public abstract class TreeBuilder<T> imp
                     elementName = ElementName.ANNOTATION_XML;
                     // Blink does not check the encoding attribute of the
                     // annotation-xml element innerHTML is being set on.
                     // Let's do the same at least until
                     // https://www.w3.org/Bugs/Public/show_bug.cgi?id=26783
                     // is resolved.
                 }
                 // This is the MathML variant of the StackNode constructor.
-                StackNode<T> node = createStackNode(elementName, elt,
+                StackNode<T> node = new StackNode<T>(elementName, elt,
                         elementName.getName(), false
                         // [NOCPP[
                         , errorHandler == null ? null
                                 : new TaintableLocatorImpl(tokenizer)
                 // ]NOCPP]
                 );
                 currentPtr++;
                 stack[currentPtr] = node;
                 tokenizer.setStateAndEndTagExpectation(Tokenizer.DATA,
                         contextName);
                 // The frameset-ok flag is set even though <frameset> never
                 // ends up being allowed as HTML frameset in the fragment case.
                 mode = FRAMESET_OK;
             } else { // html
-                StackNode<T> node = createStackNode(ElementName.HTML, elt
+                StackNode<T> node = new StackNode<T>(ElementName.HTML, elt
                 // [NOCPP[
                         , errorHandler == null ? null
                                 : new TaintableLocatorImpl(tokenizer)
                 // ]NOCPP]
                 );
                 currentPtr++;
                 stack[currentPtr] = node;
                 if ("template" == contextName) {
@@ -727,17 +715,17 @@ public abstract class TreeBuilder<T> imp
         } else {
             mode = INITIAL;
             // If we are viewing XML source, put a foreign element permanently
             // on the stack so that cdataSectionAllowed() returns true.
             // CPPONLY: if (tokenizer.isViewingXmlSource()) {
             // CPPONLY: T elt = createElement("http://www.w3.org/2000/svg",
             // CPPONLY: "svg",
             // CPPONLY: tokenizer.emptyAttributes(), null);
-            // CPPONLY: StackNode<T> node = createStackNode(ElementName.SVG,
+            // CPPONLY: StackNode<T> node = new StackNode<T>(ElementName.SVG,
             // CPPONLY: "svg",
             // CPPONLY: elt);
             // CPPONLY: currentPtr++;
             // CPPONLY: stack[currentPtr] = node;
             // CPPONLY: }
         }
     }
 
@@ -1630,39 +1618,30 @@ public abstract class TreeBuilder<T> imp
      */
     public final void endTokenization() throws SAXException {
         formPointer = null;
         headPointer = null;
         deepTreeSurrogateParent = null;
         templateModeStack = null;
         if (stack != null) {
             while (currentPtr > -1) {
-                stack[currentPtr].release(this);
+                stack[currentPtr].release();
                 currentPtr--;
             }
             stack = null;
         }
         if (listOfActiveFormattingElements != null) {
             while (listPtr > -1) {
                 if (listOfActiveFormattingElements[listPtr] != null) {
-                    listOfActiveFormattingElements[listPtr].release(this);
+                    listOfActiveFormattingElements[listPtr].release();
                 }
                 listPtr--;
             }
             listOfActiveFormattingElements = null;
         }
-        if (stackNodes != null) {
-            for (int i = 0; i < numStackNodes; i++) {
-                assert stackNodes[i].isUnused();
-                Portability.delete(stackNodes[i]);
-            }
-            numStackNodes = 0;
-            stackNodesIdx = 0;
-            stackNodes = null;
-        }
         // [NOCPP[
         idLocations.clear();
         // ]NOCPP]
         charBuffer = null;
         end();
     }
 
     public final void startTag(ElementName elementName,
@@ -2234,17 +2213,17 @@ public abstract class TreeBuilder<T> imp
                                     StackNode<T> activeA = listOfActiveFormattingElements[activeAPos];
                                     activeA.retain();
                                     adoptionAgencyEndTag("a");
                                     removeFromStack(activeA);
                                     activeAPos = findInListOfActiveFormattingElements(activeA);
                                     if (activeAPos != -1) {
                                         removeFromListOfActiveFormattingElements(activeAPos);
                                     }
-                                    activeA.release(this);
+                                    activeA.release();
                                 }
                                 reconstructTheActiveFormattingElements();
                                 appendToCurrentNodeAndPushFormattingElementMayFoster(
                                         elementName,
                                         attributes);
                                 attributes = null; // CPP
                                 break starttagloop;
                             case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
@@ -4631,32 +4610,32 @@ public abstract class TreeBuilder<T> imp
     }
 
     private void clearTheListOfActiveFormattingElementsUpToTheLastMarker() {
         while (listPtr > -1) {
             if (listOfActiveFormattingElements[listPtr] == null) {
                 --listPtr;
                 return;
             }
-            listOfActiveFormattingElements[listPtr].release(this);
+            listOfActiveFormattingElements[listPtr].release();
             --listPtr;
         }
     }
 
     @Inline private boolean isCurrent(@Local String name) {
         return stack[currentPtr].ns == "http://www.w3.org/1999/xhtml" &&
                 name == stack[currentPtr].name;
     }
 
     private void removeFromStack(int pos) throws SAXException {
         if (currentPtr == pos) {
             pop();
         } else {
             fatal();
-            stack[pos].release(this);
+            stack[pos].release();
             System.arraycopy(stack, pos + 1, stack, pos, currentPtr - pos);
             assert debugOnlyClearLastStackSlot();
             currentPtr--;
         }
     }
 
     private void removeFromStack(StackNode<T> node) throws SAXException {
         if (stack[currentPtr] == node) {
@@ -4666,25 +4645,25 @@ public abstract class TreeBuilder<T> imp
             while (pos >= 0 && stack[pos] != node) {
                 pos--;
             }
             if (pos == -1) {
                 // dead code?
                 return;
             }
             fatal();
-            node.release(this);
+            node.release();
             System.arraycopy(stack, pos + 1, stack, pos, currentPtr - pos);
             currentPtr--;
         }
     }
 
     private void removeFromListOfActiveFormattingElements(int pos) {
         assert listOfActiveFormattingElements[pos] != null;
-        listOfActiveFormattingElements[pos].release(this);
+        listOfActiveFormattingElements[pos].release();
         if (pos == listPtr) {
             assert debugOnlyClearLastListSlot();
             listPtr--;
             return;
         }
         assert pos < listPtr;
         System.arraycopy(listOfActiveFormattingElements, pos + 1,
                 listOfActiveFormattingElements, pos, listPtr - pos);
@@ -4820,28 +4799,28 @@ public abstract class TreeBuilder<T> imp
                 if (nodePos == furthestBlockPos) {
                     bookmark = nodeListPos + 1;
                 }
                 // if (hasChildren(node.node)) { XXX AAA CHANGE
                 assert node == listOfActiveFormattingElements[nodeListPos];
                 assert node == stack[nodePos];
                 T clone = createElement("http://www.w3.org/1999/xhtml",
                         node.name, node.attributes.cloneAttributes(null), commonAncestor.node);
-                StackNode<T> newNode = createStackNode(node.getFlags(), node.ns,
+                StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns,
                         node.name, clone, node.popName, node.attributes
                         // [NOCPP[
                         , node.getLocator()
                         // ]NOCPP]
                 ); // creation ownership goes to stack
                 node.dropAttributes(); // adopt ownership to newNode
                 stack[nodePos] = newNode;
                 newNode.retain(); // retain for list
                 listOfActiveFormattingElements[nodeListPos] = newNode;
-                node.release(this); // release from stack
-                node.release(this); // release from list
+                node.release(); // release from stack
+                node.release(); // release from list
                 node = newNode;
                 // } XXX AAA CHANGE
                 detachFromParent(lastNode.node);
                 appendElement(lastNode.node, node.node);
                 lastNode = node;
             }
             if (commonAncestor.isFosterParenting()) {
                 fatal();
@@ -4849,17 +4828,17 @@ public abstract class TreeBuilder<T> imp
                 insertIntoFosterParent(lastNode.node);
             } else {
                 detachFromParent(lastNode.node);
                 appendElement(lastNode.node, commonAncestor.node);
             }
             T clone = createElement("http://www.w3.org/1999/xhtml",
                     formattingElt.name,
                     formattingElt.attributes.cloneAttributes(null), furthestBlock.node);
-            StackNode<T> formattingClone = createStackNode(
+            StackNode<T> formattingClone = new StackNode<T>(
                     formattingElt.getFlags(), formattingElt.ns,
                     formattingElt.name, clone, formattingElt.popName,
                     formattingElt.attributes
                     // [NOCPP[
                     , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
                     // ]NOCPP]
             ); // Ownership transfers to stack below
             formattingElt.dropAttributes(); // transfer ownership to
@@ -4992,17 +4971,17 @@ public abstract class TreeBuilder<T> imp
         // ]NOCPP]
         addAttributesToElement(stack[0].node, attributes);
     }
 
     private void pushHeadPointerOntoStack() throws SAXException {
         assert headPointer != null;
         assert mode == AFTER_HEAD;
         fatal();
-        silentPush(createStackNode(ElementName.HEAD, headPointer
+        silentPush(new StackNode<T>(ElementName.HEAD, headPointer
         // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         ));
     }
 
     /**
      * @throws SAXException
@@ -5039,156 +5018,35 @@ public abstract class TreeBuilder<T> imp
                 clone = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", entry.name,
                         entry.attributes.cloneAttributes(null));
             } else {
                 clone = createElement("http://www.w3.org/1999/xhtml", entry.name,
                         entry.attributes.cloneAttributes(null), currentNode.node);
                 appendElement(clone, currentNode.node);
             }
 
-            StackNode<T> entryClone = createStackNode(entry.getFlags(),
+            StackNode<T> entryClone = new StackNode<T>(entry.getFlags(),
                     entry.ns, entry.name, clone, entry.popName,
                     entry.attributes
                     // [NOCPP[
                     , entry.getLocator()
                     // ]NOCPP]
             );
 
             entry.dropAttributes(); // transfer ownership to entryClone
 
             push(entryClone);
             // stack takes ownership of the local variable
             listOfActiveFormattingElements[entryPos] = entryClone;
             // overwriting the old entry on the list, so release & retain
-            entry.release(this);
+            entry.release();
             entryClone.retain();
         }
     }
 
-    void notifyUnusedStackNode(int idxInStackNodes) {
-        // stackNodesIdx is the earliest possible index of a stack node that might be unused,
-        // so update the index if necessary.
-        if (idxInStackNodes < stackNodesIdx) {
-            stackNodesIdx = idxInStackNodes;
-        }
-    }
-
-    private StackNode<T> getUnusedStackNode() {
-        // Search for an unused stack node.
-        while (stackNodesIdx < numStackNodes) {
-            if (stackNodes[stackNodesIdx].isUnused()) {
-                return stackNodes[stackNodesIdx++];
-            }
-            stackNodesIdx++;
-        }
-
-        if (stackNodesIdx < stackNodes.length) {
-            // No unused stack nodes, but there is still space in the storage array.
-            stackNodes[stackNodesIdx] = new StackNode<T>(stackNodesIdx);
-            numStackNodes++;
-            return stackNodes[stackNodesIdx++];
-        }
-
-        // Could not find an unused stack node and storage array is full.
-        StackNode<T>[] newStack = new StackNode[stackNodes.length + 64];
-        System.arraycopy(stackNodes, 0, newStack, 0, stackNodes.length);
-        stackNodes = newStack;
-
-        // Create a new stack node and return it.
-        stackNodes[stackNodesIdx] = new StackNode<T>(stackNodesIdx);
-        numStackNodes++;
-        return stackNodes[stackNodesIdx++];
-    }
-
-    private StackNode<T> createStackNode(int flags, @NsUri String ns, @Local String name, T node,
-            @Local String popName, HtmlAttributes attributes
-            // [NOCPP[
-            , TaintableLocatorImpl locator
-            // ]NOCPP]
-    ) {
-        StackNode<T> instance = getUnusedStackNode();
-        instance.setValues(flags, ns, name, node, popName, attributes
-                // [NOCPP[
-                , locator
-                // ]NOCPP]
-        );
-        return instance;
-    }
-
-    private StackNode<T> createStackNode(ElementName elementName, T node
-            // [NOCPP[
-            , TaintableLocatorImpl locator
-            // ]NOCPP]
-    ) {
-        StackNode<T> instance = getUnusedStackNode();
-        instance.setValues(elementName, node
-                // [NOCPP[
-                , locator
-                // ]NOCPP]
-        );
-        return instance;
-    }
-
-    private StackNode<T> createStackNode(ElementName elementName, T node, HtmlAttributes attributes
-            // [NOCPP[
-            , TaintableLocatorImpl locator
-            // ]NOCPP]
-    ) {
-        StackNode<T> instance = getUnusedStackNode();
-        instance.setValues(elementName, node, attributes
-                // [NOCPP[
-                , locator
-                // ]NOCPP]
-        );
-        return instance;
-    }
-
-    private StackNode<T> createStackNode(ElementName elementName, T node, @Local String popName
-            // [NOCPP[
-            , TaintableLocatorImpl locator
-            // ]NOCPP]
-    ) {
-        StackNode<T> instance = getUnusedStackNode();
-        instance.setValues(elementName, node, popName
-                // [NOCPP[
-                , locator
-                // ]NOCPP]
-        );
-        return instance;
-    }
-
-    private StackNode<T> createStackNode(ElementName elementName, @Local String popName, T node
-            // [NOCPP[
-            , TaintableLocatorImpl locator
-            // ]NOCPP]
-    ) {
-        StackNode<T> instance = getUnusedStackNode();
-        instance.setValues(elementName, popName, node
-                // [NOCPP[
-                , locator
-                // ]NOCPP]
-        );
-        return instance;
-    }
-
-    private StackNode<T> createStackNode(ElementName elementName, T node, @Local String popName,
-            boolean markAsIntegrationPoint
-            // [NOCPP[
-            , TaintableLocatorImpl locator
-            // ]NOCPP]
-    ) {
-        StackNode<T> instance = getUnusedStackNode();
-        instance.setValues(elementName, node, popName, markAsIntegrationPoint
-                // [NOCPP[
-                , locator
-                // ]NOCPP]
-        );
-        return instance;
-    }
-
     private void insertIntoFosterParent(T child) throws SAXException {
         int tablePos = findLastOrRoot(TreeBuilder.TABLE);
         int templatePos = findLastOrRoot(TreeBuilder.TEMPLATE);
 
         if (templatePos >= tablePos) {
             appendElement(child, stack[templatePos].node);
             return;
         }
@@ -5230,33 +5088,33 @@ public abstract class TreeBuilder<T> imp
         templateModePtr--;
     }
 
     private void pop() throws SAXException {
         StackNode<T> node = stack[currentPtr];
         assert debugOnlyClearLastStackSlot();
         currentPtr--;
         elementPopped(node.ns, node.popName, node.node);
-        node.release(this);
+        node.release();
     }
 
     private void silentPop() throws SAXException {
         StackNode<T> node = stack[currentPtr];
         assert debugOnlyClearLastStackSlot();
         currentPtr--;
-        node.release(this);
+        node.release();
     }
 
     private void popOnEof() throws SAXException {
         StackNode<T> node = stack[currentPtr];
         assert debugOnlyClearLastStackSlot();
         currentPtr--;
         markMalformedIfScript(node.node);
         elementPopped(node.ns, node.popName, node.node);
-        node.release(this);
+        node.release();
     }
 
     // [NOCPP[
     private void checkAttributes(HtmlAttributes attributes, @NsUri String ns)
             throws SAXException {
         if (errorHandler != null) {
             int len = attributes.getXmlnsLength();
             for (int i = 0; i < len; i++) {
@@ -5348,17 +5206,17 @@ public abstract class TreeBuilder<T> imp
     // ]NOCPP]
 
     private void appendHtmlElementToDocumentAndPush(HtmlAttributes attributes)
             throws SAXException {
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
         // ]NOCPP]
         T elt = createHtmlElementSetAsRoot(attributes);
-        StackNode<T> node = createStackNode(ElementName.HTML,
+        StackNode<T> node = new StackNode<T>(ElementName.HTML,
                 elt
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
     }
 
@@ -5370,17 +5228,17 @@ public abstract class TreeBuilder<T> imp
             throws SAXException {
         // [NOCPP[
         checkAttributes(attributes, "http://www.w3.org/1999/xhtml");
         // ]NOCPP]
         T currentNode = stack[currentPtr].node;
         T elt = createElement("http://www.w3.org/1999/xhtml", "head", attributes, currentNode);
         appendElement(elt, currentNode);
         headPointer = elt;
-        StackNode<T> node = createStackNode(ElementName.HEAD,
+        StackNode<T> node = new StackNode<T>(ElementName.HEAD,
                 elt
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
     }
 
@@ -5409,17 +5267,17 @@ public abstract class TreeBuilder<T> imp
             elt = createElement("http://www.w3.org/1999/xhtml", "form", attributes, current.node);
             appendElement(elt, current.node);
         }
 
         if (!isTemplateContents()) {
             formPointer = elt;
         }
 
-        StackNode<T> node = createStackNode(ElementName.FORM,
+        StackNode<T> node = new StackNode<T>(ElementName.FORM,
                 elt
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
                 // ]NOCPP]
         );
         push(node);
     }
 
@@ -5437,17 +5295,17 @@ public abstract class TreeBuilder<T> imp
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
             elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes);
         } else {
             elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(), attributes, current.node);
             appendElement(elt, current.node);
         }
-        StackNode<T> node = createStackNode(elementName, elt, clone
+        StackNode<T> node = new StackNode<T>(elementName, elt, clone
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
         append(node);
         node.retain(); // append doesn't retain itself
     }
@@ -5460,17 +5318,17 @@ public abstract class TreeBuilder<T> imp
         // ]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.getName(), attributes, currentNode);
         appendElement(elt, currentNode);
         if (ElementName.TEMPLATE == elementName) {
             elt = getDocumentFragmentForTemplate(elt);
         }
-        StackNode<T> node = createStackNode(elementName, elt
+        StackNode<T> node = new StackNode<T>(elementName, elt
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
     }
 
     private void appendToCurrentNodeAndPushElementMayFoster(ElementName elementName,
@@ -5487,17 +5345,17 @@ public abstract class TreeBuilder<T> imp
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
             elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", popName, attributes);
         } else {
             elt = createElement("http://www.w3.org/1999/xhtml", popName, attributes, current.node);
             appendElement(elt, current.node);
         }
-        StackNode<T> node = createStackNode(elementName, elt, popName
+        StackNode<T> node = new StackNode<T>(elementName, elt, popName
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
     }
 
     private void appendToCurrentNodeAndPushElementMayFosterMathML(
@@ -5521,17 +5379,17 @@ public abstract class TreeBuilder<T> imp
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
             elt = createAndInsertFosterParentedElement("http://www.w3.org/1998/Math/MathML", popName, attributes);
         } else {
             elt  = createElement("http://www.w3.org/1998/Math/MathML", popName, attributes, current.node);
             appendElement(elt, current.node);
         }
-        StackNode<T> node = createStackNode(elementName, elt, popName,
+        StackNode<T> node = new StackNode<T>(elementName, elt, popName,
                 markAsHtmlIntegrationPoint
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
     }
 
@@ -5570,17 +5428,17 @@ public abstract class TreeBuilder<T> imp
         StackNode<T> current = stack[currentPtr];
         if (current.isFosterParenting()) {
             fatal();
             elt = createAndInsertFosterParentedElement("http://www.w3.org/2000/svg", popName, attributes);
         } else {
             elt = createElement("http://www.w3.org/2000/svg", popName, attributes, current.node);
             appendElement(elt, current.node);
         }
-        StackNode<T> node = createStackNode(elementName, popName, elt
+        StackNode<T> node = new StackNode<T>(elementName, popName, elt
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
     }
 
     private void appendToCurrentNodeAndPushElementMayFoster(ElementName elementName,
@@ -5597,17 +5455,17 @@ public abstract class TreeBuilder<T> imp
             fatal();
             elt = createAndInsertFosterParentedElement("http://www.w3.org/1999/xhtml", elementName.getName(),
                     attributes, formOwner);
         } else {
             elt = createElement("http://www.w3.org/1999/xhtml", elementName.getName(),
                     attributes, formOwner, current.node);
             appendElement(elt, current.node);
         }
-        StackNode<T> node = createStackNode(elementName, elt
+        StackNode<T> node = new StackNode<T>(elementName, elt
                 // [NOCPP[
                 , errorHandler == null ? null : new TaintableLocatorImpl(tokenizer)
         // ]NOCPP]
         );
         push(node);
     }
 
     private void appendVoidElementToCurrentMayFoster(
@@ -6080,50 +5938,50 @@ public abstract class TreeBuilder<T> imp
      * @throws SAXException
      */
     @SuppressWarnings("unchecked") public TreeBuilderState<T> newSnapshot()
             throws SAXException {
         StackNode<T>[] listCopy = new StackNode[listPtr + 1];
         for (int i = 0; i < listCopy.length; i++) {
             StackNode<T> node = listOfActiveFormattingElements[i];
             if (node != null) {
-                StackNode<T> newNode = createStackNode(node.getFlags(), node.ns,
+                StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns,
                         node.name, node.node, node.popName,
                         node.attributes.cloneAttributes(null)
                         // [NOCPP[
                         , node.getLocator()
                 // ]NOCPP]
                 );
                 listCopy[i] = newNode;
             } else {
                 listCopy[i] = null;
             }
         }
         StackNode<T>[] stackCopy = new StackNode[currentPtr + 1];
         for (int i = 0; i < stackCopy.length; i++) {
             StackNode<T> node = stack[i];
             int listIndex = findInListOfActiveFormattingElements(node);
             if (listIndex == -1) {
-                StackNode<T> newNode = createStackNode(node.getFlags(), node.ns,
+                StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns,
                         node.name, node.node, node.popName,
                         null
                         // [NOCPP[
                         , node.getLocator()
                 // ]NOCPP]
                 );
                 stackCopy[i] = newNode;
             } else {
                 stackCopy[i] = listCopy[listIndex];
                 stackCopy[i].retain();
             }
         }
         int[] templateModeStackCopy = new int[templateModePtr + 1];
         System.arraycopy(templateModeStack, 0, templateModeStackCopy, 0,
                 templateModeStackCopy.length);
-        return new StateSnapshot<T>(this, stackCopy, listCopy, templateModeStackCopy, formPointer,
+        return new StateSnapshot<T>(stackCopy, listCopy, templateModeStackCopy, formPointer,
                 headPointer, deepTreeSurrogateParent, mode, originalMode, framesetOk,
                 needToDropLF, quirks);
     }
 
     public boolean snapshotMatches(TreeBuilderState<T> snapshot) {
         StackNode<T>[] stackCopy = snapshot.getStack();
         int stackLen = snapshot.getStackLength();
         StackNode<T>[] listCopy = snapshot.getListOfActiveFormattingElements();
@@ -6177,58 +6035,58 @@ public abstract class TreeBuilder<T> imp
         int stackLen = snapshot.getStackLength();
         StackNode<T>[] listCopy = snapshot.getListOfActiveFormattingElements();
         int listLen = snapshot.getListOfActiveFormattingElementsLength();
         int[] templateModeStackCopy = snapshot.getTemplateModeStack();
         int templateModeStackLen = snapshot.getTemplateModeStackLength();
 
         for (int i = 0; i <= listPtr; i++) {
             if (listOfActiveFormattingElements[i] != null) {
-                listOfActiveFormattingElements[i].release(this);
+                listOfActiveFormattingElements[i].release();
             }
         }
         if (listOfActiveFormattingElements.length < listLen) {
             listOfActiveFormattingElements = new StackNode[listLen];
         }
         listPtr = listLen - 1;
 
         for (int i = 0; i <= currentPtr; i++) {
-            stack[i].release(this);
+            stack[i].release();
         }
         if (stack.length < stackLen) {
             stack = new StackNode[stackLen];
         }
         currentPtr = stackLen - 1;
 
         if (templateModeStack.length < templateModeStackLen) {
             templateModeStack = new int[templateModeStackLen];
         }
         templateModePtr = templateModeStackLen - 1;
 
         for (int i = 0; i < listLen; i++) {
             StackNode<T> node = listCopy[i];
             if (node != null) {
-                StackNode<T> newNode = createStackNode(node.getFlags(), node.ns,
+                StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns,
                         Portability.newLocalFromLocal(node.name, interner), node.node,
                         Portability.newLocalFromLocal(node.popName, interner),
                         node.attributes.cloneAttributes(null)
                         // [NOCPP[
                         , node.getLocator()
                 // ]NOCPP]
                 );
                 listOfActiveFormattingElements[i] = newNode;
             } else {
                 listOfActiveFormattingElements[i] = null;
             }
         }
         for (int i = 0; i < stackLen; i++) {
             StackNode<T> node = stackCopy[i];
             int listIndex = findInArray(node, listCopy);
             if (listIndex == -1) {
-                StackNode<T> newNode = createStackNode(node.getFlags(), node.ns,
+                StackNode<T> newNode = new StackNode<T>(node.getFlags(), node.ns,
                         Portability.newLocalFromLocal(node.name, interner), node.node,
                         Portability.newLocalFromLocal(node.popName, interner),
                         null
                         // [NOCPP[
                         , node.getLocator()
                 // ]NOCPP]
                 );
                 stack[i] = newNode;
--- a/parser/html/nsHtml5StackNode.cpp
+++ b/parser/html/nsHtml5StackNode.cpp
@@ -81,111 +81,100 @@ nsHtml5StackNode::isFosterParenting()
 
 bool 
 nsHtml5StackNode::isHtmlIntegrationPoint()
 {
   return (flags & nsHtml5ElementName::HTML_INTEGRATION_POINT);
 }
 
 
-nsHtml5StackNode::nsHtml5StackNode(int32_t idxInTreeBuilder)
-  : idxInTreeBuilder(idxInTreeBuilder),
-    refcount(0)
+nsHtml5StackNode::nsHtml5StackNode(int32_t flags, int32_t ns, nsIAtom* name, nsIContentHandle* node, nsIAtom* popName, nsHtml5HtmlAttributes* attributes)
+  : flags(flags),
+    name(name),
+    popName(popName),
+    ns(ns),
+    node(node),
+    attributes(attributes),
+    refcount(1)
 {
   MOZ_COUNT_CTOR(nsHtml5StackNode);
 }
 
-void 
-nsHtml5StackNode::setValues(int32_t flags, int32_t ns, nsIAtom* name, nsIContentHandle* node, nsIAtom* popName, nsHtml5HtmlAttributes* attributes)
+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_ASSERT(isUnused());
-  this->flags = flags;
-  this->name = name;
-  this->popName = popName;
-  this->ns = ns;
-  this->node = node;
-  this->attributes = attributes;
-  this->refcount = 1;
+  MOZ_COUNT_CTOR(nsHtml5StackNode);
+  MOZ_ASSERT(elementName->isInterned(),
+             "Don't use this constructor for custom elements.");
 }
 
-void 
-nsHtml5StackNode::setValues(nsHtml5ElementName* elementName,
-                            nsIContentHandle* node)
+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_ASSERT(isUnused());
-  this->flags = elementName->getFlags();
-  this->name = elementName->getName();
-  this->popName = elementName->getName();
-  this->ns = kNameSpaceID_XHTML;
-  this->node = node;
-  this->attributes = nullptr;
-  this->refcount = 1;
-  MOZ_ASSERT(elementName->isInterned(), "Don't use this constructor for custom elements.");
-}
-
-void 
-nsHtml5StackNode::setValues(nsHtml5ElementName* elementName,
-                            nsIContentHandle* node,
-                            nsHtml5HtmlAttributes* attributes)
-{
-  MOZ_ASSERT(isUnused());
-  this->flags = elementName->getFlags();
-  this->name = elementName->getName();
-  this->popName = elementName->getName();
-  this->ns = kNameSpaceID_XHTML;
-  this->node = node;
-  this->attributes = attributes;
-  this->refcount = 1;
-  MOZ_ASSERT(elementName->isInterned(), "Don't use this constructor for custom elements.");
+  MOZ_COUNT_CTOR(nsHtml5StackNode);
+  MOZ_ASSERT(elementName->isInterned(),
+             "Don't use this constructor for custom elements.");
 }
 
-void 
-nsHtml5StackNode::setValues(nsHtml5ElementName* elementName,
-                            nsIContentHandle* node,
-                            nsIAtom* popName)
+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_ASSERT(isUnused());
-  this->flags = elementName->getFlags();
-  this->name = elementName->getName();
-  this->popName = popName;
-  this->ns = kNameSpaceID_XHTML;
-  this->node = node;
-  this->attributes = nullptr;
-  this->refcount = 1;
+  MOZ_COUNT_CTOR(nsHtml5StackNode);
 }
 
-void 
-nsHtml5StackNode::setValues(nsHtml5ElementName* elementName,
-                            nsIAtom* popName,
-                            nsIContentHandle* node)
+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_ASSERT(isUnused());
-  this->flags = prepareSvgFlags(elementName->getFlags());
-  this->name = elementName->getName();
-  this->popName = popName;
-  this->ns = kNameSpaceID_SVG;
-  this->node = node;
-  this->attributes = nullptr;
-  this->refcount = 1;
+  MOZ_COUNT_CTOR(nsHtml5StackNode);
 }
 
-void 
-nsHtml5StackNode::setValues(nsHtml5ElementName* elementName,
-                            nsIContentHandle* node,
-                            nsIAtom* popName,
-                            bool markAsIntegrationPoint)
+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_ASSERT(isUnused());
-  this->flags = prepareMathFlags(elementName->getFlags(), markAsIntegrationPoint);
-  this->name = elementName->getName();
-  this->popName = popName;
-  this->ns = kNameSpaceID_MathML;
-  this->node = node;
-  this->attributes = nullptr;
-  this->refcount = 1;
+  MOZ_COUNT_CTOR(nsHtml5StackNode);
 }
 
 int32_t 
 nsHtml5StackNode::prepareSvgFlags(int32_t flags)
 {
   flags &=
     ~(nsHtml5ElementName::FOSTER_PARENTING | nsHtml5ElementName::SCOPING |
       nsHtml5ElementName::SPECIAL | nsHtml5ElementName::OPTIONAL_END_TAG);
@@ -210,47 +199,40 @@ nsHtml5StackNode::prepareMathFlags(int32
   }
   return flags;
 }
 
 
 nsHtml5StackNode::~nsHtml5StackNode()
 {
   MOZ_COUNT_DTOR(nsHtml5StackNode);
+  delete attributes;
 }
 
 void 
 nsHtml5StackNode::dropAttributes()
 {
   attributes = nullptr;
 }
 
 void 
 nsHtml5StackNode::retain()
 {
   refcount++;
 }
 
 void 
-nsHtml5StackNode::release(nsHtml5TreeBuilder* owningTreeBuilder)
+nsHtml5StackNode::release()
 {
   refcount--;
-  MOZ_ASSERT(refcount >= 0);
   if (!refcount) {
-    delete attributes;
-    owningTreeBuilder->notifyUnusedStackNode(idxInTreeBuilder);
+    delete this;
   }
 }
 
-bool 
-nsHtml5StackNode::isUnused()
-{
-  return !refcount;
-}
-
 void
 nsHtml5StackNode::initializeStatics()
 {
 }
 
 void
 nsHtml5StackNode::releaseStatics()
 {
--- a/parser/html/nsHtml5StackNode.h
+++ b/parser/html/nsHtml5StackNode.h
@@ -55,17 +55,16 @@ class nsHtml5MetaScanner;
 class nsHtml5UTF16Buffer;
 class nsHtml5StateSnapshot;
 class nsHtml5Portability;
 
 
 class nsHtml5StackNode
 {
   public:
-    int32_t idxInTreeBuilder;
     int32_t flags;
     nsIAtom* name;
     nsIAtom* popName;
     int32_t ns;
     nsIContentHandle* node;
     nsHtml5HtmlAttributes* attributes;
   private:
     int32_t refcount;
@@ -75,30 +74,28 @@ class nsHtml5StackNode
       return flags;
     }
 
     int32_t getGroup();
     bool isScoping();
     bool isSpecial();
     bool isFosterParenting();
     bool isHtmlIntegrationPoint();
-    explicit nsHtml5StackNode(int32_t idxInTreeBuilder);
-    void setValues(int32_t flags, int32_t ns, nsIAtom* name, nsIContentHandle* node, nsIAtom* popName, nsHtml5HtmlAttributes* attributes);
-    void setValues(nsHtml5ElementName* elementName, nsIContentHandle* node);
-    void setValues(nsHtml5ElementName* elementName, nsIContentHandle* node, nsHtml5HtmlAttributes* attributes);
-    void setValues(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName);
-    void setValues(nsHtml5ElementName* elementName, nsIAtom* popName, nsIContentHandle* node);
-    void setValues(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName, bool markAsIntegrationPoint);
+    nsHtml5StackNode(int32_t flags, int32_t ns, nsIAtom* name, nsIContentHandle* node, nsIAtom* popName, nsHtml5HtmlAttributes* attributes);
+    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node);
+    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsHtml5HtmlAttributes* attributes);
+    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName);
+    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIAtom* popName, nsIContentHandle* node);
+    nsHtml5StackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName, bool markAsIntegrationPoint);
   private:
     static int32_t prepareSvgFlags(int32_t flags);
     static int32_t prepareMathFlags(int32_t flags, bool markAsIntegrationPoint);
   public:
     ~nsHtml5StackNode();
     void dropAttributes();
     void retain();
-    void release(nsHtml5TreeBuilder* owningTreeBuilder);
-    bool isUnused();
+    void release();
     static void initializeStatics();
     static void releaseStatics();
 };
 
 #endif
 
--- a/parser/html/nsHtml5StateSnapshot.cpp
+++ b/parser/html/nsHtml5StateSnapshot.cpp
@@ -50,19 +50,18 @@
 #include "nsHtml5MetaScanner.h"
 #include "nsHtml5StackNode.h"
 #include "nsHtml5UTF16Buffer.h"
 #include "nsHtml5Portability.h"
 
 #include "nsHtml5StateSnapshot.h"
 
 
-nsHtml5StateSnapshot::nsHtml5StateSnapshot(nsHtml5TreeBuilder* treeBuilder, jArray<nsHtml5StackNode*,int32_t> stack, jArray<nsHtml5StackNode*,int32_t> listOfActiveFormattingElements, jArray<int32_t,int32_t> templateModeStack, nsIContentHandle* formPointer, nsIContentHandle* headPointer, nsIContentHandle* deepTreeSurrogateParent, int32_t mode, int32_t originalMode, bool framesetOk, bool needToDropLF, bool quirks)
-  : treeBuilder(treeBuilder),
-    stack(stack),
+nsHtml5StateSnapshot::nsHtml5StateSnapshot(jArray<nsHtml5StackNode*,int32_t> stack, jArray<nsHtml5StackNode*,int32_t> listOfActiveFormattingElements, jArray<int32_t,int32_t> templateModeStack, nsIContentHandle* formPointer, nsIContentHandle* headPointer, nsIContentHandle* deepTreeSurrogateParent, int32_t mode, int32_t originalMode, bool framesetOk, bool needToDropLF, bool quirks)
+  : stack(stack),
     listOfActiveFormattingElements(listOfActiveFormattingElements),
     templateModeStack(templateModeStack),
     formPointer(formPointer),
     headPointer(headPointer),
     deepTreeSurrogateParent(deepTreeSurrogateParent),
     mode(mode),
     originalMode(originalMode),
     framesetOk(framesetOk),
@@ -156,21 +155,21 @@ nsHtml5StateSnapshot::getTemplateModeSta
   return templateModeStack.length;
 }
 
 
 nsHtml5StateSnapshot::~nsHtml5StateSnapshot()
 {
   MOZ_COUNT_DTOR(nsHtml5StateSnapshot);
   for (int32_t i = 0; i < stack.length; i++) {
-    stack[i]->release(treeBuilder);
+    stack[i]->release();
   }
   for (int32_t i = 0; i < listOfActiveFormattingElements.length; i++) {
     if (listOfActiveFormattingElements[i]) {
-      listOfActiveFormattingElements[i]->release(treeBuilder);
+      listOfActiveFormattingElements[i]->release();
     }
   }
 }
 
 void
 nsHtml5StateSnapshot::initializeStatics()
 {
 }
--- a/parser/html/nsHtml5StateSnapshot.h
+++ b/parser/html/nsHtml5StateSnapshot.h
@@ -53,30 +53,29 @@ class nsHtml5TreeBuilder;
 class nsHtml5MetaScanner;
 class nsHtml5UTF16Buffer;
 class nsHtml5Portability;
 
 
 class nsHtml5StateSnapshot : public nsAHtml5TreeBuilderState
 {
   private:
-    nsHtml5TreeBuilder* treeBuilder;
     autoJArray<nsHtml5StackNode*,int32_t> stack;
     autoJArray<nsHtml5StackNode*,int32_t> listOfActiveFormattingElements;
     autoJArray<int32_t,int32_t> templateModeStack;
     nsIContentHandle* formPointer;
     nsIContentHandle* headPointer;
     nsIContentHandle* deepTreeSurrogateParent;
     int32_t mode;
     int32_t originalMode;
     bool framesetOk;
     bool needToDropLF;
     bool quirks;
   public:
-    nsHtml5StateSnapshot(nsHtml5TreeBuilder* treeBuilder, jArray<nsHtml5StackNode*,int32_t> stack, jArray<nsHtml5StackNode*,int32_t> listOfActiveFormattingElements, jArray<int32_t,int32_t> templateModeStack, nsIContentHandle* formPointer, nsIContentHandle* headPointer, nsIContentHandle* deepTreeSurrogateParent, int32_t mode, int32_t originalMode, bool framesetOk, bool needToDropLF, bool quirks);
+    nsHtml5StateSnapshot(jArray<nsHtml5StackNode*,int32_t> stack, jArray<nsHtml5StackNode*,int32_t> listOfActiveFormattingElements, jArray<int32_t,int32_t> templateModeStack, nsIContentHandle* formPointer, nsIContentHandle* headPointer, nsIContentHandle* deepTreeSurrogateParent, int32_t mode, int32_t originalMode, bool framesetOk, bool needToDropLF, bool quirks);
     jArray<nsHtml5StackNode*,int32_t> getStack();
     jArray<int32_t,int32_t> getTemplateModeStack();
     jArray<nsHtml5StackNode*,int32_t> getListOfActiveFormattingElements();
     nsIContentHandle* getFormPointer();
     nsIContentHandle* getHeadPointer();
     nsIContentHandle* getDeepTreeSurrogateParent();
     int32_t getMode();
     int32_t getOriginalMode();
--- a/parser/html/nsHtml5StreamParser.cpp
+++ b/parser/html/nsHtml5StreamParser.cpp
@@ -215,19 +215,16 @@ nsHtml5StreamParser::nsHtml5StreamParser
   }
 
   // There's a zeroing operator new for everything else
 }
 
 nsHtml5StreamParser::~nsHtml5StreamParser()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-  // mSpeculations may contain StateSnapshot holding StackNodes that we
-  // want to free when the tokenizer ends, so clear the speculations first.
-  mSpeculations.Clear();
   mTokenizer->end();
 #ifdef DEBUG
   {
     mozilla::MutexAutoLock flushTimerLock(mFlushTimerMutex);
     MOZ_ASSERT(!mFlushTimer, "Flush timer was not dropped before dtor!");
   }
   mRequest = nullptr;
   mObserver = nullptr;
--- a/parser/html/nsHtml5TreeBuilder.cpp
+++ b/parser/html/nsHtml5TreeBuilder.cpp
@@ -69,25 +69,22 @@
 
 char16_t nsHtml5TreeBuilder::REPLACEMENT_CHARACTER[] = { 0xfffd };
 static const char* const QUIRKY_PUBLIC_IDS_DATA[] = { "+//silmaril//dtd html pro v0r11 19970101//", "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", "-//as//dtd html 3.0 aswedit + extensions//", "-//ietf//dtd html 2.0 level 1//", "-//ietf//dtd html 2.0 level 2//", "-//ietf//dtd html 2.0 strict level 1//", "-//ietf//dtd html 2.0 strict level 2//", "-//ietf//dtd html 2.0 strict//", "-//ietf//dtd html 2.0//", "-//ietf//dtd html 2.1e//", "-//ietf//dtd html 3.0//", "-//ietf//dtd html 3.2 final//", "-//ietf//dtd html 3.2//", "-//ietf//dtd html 3//", "-//ietf//dtd html level 0//", "-//ietf//dtd html level 1//", "-//ietf//dtd html level 2//", "-//ietf//dtd html level 3//", "-//ietf//dtd html strict level 0//", "-//ietf//dtd html strict level 1//", "-//ietf//dtd html strict level 2//", "-//ietf//dtd html strict level 3//", "-//ietf//dtd html strict//", "-//ietf//dtd html//", "-//metrius//dtd metrius presentational//", "-//microsoft//dtd internet explorer 2.0 html strict//", "-//microsoft//dtd internet explorer 2.0 html//", "-//microsoft//dtd internet explorer 2.0 tables//", "-//microsoft//dtd internet explorer 3.0 html strict//", "-//microsoft//dtd internet explorer 3.0 html//", "-//microsoft//dtd internet explorer 3.0 tables//", "-//netscape comm. corp.//dtd html//", "-//netscape comm. corp.//dtd strict html//", "-//o'reilly and associates//dtd html 2.0//", "-//o'reilly and associates//dtd html extended 1.0//", "-//o'reilly and associates//dtd html extended relaxed 1.0//", "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", "-//spyglass//dtd html 2.0 extended//", "-//sq//dtd html 2.0 hotmetal + extensions//", "-//sun microsystems corp.//dtd hotjava html//", "-//sun microsystems corp.//dtd hotjava strict html//", "-//w3c//dtd html 3 1995-03-24//", "-//w3c//dtd html 3.2 draft//", "-//w3c//dtd html 3.2 final//", "-//w3c//dtd html 3.2//", "-//w3c//dtd html 3.2s draft//", "-//w3c//dtd html 4.0 frameset//", "-//w3c//dtd html 4.0 transitional//", "-//w3c//dtd html experimental 19960712//", "-//w3c//dtd html experimental 970421//", "-//w3c//dtd w3 html//", "-//w3o//dtd w3 html 3.0//", "-//webtechs//dtd mozilla html 2.0//", "-//webtechs//dtd mozilla html//" };
 staticJArray<const char*,int32_t> nsHtml5TreeBuilder::QUIRKY_PUBLIC_IDS = { QUIRKY_PUBLIC_IDS_DATA, MOZ_ARRAY_LENGTH(QUIRKY_PUBLIC_IDS_DATA) };
 void 
 nsHtml5TreeBuilder::startTokenization(nsHtml5Tokenizer* self)
 {
   tokenizer = self;
-  stackNodes = jArray<nsHtml5StackNode*,int32_t>::newJArray(64);
   stack = jArray<nsHtml5StackNode*,int32_t>::newJArray(64);
   templateModeStack = jArray<int32_t,int32_t>::newJArray(64);
   listOfActiveFormattingElements = jArray<nsHtml5StackNode*,int32_t>::newJArray(64);
   needToDropLF = false;
   originalMode = INITIAL;
   templateModePtr = -1;
-  stackNodesIdx = 0;
-  numStackNodes = 0;
   currentPtr = -1;
   listPtr = -1;
   formPointer = nullptr;
   headPointer = nullptr;
   deepTreeSurrogateParent = nullptr;
   start(fragment);
   charBufferLen = 0;
   charBuffer = nullptr;
@@ -101,40 +98,40 @@ nsHtml5TreeBuilder::startTokenization(ns
     }
     if (contextNamespace == kNameSpaceID_SVG) {
       nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_SVG;
       if (nsGkAtoms::title == contextName || nsGkAtoms::desc == contextName ||
           nsGkAtoms::foreignObject == contextName) {
         elementName = nsHtml5ElementName::ELT_FOREIGNOBJECT;
       }
       nsHtml5StackNode* node =
-        createStackNode(elementName, elementName->getCamelCaseName(), elt);
+        new nsHtml5StackNode(elementName, elementName->getCamelCaseName(), elt);
       currentPtr++;
       stack[currentPtr] = node;
       tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::DATA,
                                               contextName);
       mode = FRAMESET_OK;
     } else if (contextNamespace == kNameSpaceID_MathML) {
       nsHtml5ElementName* elementName = nsHtml5ElementName::ELT_MATH;
       if (nsGkAtoms::mi_ == contextName || nsGkAtoms::mo_ == contextName ||
           nsGkAtoms::mn_ == contextName || nsGkAtoms::ms_ == contextName ||
           nsGkAtoms::mtext_ == contextName) {
         elementName = nsHtml5ElementName::ELT_MTEXT;
       } else if (nsGkAtoms::annotation_xml_ == contextName) {
         elementName = nsHtml5ElementName::ELT_ANNOTATION_XML;
       }
       nsHtml5StackNode* node =
-        createStackNode(elementName, elt, elementName->getName(), false);
+        new nsHtml5StackNode(elementName, elt, elementName->getName(), false);
       currentPtr++;
       stack[currentPtr] = node;
       tokenizer->setStateAndEndTagExpectation(nsHtml5Tokenizer::DATA,
                                               contextName);
       mode = FRAMESET_OK;
     } else {
-      nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_HTML, elt);
+      nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_HTML, elt);
       currentPtr++;
       stack[currentPtr] = node;
       if (nsGkAtoms::_template == contextName) {
         pushTemplateMode(IN_TEMPLATE);
       }
       resetTheInsertionMode();
       formPointer = getFormPointerForContext(contextNode);
       if (nsGkAtoms::title == contextName ||
@@ -165,17 +162,17 @@ nsHtml5TreeBuilder::startTokenization(ns
   } else {
     mode = INITIAL;
     if (tokenizer->isViewingXmlSource()) {
       nsIContentHandle* elt = createElement(kNameSpaceID_SVG,
                                             nsGkAtoms::svg,
                                             tokenizer->emptyAttributes(),
                                             nullptr);
       nsHtml5StackNode* node =
-        createStackNode(nsHtml5ElementName::ELT_SVG, nsGkAtoms::svg, elt);
+        new nsHtml5StackNode(nsHtml5ElementName::ELT_SVG, nsGkAtoms::svg, elt);
       currentPtr++;
       stack[currentPtr] = node;
     }
   }
 }
 
 void
 nsHtml5TreeBuilder::doctype(nsIAtom* name,
@@ -606,39 +603,30 @@ void
 nsHtml5TreeBuilder::endTokenization()
 {
   formPointer = nullptr;
   headPointer = nullptr;
   deepTreeSurrogateParent = nullptr;
   templateModeStack = nullptr;
   if (stack) {
     while (currentPtr > -1) {
-      stack[currentPtr]->release(this);
+      stack[currentPtr]->release();
       currentPtr--;
     }
     stack = nullptr;
   }
   if (listOfActiveFormattingElements) {
     while (listPtr > -1) {
       if (listOfActiveFormattingElements[listPtr]) {
-        listOfActiveFormattingElements[listPtr]->release(this);
+        listOfActiveFormattingElements[listPtr]->release();
       }
       listPtr--;
     }
     listOfActiveFormattingElements = nullptr;
   }
-  if (stackNodes) {
-    for (int32_t i = 0; i < numStackNodes; i++) {
-      MOZ_ASSERT(stackNodes[i]->isUnused());
-      delete stackNodes[i];
-    }
-    numStackNodes = 0;
-    stackNodesIdx = 0;
-    stackNodes = nullptr;
-  }
   charBuffer = nullptr;
   end();
 }
 
 void 
 nsHtml5TreeBuilder::startTag(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, bool selfClosing)
 {
   flushCharacters();
@@ -1188,17 +1176,17 @@ nsHtml5TreeBuilder::startTag(nsHtml5Elem
                 nsHtml5StackNode* activeA = listOfActiveFormattingElements[activeAPos];
                 activeA->retain();
                 adoptionAgencyEndTag(nsGkAtoms::a);
                 removeFromStack(activeA);
                 activeAPos = findInListOfActiveFormattingElements(activeA);
                 if (activeAPos != -1) {
                   removeFromListOfActiveFormattingElements(activeAPos);
                 }
-                activeA->release(this);
+                activeA->release();
               }
               reconstructTheActiveFormattingElements();
               appendToCurrentNodeAndPushFormattingElementMayFoster(elementName, attributes);
               attributes = nullptr;
               NS_HTML5_BREAK(starttagloop);
             }
             case B_OR_BIG_OR_CODE_OR_EM_OR_I_OR_S_OR_SMALL_OR_STRIKE_OR_STRONG_OR_TT_OR_U:
             case FONT: {
@@ -3598,29 +3586,29 @@ nsHtml5TreeBuilder::append(nsHtml5StackN
 void 
 nsHtml5TreeBuilder::clearTheListOfActiveFormattingElementsUpToTheLastMarker()
 {
   while (listPtr > -1) {
     if (!listOfActiveFormattingElements[listPtr]) {
       --listPtr;
       return;
     }
-    listOfActiveFormattingElements[listPtr]->release(this);
+    listOfActiveFormattingElements[listPtr]->release();
     --listPtr;
   }
 }
 
 void 
 nsHtml5TreeBuilder::removeFromStack(int32_t pos)
 {
   if (currentPtr == pos) {
     pop();
   } else {
 
-    stack[pos]->release(this);
+    stack[pos]->release();
     nsHtml5ArrayCopy::arraycopy(stack, pos + 1, pos, currentPtr - pos);
     MOZ_ASSERT(debugOnlyClearLastStackSlot());
     currentPtr--;
   }
 }
 
 void 
 nsHtml5TreeBuilder::removeFromStack(nsHtml5StackNode* node)
@@ -3631,27 +3619,27 @@ nsHtml5TreeBuilder::removeFromStack(nsHt
     int32_t pos = currentPtr - 1;
     while (pos >= 0 && stack[pos] != node) {
       pos--;
     }
     if (pos == -1) {
       return;
     }
 
-    node->release(this);
+    node->release();
     nsHtml5ArrayCopy::arraycopy(stack, pos + 1, pos, currentPtr - pos);
     currentPtr--;
   }
 }
 
 void 
 nsHtml5TreeBuilder::removeFromListOfActiveFormattingElements(int32_t pos)
 {
   MOZ_ASSERT(!!listOfActiveFormattingElements[pos]);
-  listOfActiveFormattingElements[pos]->release(this);
+  listOfActiveFormattingElements[pos]->release();
   if (pos == listPtr) {
     MOZ_ASSERT(debugOnlyClearLastListSlot());
     listPtr--;
     return;
   }
   MOZ_ASSERT(pos < listPtr);
   nsHtml5ArrayCopy::arraycopy(listOfActiveFormattingElements, pos + 1, pos, listPtr - pos);
   MOZ_ASSERT(debugOnlyClearLastListSlot());
@@ -3753,38 +3741,38 @@ nsHtml5TreeBuilder::adoptionAgencyEndTag
         continue;
       }
       if (nodePos == furthestBlockPos) {
         bookmark = nodeListPos + 1;
       }
       MOZ_ASSERT(node == listOfActiveFormattingElements[nodeListPos]);
       MOZ_ASSERT(node == stack[nodePos]);
       nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, node->name, node->attributes->cloneAttributes(nullptr), commonAncestor->node);
-      nsHtml5StackNode* newNode = createStackNode(node->getFlags(), node->ns, node->name, clone, node->popName, node->attributes);
+      nsHtml5StackNode* newNode = new nsHtml5StackNode(node->getFlags(), node->ns, node->name, clone, node->popName, node->attributes);
       node->dropAttributes();
       stack[nodePos] = newNode;
       newNode->retain();
       listOfActiveFormattingElements[nodeListPos] = newNode;
-      node->release(this);
-      node->release(this);
+      node->release();
+      node->release();
       node = newNode;
       detachFromParent(lastNode->node);
       appendElement(lastNode->node, node->node);
       lastNode = node;
     }
     if (commonAncestor->isFosterParenting()) {
 
       detachFromParent(lastNode->node);
       insertIntoFosterParent(lastNode->node);
     } else {
       detachFromParent(lastNode->node);
       appendElement(lastNode->node, commonAncestor->node);
     }
     nsIContentHandle* clone = createElement(kNameSpaceID_XHTML, formattingElt->name, formattingElt->attributes->cloneAttributes(nullptr), furthestBlock->node);
-    nsHtml5StackNode* formattingClone = createStackNode(formattingElt->getFlags(), formattingElt->ns, formattingElt->name, clone, formattingElt->popName, formattingElt->attributes);
+    nsHtml5StackNode* formattingClone = new nsHtml5StackNode(formattingElt->getFlags(), formattingElt->ns, formattingElt->name, clone, formattingElt->popName, formattingElt->attributes);
     formattingElt->dropAttributes();
     appendChildrenToNewParent(furthestBlock->node, clone);
     appendElement(clone, furthestBlock->node);
     removeFromListOfActiveFormattingElements(formattingEltListPos);
     insertIntoListOfActiveFormattingElements(formattingClone, bookmark);
     MOZ_ASSERT(formattingEltStackPos < furthestBlockPos);
     removeFromStack(formattingEltStackPos);
     insertIntoStack(formattingClone, furthestBlockPos);
@@ -3905,17 +3893,17 @@ nsHtml5TreeBuilder::addAttributesToHtml(
 }
 
 void 
 nsHtml5TreeBuilder::pushHeadPointerOntoStack()
 {
   MOZ_ASSERT(!!headPointer);
   MOZ_ASSERT(mode == AFTER_HEAD);
 
-  silentPush(createStackNode(nsHtml5ElementName::ELT_HEAD, headPointer));
+  silentPush(new nsHtml5StackNode(nsHtml5ElementName::ELT_HEAD, headPointer));
 }
 
 void 
 nsHtml5TreeBuilder::reconstructTheActiveFormattingElements()
 {
   if (listPtr == -1) {
     return;
   }
@@ -3942,104 +3930,26 @@ nsHtml5TreeBuilder::reconstructTheActive
     nsHtml5StackNode* currentNode = stack[currentPtr];
     nsIContentHandle* clone;
     if (currentNode->isFosterParenting()) {
       clone = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(nullptr));
     } else {
       clone = createElement(kNameSpaceID_XHTML, entry->name, entry->attributes->cloneAttributes(nullptr), currentNode->node);
       appendElement(clone, currentNode->node);
     }
-    nsHtml5StackNode* entryClone = createStackNode(entry->getFlags(), entry->ns, entry->name, clone, entry->popName, entry->attributes);
+    nsHtml5StackNode* entryClone = new nsHtml5StackNode(entry->getFlags(), entry->ns, entry->name, clone, entry->popName, entry->attributes);
     entry->dropAttributes();
     push(entryClone);
     listOfActiveFormattingElements[entryPos] = entryClone;
-    entry->release(this);
+    entry->release();
     entryClone->retain();
   }
 }
 
 void 
-nsHtml5TreeBuilder::notifyUnusedStackNode(int32_t idxInStackNodes)
-{
-  if (idxInStackNodes < stackNodesIdx) {
-    stackNodesIdx = idxInStackNodes;
-  }
-}
-
-nsHtml5StackNode* 
-nsHtml5TreeBuilder::getUnusedStackNode()
-{
-  while (stackNodesIdx < numStackNodes) {
-    if (stackNodes[stackNodesIdx]->isUnused()) {
-      return stackNodes[stackNodesIdx++];
-    }
-    stackNodesIdx++;
-  }
-  if (stackNodesIdx < stackNodes.length) {
-    stackNodes[stackNodesIdx] = new nsHtml5StackNode(stackNodesIdx);
-    numStackNodes++;
-    return stackNodes[stackNodesIdx++];
-  }
-  jArray<nsHtml5StackNode*,int32_t> newStack = jArray<nsHtml5StackNode*,int32_t>::newJArray(stackNodes.length + 64);
-  nsHtml5ArrayCopy::arraycopy(stackNodes, newStack, stackNodes.length);
-  stackNodes = newStack;
-  stackNodes[stackNodesIdx] = new nsHtml5StackNode(stackNodesIdx);
-  numStackNodes++;
-  return stackNodes[stackNodesIdx++];
-}
-
-nsHtml5StackNode* 
-nsHtml5TreeBuilder::createStackNode(int32_t flags, int32_t ns, nsIAtom* name, nsIContentHandle* node, nsIAtom* popName, nsHtml5HtmlAttributes* attributes)
-{
-  nsHtml5StackNode* instance = getUnusedStackNode();
-  instance->setValues(flags, ns, name, node, popName, attributes);
-  return instance;
-}
-
-nsHtml5StackNode* 
-nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName* elementName, nsIContentHandle* node)
-{
-  nsHtml5StackNode* instance = getUnusedStackNode();
-  instance->setValues(elementName, node);
-  return instance;
-}
-
-nsHtml5StackNode* 
-nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsHtml5HtmlAttributes* attributes)
-{
-  nsHtml5StackNode* instance = getUnusedStackNode();
-  instance->setValues(elementName, node, attributes);
-  return instance;
-}
-
-nsHtml5StackNode* 
-nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName)
-{
-  nsHtml5StackNode* instance = getUnusedStackNode();
-  instance->setValues(elementName, node, popName);
-  return instance;
-}
-
-nsHtml5StackNode* 
-nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName* elementName, nsIAtom* popName, nsIContentHandle* node)
-{
-  nsHtml5StackNode* instance = getUnusedStackNode();
-  instance->setValues(elementName, popName, node);
-  return instance;
-}
-
-nsHtml5StackNode* 
-nsHtml5TreeBuilder::createStackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName, bool markAsIntegrationPoint)
-{
-  nsHtml5StackNode* instance = getUnusedStackNode();
-  instance->setValues(elementName, node, popName, markAsIntegrationPoint);
-  return instance;
-}
-
-void 
 nsHtml5TreeBuilder::insertIntoFosterParent(nsIContentHandle* child)
 {
   int32_t tablePos = findLastOrRoot(nsHtml5TreeBuilder::TABLE);
   int32_t templatePos = findLastOrRoot(nsHtml5TreeBuilder::TEMPLATE);
   if (templatePos >= tablePos) {
     appendElement(child, stack[templatePos]->node);
     return;
   }
@@ -4086,44 +3996,44 @@ nsHtml5TreeBuilder::popTemplateMode()
 
 void 
 nsHtml5TreeBuilder::pop()
 {
   nsHtml5StackNode* node = stack[currentPtr];
   MOZ_ASSERT(debugOnlyClearLastStackSlot());
   currentPtr--;
   elementPopped(node->ns, node->popName, node->node);
-  node->release(this);
+  node->release();
 }
 
 void 
 nsHtml5TreeBuilder::silentPop()
 {
   nsHtml5StackNode* node = stack[currentPtr];
   MOZ_ASSERT(debugOnlyClearLastStackSlot());
   currentPtr--;
-  node->release(this);
+  node->release();
 }
 
 void 
 nsHtml5TreeBuilder::popOnEof()
 {
   nsHtml5StackNode* node = stack[currentPtr];
   MOZ_ASSERT(debugOnlyClearLastStackSlot());
   currentPtr--;
   markMalformedIfScript(node->node);
   elementPopped(node->ns, node->popName, node->node);
-  node->release(this);
+  node->release();
 }
 
 void 
 nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush(nsHtml5HtmlAttributes* attributes)
 {
   nsIContentHandle* elt = createHtmlElementSetAsRoot(attributes);
-  nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_HTML, elt);
+  nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_HTML, elt);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendHtmlElementToDocumentAndPush()
 {
   appendHtmlElementToDocumentAndPush(tokenizer->emptyAttributes());
 }
@@ -4131,17 +4041,17 @@ nsHtml5TreeBuilder::appendHtmlElementToD
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushHeadElement(nsHtml5HtmlAttributes* attributes)
 {
   nsIContentHandle* currentNode = stack[currentPtr]->node;
   nsIContentHandle* elt =
     createElement(kNameSpaceID_XHTML, nsGkAtoms::head, attributes, currentNode);
   appendElement(elt, currentNode);
   headPointer = elt;
-  nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_HEAD, elt);
+  nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_HEAD, elt);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushBodyElement(nsHtml5HtmlAttributes* attributes)
 {
   appendToCurrentNodeAndPushElement(nsHtml5ElementName::ELT_BODY, attributes);
 }
@@ -4164,17 +4074,17 @@ nsHtml5TreeBuilder::appendToCurrentNodeA
   } else {
     elt = createElement(
       kNameSpaceID_XHTML, nsGkAtoms::form, attributes, current->node);
     appendElement(elt, current->node);
   }
   if (!isTemplateContents()) {
     formPointer = elt;
   }
-  nsHtml5StackNode* node = createStackNode(nsHtml5ElementName::ELT_FORM, elt);
+  nsHtml5StackNode* node = new nsHtml5StackNode(nsHtml5ElementName::ELT_FORM, elt);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushFormattingElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
 {
   nsHtml5HtmlAttributes* clone = attributes->cloneAttributes(nullptr);
   nsIContentHandle* elt;
@@ -4183,50 +4093,50 @@ nsHtml5TreeBuilder::appendToCurrentNodeA
 
     elt = createAndInsertFosterParentedElement(
       kNameSpaceID_XHTML, elementName->getName(), attributes);
   } else {
     elt = createElement(
       kNameSpaceID_XHTML, elementName->getName(), attributes, current->node);
     appendElement(elt, current->node);
   }
-  nsHtml5StackNode* node = createStackNode(elementName, elt, clone);
+  nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, clone);
   push(node);
   append(node);
   node->retain();
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElement(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
 {
   nsIContentHandle* currentNode = stack[currentPtr]->node;
   nsIContentHandle* elt = createElement(
     kNameSpaceID_XHTML, elementName->getName(), attributes, currentNode);
   appendElement(elt, currentNode);
   if (nsHtml5ElementName::ELT_TEMPLATE == elementName) {
     elt = getDocumentFragmentForTemplate(elt);
   }
-  nsHtml5StackNode* node = createStackNode(elementName, elt);
+  nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
 {
   nsIAtom* popName = elementName->getName();
   nsIContentHandle* elt;
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
     elt = createAndInsertFosterParentedElement(kNameSpaceID_XHTML, popName, attributes);
   } else {
     elt = createElement(kNameSpaceID_XHTML, popName, attributes, current->node);
     appendElement(elt, current->node);
   }
-  nsHtml5StackNode* node = createStackNode(elementName, elt, popName);
+  nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, popName);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFosterMathML(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes)
 {
   nsIAtom* popName = elementName->getName();
   bool markAsHtmlIntegrationPoint = false;
@@ -4237,17 +4147,17 @@ nsHtml5TreeBuilder::appendToCurrentNodeA
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
     elt = createAndInsertFosterParentedElement(kNameSpaceID_MathML, popName, attributes);
   } else {
     elt = createElement(kNameSpaceID_MathML, popName, attributes, current->node);
     appendElement(elt, current->node);
   }
-  nsHtml5StackNode* node = createStackNode(elementName, elt, popName, markAsHtmlIntegrationPoint);
+  nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt, popName, markAsHtmlIntegrationPoint);
   push(node);
 }
 
 bool 
 nsHtml5TreeBuilder::annotationXmlEncodingPermitsHtml(nsHtml5HtmlAttributes* attributes)
 {
   nsHtml5String encoding =
     attributes->getValue(nsHtml5AttributeName::ATTR_ENCODING);
@@ -4265,17 +4175,17 @@ nsHtml5TreeBuilder::appendToCurrentNodeA
   nsHtml5StackNode* current = stack[currentPtr];
   if (current->isFosterParenting()) {
 
     elt = createAndInsertFosterParentedElement(kNameSpaceID_SVG, popName, attributes);
   } else {
     elt = createElement(kNameSpaceID_SVG, popName, attributes, current->node);
     appendElement(elt, current->node);
   }
-  nsHtml5StackNode* node = createStackNode(elementName, popName, elt);
+  nsHtml5StackNode* node = new nsHtml5StackNode(elementName, popName, elt);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendToCurrentNodeAndPushElementMayFoster(nsHtml5ElementName* elementName, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
 {
   nsIContentHandle* elt;
   nsIContentHandle* formOwner = !form || fragment || isTemplateContents() ? nullptr : form;
@@ -4287,17 +4197,17 @@ nsHtml5TreeBuilder::appendToCurrentNodeA
   } else {
     elt = createElement(kNameSpaceID_XHTML,
                         elementName->getName(),
                         attributes,
                         formOwner,
                         current->node);
     appendElement(elt, current->node);
   }
-  nsHtml5StackNode* node = createStackNode(elementName, elt);
+  nsHtml5StackNode* node = new nsHtml5StackNode(elementName, elt);
   push(node);
 }
 
 void 
 nsHtml5TreeBuilder::appendVoidElementToCurrentMayFoster(nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form)
 {
   nsIContentHandle* elt;
   nsIContentHandle* formOwner = !form || fragment || isTemplateContents() ? nullptr : form;
@@ -4493,37 +4403,37 @@ nsHtml5TreeBuilder::charBufferContainsNo
 
 nsAHtml5TreeBuilderState* 
 nsHtml5TreeBuilder::newSnapshot()
 {
   jArray<nsHtml5StackNode*,int32_t> listCopy = jArray<nsHtml5StackNode*,int32_t>::newJArray(listPtr + 1);
   for (int32_t i = 0; i < listCopy.length; i++) {
     nsHtml5StackNode* node = listOfActiveFormattingElements[i];
     if (node) {
-      nsHtml5StackNode* newNode = createStackNode(node->getFlags(), node->ns, node->name, node->node, node->popName, node->attributes->cloneAttributes(nullptr));
+      nsHtml5StackNode* newNode = new nsHtml5StackNode(node->getFlags(), node->ns, node->name, node->node, node->popName, node->attributes->cloneAttributes(nullptr));
       listCopy[i] = newNode;
     } else {
       listCopy[i] = nullptr;
     }
   }
   jArray<nsHtml5StackNode*,int32_t> stackCopy = jArray<nsHtml5StackNode*,int32_t>::newJArray(currentPtr + 1);
   for (int32_t i = 0; i < stackCopy.length; i++) {
     nsHtml5StackNode* node = stack[i];
     int32_t listIndex = findInListOfActiveFormattingElements(node);
     if (listIndex == -1) {
-      nsHtml5StackNode* newNode = createStackNode(node->getFlags(), node->ns, node->name, node->node, node->popName, nullptr);
+      nsHtml5StackNode* newNode = new nsHtml5StackNode(node->getFlags(), node->ns, node->name, node->node, node->popName, nullptr);
       stackCopy[i] = newNode;
     } else {
       stackCopy[i] = listCopy[listIndex];
       stackCopy[i]->retain();
     }
   }
   jArray<int32_t,int32_t> templateModeStackCopy = jArray<int32_t,int32_t>::newJArray(templateModePtr + 1);
   nsHtml5ArrayCopy::arraycopy(templateModeStack, templateModeStackCopy, templateModeStackCopy.length);
-  return new nsHtml5StateSnapshot(this, stackCopy, listCopy, templateModeStackCopy, formPointer, headPointer, deepTreeSurrogateParent, mode, originalMode, framesetOk, needToDropLF, quirks);
+  return new nsHtml5StateSnapshot(stackCopy, listCopy, templateModeStackCopy, formPointer, headPointer, deepTreeSurrogateParent, mode, originalMode, framesetOk, needToDropLF, quirks);
 }
 
 bool 
 nsHtml5TreeBuilder::snapshotMatches(nsAHtml5TreeBuilderState* snapshot)
 {
   jArray<nsHtml5StackNode*,int32_t> stackCopy = snapshot->getStack();
   int32_t stackLen = snapshot->getStackLength();
   jArray<nsHtml5StackNode*,int32_t> listCopy = snapshot->getListOfActiveFormattingElements();
@@ -4562,48 +4472,48 @@ nsHtml5TreeBuilder::loadState(nsAHtml5Tr
   jArray<nsHtml5StackNode*,int32_t> stackCopy = snapshot->getStack();
   int32_t stackLen = snapshot->getStackLength();
   jArray<nsHtml5StackNode*,int32_t> listCopy = snapshot->getListOfActiveFormattingElements();
   int32_t listLen = snapshot->getListOfActiveFormattingElementsLength();
   jArray<int32_t,int32_t> templateModeStackCopy = snapshot->getTemplateModeStack();
   int32_t templateModeStackLen = snapshot->getTemplateModeStackLength();
   for (int32_t i = 0; i <= listPtr; i++) {
     if (listOfActiveFormattingElements[i]) {
-      listOfActiveFormattingElements[i]->release(this);
+      listOfActiveFormattingElements[i]->release();
     }
   }
   if (listOfActiveFormattingElements.length < listLen) {
     listOfActiveFormattingElements = jArray<nsHtml5StackNode*,int32_t>::newJArray(listLen);
   }
   listPtr = listLen - 1;
   for (int32_t i = 0; i <= currentPtr; i++) {
-    stack[i]->release(this);
+    stack[i]->release();
   }
   if (stack.length < stackLen) {
     stack = jArray<nsHtml5StackNode*,int32_t>::newJArray(stackLen);
   }
   currentPtr = stackLen - 1;
   if (templateModeStack.length < templateModeStackLen) {
     templateModeStack = jArray<int32_t,int32_t>::newJArray(templateModeStackLen);
   }
   templateModePtr = templateModeStackLen - 1;
   for (int32_t i = 0; i < listLen; i++) {
     nsHtml5StackNode* node = listCopy[i];
     if (node) {
-      nsHtml5StackNode* newNode = createStackNode(node->getFlags(), node->ns, nsHtml5Portability::newLocalFromLocal(node->name, interner), node->node, nsHtml5Portability::newLocalFromLocal(node->popName, interner), node->attributes->cloneAttributes(nullptr));
+      nsHtml5StackNode* newNode = new nsHtml5StackNode(node->getFlags(), node->ns, nsHtml5Portability::newLocalFromLocal(node->name, interner), node->node, nsHtml5Portability::newLocalFromLocal(node->popName, interner), node->attributes->cloneAttributes(nullptr));
       listOfActiveFormattingElements[i] = newNode;
     } else {
       listOfActiveFormattingElements[i] = nullptr;
     }
   }
   for (int32_t i = 0; i < stackLen; i++) {
     nsHtml5StackNode* node = stackCopy[i];
     int32_t listIndex = findInArray(node, listCopy);
     if (listIndex == -1) {
-      nsHtml5StackNode* newNode = createStackNode(node->getFlags(), node->ns, nsHtml5Portability::newLocalFromLocal(node->name, interner), node->node, nsHtml5Portability::newLocalFromLocal(node->popName, interner), nullptr);
+      nsHtml5StackNode* newNode = new nsHtml5StackNode(node->getFlags(), node->ns, nsHtml5Portability::newLocalFromLocal(node->name, interner), node->node, nsHtml5Portability::newLocalFromLocal(node->popName, interner), nullptr);
       stack[i] = newNode;
     } else {
       stack[i] = listOfActiveFormattingElements[listIndex];
       stack[i]->retain();
     }
   }
   nsHtml5ArrayCopy::arraycopy(templateModeStackCopy, templateModeStack, templateModeStackLen);
   formPointer = snapshot->getFormPointer();
--- a/parser/html/nsHtml5TreeBuilder.h
+++ b/parser/html/nsHtml5TreeBuilder.h
@@ -296,19 +296,16 @@ class nsHtml5TreeBuilder : public nsAHtm
     bool scriptingEnabled;
     bool needToDropLF;
     bool fragment;
     nsIAtom* contextName;
     int32_t contextNamespace;
     nsIContentHandle* contextNode;
     autoJArray<int32_t,int32_t> templateModeStack;
     int32_t templateModePtr;
-    autoJArray<nsHtml5StackNode*,int32_t> stackNodes;
-    int32_t stackNodesIdx;
-    int32_t numStackNodes;
     autoJArray<nsHtml5StackNode*,int32_t> stack;
     int32_t currentPtr;
     autoJArray<nsHtml5StackNode*,int32_t> listOfActiveFormattingElements;
     int32_t listPtr;
     nsIContentHandle* formPointer;
     nsIContentHandle* headPointer;
     nsIContentHandle* deepTreeSurrogateParent;
   protected:
@@ -399,26 +396,16 @@ class nsHtml5TreeBuilder : public nsAHtm
     int32_t findInListOfActiveFormattingElementsContainsBetweenEndAndLastMarker(nsIAtom* name);
     void maybeForgetEarlierDuplicateFormattingElement(nsIAtom* name, nsHtml5HtmlAttributes* attributes);
     int32_t findLastOrRoot(nsIAtom* name);
     int32_t findLastOrRoot(int32_t group);
     bool addAttributesToBody(nsHtml5HtmlAttributes* attributes);
     void addAttributesToHtml(nsHtml5HtmlAttributes* attributes);
     void pushHeadPointerOntoStack();
     void reconstructTheActiveFormattingElements();
-  public:
-    void notifyUnusedStackNode(int32_t idxInStackNodes);
-  private:
-    nsHtml5StackNode* getUnusedStackNode();
-    nsHtml5StackNode* createStackNode(int32_t flags, int32_t ns, nsIAtom* name, nsIContentHandle* node, nsIAtom* popName, nsHtml5HtmlAttributes* attributes);
-    nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName, nsIContentHandle* node);
-    nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsHtml5HtmlAttributes* attributes);
-    nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName);
-    nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName, nsIAtom* popName, nsIContentHandle* node);
-    nsHtml5StackNode* createStackNode(nsHtml5ElementName* elementName, nsIContentHandle* node, nsIAtom* popName, bool markAsIntegrationPoint);
     void insertIntoFosterParent(nsIContentHandle* child);
     nsIContentHandle* createAndInsertFosterParentedElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes);
     nsIContentHandle* createAndInsertFosterParentedElement(int32_t ns, nsIAtom* name, nsHtml5HtmlAttributes* attributes, nsIContentHandle* form);
     bool isInStack(nsHtml5StackNode* node);
     void popTemplateMode();
     void pop();
     void silentPop();
     void popOnEof();