Backed out changeset 4465b8d521ee (bug 1286911) for asserting !strBufLen (strBufLen not reset after previous use!), at nsHtml5Tokenizer.h:173. r=backout on a CLOSED TREE
authorSebastian Hengst <archaeopteryx@coole-files.de>
Tue, 27 Sep 2016 13:49:30 +0200
changeset 315444 e329a7efecec6e6099c85037c87fbce65cad5728
parent 315443 4d031de3816579a8324024de86c6d3bae0d333ee
child 315445 2026d893a981db03e6a37bd19302e5c0ab66ea17
push id30750
push usercbook@mozilla.com
push dateWed, 28 Sep 2016 13:57:20 +0000
treeherdermozilla-central@b1d60f2f68c7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1286911
milestone52.0a1
backs out4465b8d521eecc6d6d5d6142d1fd544160354ba2
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 4465b8d521ee (bug 1286911) for asserting !strBufLen (strBufLen not reset after previous use!), at nsHtml5Tokenizer.h:173. r=backout on a CLOSED TREE
parser/html/javasrc/HtmlAttributes.java
parser/html/javasrc/Tokenizer.java
parser/html/nsHtml5Tokenizer.cpp
parser/html/nsHtml5Tokenizer.h
parser/html/nsHtml5TreeBuilderCppSupplement.h
--- a/parser/html/javasrc/HtmlAttributes.java
+++ b/parser/html/javasrc/HtmlAttributes.java
@@ -57,17 +57,17 @@ public final class HtmlAttributes implem
 
     private int mode;
 
     private int length;
 
     private @Auto AttributeName[] names;
 
     private @Auto String[] values; // XXX perhaps make this @NoLength?
-    
+
     // CPPONLY: private @Auto int[] lines; // XXX perhaps make this @NoLength?
 
     // [NOCPP[
 
     private String idValue;
 
     private int xmlnsLength;
 
--- a/parser/html/javasrc/Tokenizer.java
+++ b/parser/html/javasrc/Tokenizer.java
@@ -812,101 +812,87 @@ public class Tokenizer implements Locato
             // ]NOCPP]
             return HtmlAttributes.EMPTY_ATTRIBUTES;
             // [NOCPP[
         }
         // ]NOCPP]
     }
 
     @Inline private void appendCharRefBuf(char c) {
-        // CPPONLY: assert charRefBufLen < charRefBuf.length:
-        // CPPONLY:     "RELEASE: Attempted to overrun charRefBuf!";
         charRefBuf[charRefBufLen++] = c;
     }
 
+    @Inline private void clearCharRefBufAndAppend(char c) {
+        charRefBuf[0] = c;
+        charRefBufLen = 1;
+    }
+
     private void emitOrAppendCharRefBuf(int returnState) throws SAXException {
         if ((returnState & DATA_AND_RCDATA_MASK) != 0) {
             appendCharRefBufToStrBuf();
         } else {
             if (charRefBufLen > 0) {
                 tokenHandler.characters(charRefBuf, 0, charRefBufLen);
-                charRefBufLen = 0;
             }
         }
     }
 
-    @Inline private void clearStrBufAfterUse() {
-        strBufLen = 0;
-    }
-
-    @Inline private void clearStrBufBeforeUse() {
-        assert strBufLen == 0: "strBufLen not reset after previous use!";
-        strBufLen = 0; // no-op in the absence of bugs
-    }
-
-    @Inline private void clearStrBufAfterOneHyphen() {
-        assert strBufLen == 1: "strBufLen length not one!";
-        assert strBuf[0] == '-': "strBuf does not start with a hyphen!";
+    @Inline private void clearStrBufAndAppend(char c) {
+        strBuf[0] = c;
+        strBufLen = 1;
+    }
+
+    @Inline private void clearStrBuf() {
         strBufLen = 0;
     }
 
     /**
      * Appends to the buffer.
      * 
      * @param c
      *            the UTF-16 code unit to append
      */
-    @Inline private void appendStrBuf(char c) {
-        // CPPONLY: assert strBufLen < strBuf.length: "Previous buffer length insufficient.";
-        // CPPONLY: if (strBufLen == strBuf.length) {
-        // CPPONLY:     if (!EnsureBufferSpace(1)) {
-        // CPPONLY:         assert false: "RELEASE: Unable to recover from buffer reallocation failure";
-        // CPPONLY:     } // TODO: Add telemetry when outer if fires but inner does not
-        // CPPONLY: }
+    private void appendStrBuf(char c) {
         strBuf[strBufLen++] = c;
     }
 
     /**
      * The buffer as a String. Currently only used for error reporting.
      * 
      * <p>
      * C++ memory note: The return value must be released.
      * 
      * @return the buffer as a string
      */
     protected String strBufToString() {
-        String str = Portability.newStringFromBuffer(strBuf, 0, strBufLen
+        return Portability.newStringFromBuffer(strBuf, 0, strBufLen
             // CPPONLY: , tokenHandler
         );
-        clearStrBufAfterUse();
-        return str;
     }
 
     /**
      * Returns the buffer as a local name. The return value is released in
      * emitDoctypeToken().
      * 
      * @return the buffer as local name
      */
     private void strBufToDoctypeName() {
         doctypeName = Portability.newLocalNameFromBuffer(strBuf, 0, strBufLen,
                 interner);
-        clearStrBufAfterUse();
     }
 
     /**
      * Emits the buffer as character tokens.
      * 
      * @throws SAXException
      *             if the token handler threw
      */
     private void emitStrBuf() throws SAXException {
         if (strBufLen > 0) {
             tokenHandler.characters(strBuf, 0, strBufLen);
-            clearStrBufAfterUse();
         }
     }
 
     @Inline private void appendSecondHyphenToBogusComment() throws SAXException {
         // [NOCPP[
         switch (commentPolicy) {
             case ALTER_INFOSET:
                 appendStrBuf(' ');
@@ -943,18 +929,16 @@ public class Tokenizer implements Locato
 
     @Inline private void adjustDoubleHyphenAndAppendToStrBufAndErr(char c)
             throws SAXException {
         errConsecutiveHyphens();
         // [NOCPP[
         switch (commentPolicy) {
             case ALTER_INFOSET:
                 strBufLen--;
-                // WARNING!!! This expands the worst case of the buffer length
-                // given the length of input!
                 appendStrBuf(' ');
                 appendStrBuf('-');
                 // FALLTHROUGH
             case ALLOW:
                 warn("The document is not mappable to XML 1.0 due to two consecutive hyphens in a comment.");
                 // ]NOCPP]
                 appendStrBuf(c);
                 // [NOCPP[
@@ -962,33 +946,31 @@ public class Tokenizer implements Locato
             case FATAL:
                 fatal("The document is not mappable to XML 1.0 due to two consecutive hyphens in a comment.");
                 break;
         }
         // ]NOCPP]
     }
 
     private void appendStrBuf(@NoLength char[] buffer, int offset, int length) {
-        int newLen = strBufLen + length;
-        // CPPONLY: assert newLen <= strBuf.length: "Previous buffer length insufficient.";
-        // CPPONLY: if (strBuf.length < newLen) {
-        // CPPONLY:     if (!EnsureBufferSpace(length)) {
-        // CPPONLY:         assert false: "RELEASE: Unable to recover from buffer reallocation failure";
-        // CPPONLY:     } // TODO: Add telemetry when outer if fires but inner does not
-        // CPPONLY: }
+        int reqLen = strBufLen + length;
+        if (strBuf.length < reqLen) {
+            char[] newBuf = new char[reqLen + (reqLen >> 1)];
+            System.arraycopy(strBuf, 0, newBuf, 0, strBuf.length);
+            strBuf = newBuf;
+        }
         System.arraycopy(buffer, offset, strBuf, strBufLen, length);
-        strBufLen = newLen;
+        strBufLen = reqLen;
     }
 
     /**
      * Append the contents of the char reference buffer to the main one.
      */
     @Inline private void appendCharRefBufToStrBuf() {
         appendStrBuf(charRefBuf, 0, charRefBufLen);
-        charRefBufLen = 0;
     }
 
     /**
      * Emits the current comment token.
      * 
      * @param pos
      *            TODO
      * 
@@ -999,17 +981,16 @@ public class Tokenizer implements Locato
         // [NOCPP[
         if (wantsComments) {
             // ]NOCPP]
             tokenHandler.comment(strBuf, 0, strBufLen
                     - provisionalHyphens);
             // [NOCPP[
         }
         // ]NOCPP]
-        clearStrBufAfterUse();
         cstart = pos + 1;
     }
 
     /**
      * Flushes coalesced character tokens.
      * 
      * @param buf
      *            TODO
@@ -1087,17 +1068,16 @@ public class Tokenizer implements Locato
         }
         SAXParseException spe = new SAXParseException(message, this);
         errorHandler.warning(spe);
     }
 
     private void strBufToElementNameString() {
         tagName = ElementName.elementNameByBuffer(strBuf, 0, strBufLen,
                 interner);
-        clearStrBufAfterUse();
     }
 
     private int emitCurrentTagToken(boolean selfClosing, int pos)
             throws SAXException {
         cstart = pos + 1;
         maybeErrSlashInEndTag(selfClosing);
         stateSave = Tokenizer.DATA;
         HtmlAttributes attrs = (attributes == null ? HtmlAttributes.EMPTY_ATTRIBUTES
@@ -1139,17 +1119,16 @@ public class Tokenizer implements Locato
     }
 
     private void attributeNameComplete() throws SAXException {
         attributeName = AttributeName.nameByBuffer(strBuf, 0, strBufLen
         // [NOCPP[
                 , namePolicy != XmlViolationPolicy.ALLOW
                 // ]NOCPP]
                 , interner);
-        clearStrBufAfterUse();
 
         if (attributes == null) {
             attributes = new HtmlAttributes(mappingLangToXmlLang);
         }
 
         /*
          * When the user agent leaves the attribute name state (and before
          * emitting the tag token, if appropriate), the complete attribute's
@@ -1206,18 +1185,16 @@ public class Tokenizer implements Locato
                 // ]NOCPP]
                 // CPPONLY: , attributeLine
                 );
                 // [NOCPP[
             }
             // ]NOCPP]
             attributeName = null; // attributeName has been adopted by the
             // |attributes| object
-        } else {
-            clearStrBufAfterUse();
         }
     }
 
     private void addAttributeWithValue() throws SAXException {
         // [NOCPP[
         if (metaBoundaryPassed && ElementName.META == tagName
                 && AttributeName.CHARSET == attributeName) {
             err("A \u201Ccharset\u201D attribute on a \u201Cmeta\u201D element found after the first 512 bytes.");
@@ -1356,24 +1333,16 @@ public class Tokenizer implements Locato
     // [NOCPP[
     private void ensureBufferSpace(int inputLength) throws SAXException {
         // Add 2 to account for emissions of LT_GT, LT_SOLIDUS and RSQB_RSQB.
         // Adding to the general worst case instead of only the
         // TreeBuilder-exposed worst case to avoid re-introducing a bug when
         // unifying the tokenizer and tree builder buffers in the future.
         int worstCase = strBufLen + inputLength + charRefBufLen + 2;
         tokenHandler.ensureBufferSpace(worstCase);
-        if (commentPolicy == XmlViolationPolicy.ALTER_INFOSET) {
-            // When altering infoset, if the comment contents are consecutive
-            // hyphens, each hyphen generates a space, too. These buffer
-            // contents never get emitted as characters() to the tokenHandler,
-            // which is why this calculation happens after the call to 
-            // ensureBufferSpace on tokenHandler.
-            worstCase *= 2;
-        }
         if (strBuf == null) {
             // Add an arbitrary small value to avoid immediate reallocation
             // once there are a few characters in the buffer.
             strBuf = new char[worstCase + 128];
         } else if (worstCase > strBuf.length) {
             // HotSpot reportedly allocates memory with 8-byte accuracy, so
             // there's no point in trying to do math here to avoid slop.
             // Maybe we should add some small constant to worstCase here
@@ -1472,18 +1441,17 @@ public class Tokenizer implements Locato
                         }
                         switch (c) {
                             case '&':
                                 /*
                                  * U+0026 AMPERSAND (&) Switch to the character
                                  * reference in data state.
                                  */
                                 flushChars(buf, pos);
-                                assert charRefBufLen == 0: "charRefBufLen not reset after previous use!";
-                                appendCharRefBuf(c);
+                                clearCharRefBufAndAppend(c);
                                 setAdditionalAndRememberAmpersandLocation('\u0000');
                                 returnState = state;
                                 state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos);
                                 continue stateloop;
                             case '<':
                                 /*
                                  * U+003C LESS-THAN SIGN (<) Switch to the tag
                                  * open state.
@@ -1533,18 +1501,17 @@ public class Tokenizer implements Locato
                              * token,
                              */
                             endTag = false;
                             /*
                              * set its tag name to the lowercase version of the
                              * input character (add 0x0020 to the character's
                              * code point),
                              */
-                            clearStrBufBeforeUse();
-                            appendStrBuf((char) (c + 0x20));
+                            clearStrBufAndAppend((char) (c + 0x20));
                             /* then switch to the tag name state. */
                             state = transition(state, Tokenizer.TAG_NAME, reconsume, pos);
                             /*
                              * (Don't emit the token yet; further details will
                              * be filled in before it is emitted.)
                              */
                             break tagopenloop;
                             // continue stateloop;
@@ -1553,18 +1520,17 @@ public class Tokenizer implements Locato
                              * U+0061 LATIN SMALL LETTER A through to U+007A
                              * LATIN SMALL LETTER Z Create a new start tag
                              * token,
                              */
                             endTag = false;
                             /*
                              * set its tag name to the input character,
                              */
-                            clearStrBufBeforeUse();
-                            appendStrBuf(c);
+                            clearStrBufAndAppend(c);
                             /* then switch to the tag name state. */
                             state = transition(state, Tokenizer.TAG_NAME, reconsume, pos);
                             /*
                              * (Don't emit the token yet; further details will
                              * be filled in before it is emitted.)
                              */
                             break tagopenloop;
                             // continue stateloop;
@@ -1594,18 +1560,17 @@ public class Tokenizer implements Locato
                                 // CPPONLY: }
                                 /*
                                  * U+003F QUESTION MARK (?) Parse error.
                                  */
                                 errProcessingInstruction();
                                 /*
                                  * Switch to the bogus comment state.
                                  */
-                                clearStrBufBeforeUse();
-                                appendStrBuf(c);
+                                clearStrBufAndAppend(c);
                                 state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
                                 continue stateloop;
                             case '>':
                                 /*
                                  * U+003E GREATER-THAN SIGN (>) Parse error.
                                  */
                                 errLtGt();
                                 /*
@@ -1798,18 +1763,17 @@ public class Tokenizer implements Locato
                                      */
                                     c += 0x20;
                                 }
                                 // CPPONLY: attributeLine = line;
                                 /*
                                  * Set that attribute's name to the current
                                  * input character,
                                  */
-                                clearStrBufBeforeUse();
-                                appendStrBuf(c);
+                                clearStrBufAndAppend(c);
                                 /*
                                  * and its value to the empty string.
                                  */
                                 // Will do later.
                                 /*
                                  * Switch to the attribute name state.
                                  */
                                 state = transition(state, Tokenizer.ATTRIBUTE_NAME, reconsume, pos);
@@ -1945,39 +1909,39 @@ public class Tokenizer implements Locato
                                  */
                                 continue;
                             case '"':
                                 /*
                                  * U+0022 QUOTATION MARK (") Switch to the
                                  * attribute value (double-quoted) state.
                                  */
                                 // CPPONLY: attributeLine = line;
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 state = transition(state, Tokenizer.ATTRIBUTE_VALUE_DOUBLE_QUOTED, reconsume, pos);
                                 break beforeattributevalueloop;
                             // continue stateloop;
                             case '&':
                                 /*
                                  * U+0026 AMPERSAND (&) Switch to the attribute
                                  * value (unquoted) state and reconsume this
                                  * input character.
                                  */
                                 // CPPONLY: attributeLine = line;
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 reconsume = true;
                                 state = transition(state, Tokenizer.ATTRIBUTE_VALUE_UNQUOTED, reconsume, pos);
                                 noteUnquotedAttributeValue();
                                 continue stateloop;
                             case '\'':
                                 /*
                                  * U+0027 APOSTROPHE (') Switch to the attribute
                                  * value (single-quoted) state.
                                  */
                                 // CPPONLY: attributeLine = line;
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 state = transition(state, Tokenizer.ATTRIBUTE_VALUE_SINGLE_QUOTED, reconsume, pos);
                                 continue stateloop;
                             case '>':
                                 /*
                                  * U+003E GREATER-THAN SIGN (>) Parse error.
                                  */
                                 errAttributeValueMissing();
                                 /*
@@ -2011,18 +1975,17 @@ public class Tokenizer implements Locato
                                 // [NOCPP[
                                 errHtml4NonNameInUnquotedAttribute(c);
                                 // ]NOCPP]
                                 /*
                                  * Anything else Append the current input
                                  * character to the current attribute's value.
                                  */
                                 // CPPONLY: attributeLine = line;
-                                clearStrBufBeforeUse();
-                                appendStrBuf(c);
+                                clearStrBufAndAppend(c);
                                 /*
                                  * Switch to the attribute value (unquoted)
                                  * state.
                                  */
 
                                 state = transition(state, Tokenizer.ATTRIBUTE_VALUE_UNQUOTED, reconsume, pos);
                                 noteUnquotedAttributeValue();
                                 continue stateloop;
@@ -2055,18 +2018,17 @@ public class Tokenizer implements Locato
                             // continue stateloop;
                             case '&':
                                 /*
                                  * U+0026 AMPERSAND (&) Switch to the character
                                  * reference in attribute value state, with the
                                  * additional allowed character being U+0022
                                  * QUOTATION MARK (").
                                  */
-                                assert charRefBufLen == 0: "charRefBufLen not reset after previous use!";
-                                appendCharRefBuf(c);
+                                clearCharRefBufAndAppend(c);
                                 setAdditionalAndRememberAmpersandLocation('\"');
                                 returnState = state;
                                 state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos);
                                 continue stateloop;
                             case '\r':
                                 appendStrBufCarriageReturn();
                                 break stateloop;
                             case '\n':
@@ -2225,18 +2187,17 @@ public class Tokenizer implements Locato
                                 continue stateloop;
                             case '&':
                                 /*
                                  * U+0026 AMPERSAND (&) Switch to the character
                                  * reference in attribute value state, with the
                                  * additional allowed character being U+003E
                                  * GREATER-THAN SIGN (>)
                                  */
-                                assert charRefBufLen == 0: "charRefBufLen not reset after previous use!";
-                                appendCharRefBuf(c);
+                                clearCharRefBufAndAppend(c);
                                 setAdditionalAndRememberAmpersandLocation('>');
                                 returnState = state;
                                 state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos);
                                 continue stateloop;
                             case '>':
                                 /*
                                  * U+003E GREATER-THAN SIGN (>) Emit the current
                                  * tag token.
@@ -2365,18 +2326,17 @@ public class Tokenizer implements Locato
                                      * 0x0020 to the character's code point)
                                      */
                                     c += 0x20;
                                 }
                                 /*
                                  * Set that attribute's name to the current
                                  * input character,
                                  */
-                                clearStrBufBeforeUse();
-                                appendStrBuf(c);
+                                clearStrBufAndAppend(c);
                                 /*
                                  * and its value to the empty string.
                                  */
                                 // Will do later.
                                 /*
                                  * Switch to the attribute name state.
                                  */
                                 state = transition(state, Tokenizer.ATTRIBUTE_NAME, reconsume, pos);
@@ -2412,57 +2372,54 @@ public class Tokenizer implements Locato
                          * 
                          * Otherwise, is is a parse error. Switch to the bogus
                          * comment state. The next character that is consumed,
                          * if any, is the first character that will be in the
                          * comment.
                          */
                         switch (c) {
                             case '-':
-                                clearStrBufBeforeUse();
-                                appendStrBuf(c);
+                                clearStrBufAndAppend(c);
                                 state = transition(state, Tokenizer.MARKUP_DECLARATION_HYPHEN, reconsume, pos);
                                 break markupdeclarationopenloop;
                             // continue stateloop;
                             case 'd':
                             case 'D':
-                                clearStrBufBeforeUse();
-                                appendStrBuf(c);
+                                clearStrBufAndAppend(c);
                                 index = 0;
                                 state = transition(state, Tokenizer.MARKUP_DECLARATION_OCTYPE, reconsume, pos);
                                 continue stateloop;
                             case '[':
                                 if (tokenHandler.cdataSectionAllowed()) {
-                                    clearStrBufBeforeUse();
-                                    appendStrBuf(c);
+                                    clearStrBufAndAppend(c);
                                     index = 0;
                                     state = transition(state, Tokenizer.CDATA_START, reconsume, pos);
                                     continue stateloop;
                                 }
                                 // else fall through
                             default:
                                 errBogusComment();
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 reconsume = true;
                                 state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
                                 continue stateloop;
                         }
                     }
                     // FALLTHRU DON'T REORDER
                 case MARKUP_DECLARATION_HYPHEN:
                     markupdeclarationhyphenloop: for (;;) {
                         if (++pos == endPos) {
                             break stateloop;
                         }
                         c = checkChar(buf, pos);
                         switch (c) {
                             case '\u0000':
                                 break stateloop;
                             case '-':
-                                clearStrBufAfterOneHyphen();
+                                clearStrBuf();
                                 state = transition(state, Tokenizer.COMMENT_START, reconsume, pos);
                                 break markupdeclarationhyphenloop;
                             // continue stateloop;
                             default:
                                 errBogusComment();
                                 reconsume = true;
                                 state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
                                 continue stateloop;
@@ -2806,17 +2763,16 @@ public class Tokenizer implements Locato
                                 errBogusComment();
                                 reconsume = true;
                                 state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
                                 continue stateloop;
                             }
                             index++;
                             continue;
                         } else {
-                            clearStrBufAfterUse();
                             cstart = pos; // start coalescing
                             reconsume = true;
                             state = transition(state, Tokenizer.CDATA_SECTION, reconsume, pos);
                             break; // FALL THROUGH continue stateloop;
                         }
                     }
                     // WARNING FALLTHRU CASE TRANSITION: DON'T REORDER
                 case CDATA_SECTION:
@@ -2920,18 +2876,17 @@ public class Tokenizer implements Locato
                                 continue stateloop;
                             case '&':
                                 /*
                                  * U+0026 AMPERSAND (&) Switch to the character
                                  * reference in attribute value state, with the
                                  * + additional allowed character being U+0027
                                  * APOSTROPHE (').
                                  */
-                                assert charRefBufLen == 0: "charRefBufLen not reset after previous use!";
-                                appendCharRefBuf(c);
+                                clearCharRefBufAndAppend(c);
                                 setAdditionalAndRememberAmpersandLocation('\'');
                                 returnState = state;
                                 state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos);
                                 break attributevaluesinglequotedloop;
                             // continue stateloop;
                             case '\r':
                                 appendStrBufCarriageReturn();
                                 break stateloop;
@@ -3269,26 +3224,23 @@ public class Tokenizer implements Locato
                             if ((returnState & DATA_AND_RCDATA_MASK) != 0) {
                                 appendStrBuf(charRefBuf, charRefBufMark,
                                         charRefBufLen - charRefBufMark);
                             } else {
                                 tokenHandler.characters(charRefBuf, charRefBufMark,
                                         charRefBufLen - charRefBufMark);
                             }
                         }
-                        // charRefBufLen will be zeroed below!
-
                         // Check if we broke out early with c being the last
                         // character that matched as opposed to being the
                         // first one that didn't match. In the case of an 
                         // early break, the next run on text should start
                         // *after* the current character and the current 
                         // character shouldn't be reconsumed.
                         boolean earlyBreak = (c == ';' && charRefBufMark == charRefBufLen);
-                        charRefBufLen = 0;
                         if ((returnState & DATA_AND_RCDATA_MASK) == 0) {
                             cstart = earlyBreak ? pos + 1 : pos;
                         }
                         reconsume = !earlyBreak;
                         state = transition(state, returnState, reconsume, pos);
                         continue stateloop;
                         /*
                          * If the markup contains I'm &notit; I tell you, the
@@ -3417,18 +3369,16 @@ public class Tokenizer implements Locato
                                 // FALL THROUGH continue stateloop;
                                 break decimalloop;
                             }
                         }
                     }
                     // WARNING FALLTHRU CASE TRANSITION: DON'T REORDER
                 case HANDLE_NCR_VALUE:
                     // WARNING previous state sets reconsume
-                    // We are not going to emit the contents of charRefBuf.
-                    charRefBufLen = 0;
                     // XXX inline this case if the method size can take it
                     handleNcrValue(returnState);
                     state = transition(state, returnState, reconsume, pos);
                     continue stateloop;
                     // XXX reorder point
                 case HEX_NCR_LOOP:
                     for (;;) {
                         if (++pos == endPos) {
@@ -3565,29 +3515,27 @@ public class Tokenizer implements Locato
                             continue stateloop;
                         case '\r':
                             silentCarriageReturn();
                             /* Anything else Parse error. */
                             errGarbageAfterLtSlash();
                             /*
                              * Switch to the bogus comment state.
                              */
-                            clearStrBufBeforeUse();
-                            appendStrBuf('\n');
+                            clearStrBufAndAppend('\n');
                             state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
                             break stateloop;
                         case '\n':
                             silentLineFeed();
                             /* Anything else Parse error. */
                             errGarbageAfterLtSlash();
                             /*
                              * Switch to the bogus comment state.
                              */
-                            clearStrBufBeforeUse();
-                            appendStrBuf(c);
+                            clearStrBufAndAppend('\n');
                             state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
                             continue stateloop;
                         case '\u0000':
                             c = '\uFFFD';
                             // fall thru
                         default:
                             if (c >= 'A' && c <= 'Z') {
                                 c += 0x20;
@@ -3597,33 +3545,31 @@ public class Tokenizer implements Locato
                                  * U+0061 LATIN SMALL LETTER A through to U+007A
                                  * LATIN SMALL LETTER Z Create a new end tag
                                  * token,
                                  */
                                 endTag = true;
                                 /*
                                  * set its tag name to the input character,
                                  */
-                                clearStrBufBeforeUse();
-                                appendStrBuf(c);
+                                clearStrBufAndAppend(c);
                                 /*
                                  * then switch to the tag name state. (Don't
                                  * emit the token yet; further details will be
                                  * filled in before it is emitted.)
                                  */
                                 state = transition(state, Tokenizer.TAG_NAME, reconsume, pos);
                                 continue stateloop;
                             } else {
                                 /* Anything else Parse error. */
                                 errGarbageAfterLtSlash();
                                 /*
                                  * Switch to the bogus comment state.
                                  */
-                                clearStrBufBeforeUse();
-                                appendStrBuf(c);
+                                clearStrBufAndAppend(c);
                                 state = transition(state, Tokenizer.BOGUS_COMMENT, reconsume, pos);
                                 continue stateloop;
                             }
                     }
                     // XXX reorder point
                 case RCDATA:
                     rcdataloop: for (;;) {
                         if (reconsume) {
@@ -3636,18 +3582,17 @@ public class Tokenizer implements Locato
                         }
                         switch (c) {
                             case '&':
                                 /*
                                  * U+0026 AMPERSAND (&) Switch to the character
                                  * reference in RCDATA state.
                                  */
                                 flushChars(buf, pos);
-                                assert charRefBufLen == 0: "charRefBufLen not reset after previous use!";
-                                appendCharRefBuf(c);
+                                clearCharRefBufAndAppend(c);
                                 setAdditionalAndRememberAmpersandLocation('\u0000');
                                 returnState = state;
                                 state = transition(state, Tokenizer.CONSUME_CHARACTER_REFERENCE, reconsume, pos);
                                 continue stateloop;
                             case '<':
                                 /*
                                  * U+003C LESS-THAN SIGN (<) Switch to the
                                  * RCDATA less-than sign state.
@@ -3722,17 +3667,17 @@ public class Tokenizer implements Locato
                         switch (c) {
                             case '/':
                                 /*
                                  * U+002F SOLIDUS (/) Set the temporary buffer
                                  * to the empty string. Switch to the script
                                  * data end tag open state.
                                  */
                                 index = 0;
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 state = transition(state, Tokenizer.NON_DATA_END_TAG_NAME, reconsume, pos);
                                 break rawtextrcdatalessthansignloop;
                             // FALL THRU continue stateloop;
                             default:
                                 /*
                                  * Otherwise, emit a U+003C LESS-THAN SIGN
                                  * character token
                                  */
@@ -3751,17 +3696,17 @@ public class Tokenizer implements Locato
                 case NON_DATA_END_TAG_NAME:
                     for (;;) {
                         if (++pos == endPos) {
                             break stateloop;
                         }
                         c = checkChar(buf, pos);
                         /*
                          * ASSERT! when entering this state, set index to 0 and
-                         * call clearStrBufBeforeUse() assert (contentModelElement !=
+                         * call clearStrBuf() assert (contentModelElement !=
                          * null); Let's implement the above without lookahead.
                          * strBuf is the 'temporary buffer'.
                          */
                         if (index < endTagExpectationAsArray.length) {
                             char e = endTagExpectationAsArray[index];
                             char folded = c;
                             if (c >= 'A' && c <= 'Z') {
                                 folded += 0x20;
@@ -3784,53 +3729,49 @@ public class Tokenizer implements Locato
                         } else {
                             endTag = true;
                             // XXX replace contentModelElement with different
                             // type
                             tagName = endTagExpectation;
                             switch (c) {
                                 case '\r':
                                     silentCarriageReturn();
-                                    clearStrBufAfterUse(); // strBuf not used
                                     state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos);
                                     break stateloop;
                                 case '\n':
                                     silentLineFeed();
                                     // fall thru
                                 case ' ':
                                 case '\t':
                                 case '\u000C':
                                     /*
                                      * U+0009 CHARACTER TABULATION U+000A LINE
                                      * FEED (LF) U+000C FORM FEED (FF) U+0020
                                      * SPACE If the current end tag token is an
                                      * appropriate end tag token, then switch to
                                      * the before attribute name state.
                                      */
-                                    clearStrBufAfterUse(); // strBuf not used
                                     state = transition(state, Tokenizer.BEFORE_ATTRIBUTE_NAME, reconsume, pos);
                                     continue stateloop;
                                 case '/':
                                     /*
                                      * U+002F SOLIDUS (/) If the current end tag
                                      * token is an appropriate end tag token,
                                      * then switch to the self-closing start tag
                                      * state.
                                      */
-                                    clearStrBufAfterUse(); // strBuf not used
                                     state = transition(state, Tokenizer.SELF_CLOSING_START_TAG, reconsume, pos);
                                     continue stateloop;
                                 case '>':
                                     /*
                                      * U+003E GREATER-THAN SIGN (>) If the
                                      * current end tag token is an appropriate
                                      * end tag token, then emit the current tag
                                      * token and switch to the data state.
                                      */
-                                    clearStrBufAfterUse(); // strBuf not used
                                     state = transition(state, emitCurrentTagToken(false, pos), reconsume, pos);
                                     if (shouldSuspend) {
                                         break stateloop;
                                     }
                                     continue stateloop;
                                 default:
                                     /*
                                      * Emit a U+003C LESS-THAN SIGN character
@@ -3995,17 +3936,17 @@ public class Tokenizer implements Locato
                         switch (c) {
                             case '/':
                                 /*
                                  * U+002F SOLIDUS (/) Set the temporary buffer
                                  * to the empty string. Switch to the script
                                  * data end tag open state.
                                  */
                                 index = 0;
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 state = transition(state, Tokenizer.NON_DATA_END_TAG_NAME, reconsume, pos);
                                 continue stateloop;
                             case '!':
                                 tokenHandler.characters(Tokenizer.LT_GT, 0, 1);
                                 cstart = pos;
                                 state = transition(state, Tokenizer.SCRIPT_DATA_ESCAPE_START, reconsume, pos);
                                 break scriptdatalessthansignloop; // FALL THRU
                             // continue
@@ -4253,17 +4194,17 @@ public class Tokenizer implements Locato
                         switch (c) {
                             case '/':
                                 /*
                                  * U+002F SOLIDUS (/) Set the temporary buffer
                                  * to the empty string. Switch to the script
                                  * data escaped end tag open state.
                                  */
                                 index = 0;
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 returnState = Tokenizer.SCRIPT_DATA_ESCAPED;
                                 state = transition(state, Tokenizer.NON_DATA_END_TAG_NAME, reconsume, pos);
                                 continue stateloop;
                             case 'S':
                             case 's':
                                 /*
                                  * U+0041 LATIN CAPITAL LETTER A through to
                                  * U+005A LATIN CAPITAL LETTER Z Emit a U+003C
@@ -4735,18 +4676,17 @@ public class Tokenizer implements Locato
                                      */
                                     c += 0x20;
                                 }
                                 /* Anything else Create a new DOCTYPE token. */
                                 /*
                                  * Set the token's name name to the current
                                  * input character.
                                  */
-                                clearStrBufBeforeUse();
-                                appendStrBuf(c);
+                                clearStrBufAndAppend(c);
                                 /*
                                  * Switch to the DOCTYPE name state.
                                  */
                                 state = transition(state, Tokenizer.DOCTYPE_NAME, reconsume, pos);
                                 break beforedoctypenameloop;
                             // continue stateloop;
                         }
                     }
@@ -4957,33 +4897,33 @@ public class Tokenizer implements Locato
                                 /*
                                  * U+0022 QUOTATION MARK (") Parse Error.
                                  */
                                 errNoSpaceBetweenDoctypePublicKeywordAndQuote();
                                 /*
                                  * Set the DOCTYPE token's public identifier to
                                  * the empty string (not missing),
                                  */
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 /*
                                  * then switch to the DOCTYPE public identifier
                                  * (double-quoted) state.
                                  */
                                 state = transition(state, Tokenizer.DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
                                 continue stateloop;
                             case '\'':
                                 /*
                                  * U+0027 APOSTROPHE (') Parse Error.
                                  */
                                 errNoSpaceBetweenDoctypePublicKeywordAndQuote();
                                 /*
                                  * Set the DOCTYPE token's public identifier to
                                  * the empty string (not missing),
                                  */
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 /*
                                  * then switch to the DOCTYPE public identifier
                                  * (single-quoted) state.
                                  */
                                 state = transition(state, Tokenizer.DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
                                 continue stateloop;
                             case '>':
                                 /* U+003E GREATER-THAN SIGN (>) Parse error. */
@@ -5044,31 +4984,31 @@ public class Tokenizer implements Locato
                                  */
                                 continue;
                             case '"':
                                 /*
                                  * U+0022 QUOTATION MARK (") Set the DOCTYPE
                                  * token's public identifier to the empty string
                                  * (not missing),
                                  */
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 /*
                                  * then switch to the DOCTYPE public identifier
                                  * (double-quoted) state.
                                  */
                                 state = transition(state, Tokenizer.DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
                                 break beforedoctypepublicidentifierloop;
                             // continue stateloop;
                             case '\'':
                                 /*
                                  * U+0027 APOSTROPHE (') Set the DOCTYPE token's
                                  * public identifier to the empty string (not
                                  * missing),
                                  */
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 /*
                                  * then switch to the DOCTYPE public identifier
                                  * (single-quoted) state.
                                  */
                                 state = transition(state, Tokenizer.DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
                                 continue stateloop;
                             case '>':
                                 /* U+003E GREATER-THAN SIGN (>) Parse error. */
@@ -5209,33 +5149,33 @@ public class Tokenizer implements Locato
                                 /*
                                  * U+0022 QUOTATION MARK (") Parse error.
                                  */
                                 errNoSpaceBetweenPublicAndSystemIds();
                                 /*
                                  * Set the DOCTYPE token's system identifier to
                                  * the empty string (not missing),
                                  */
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 /*
                                  * then switch to the DOCTYPE system identifier
                                  * (double-quoted) state.
                                  */
                                 state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
                                 continue stateloop;
                             case '\'':
                                 /*
                                  * U+0027 APOSTROPHE (') Parse error.
                                  */
                                 errNoSpaceBetweenPublicAndSystemIds();
                                 /*
                                  * Set the DOCTYPE token's system identifier to
                                  * the empty string (not missing),
                                  */
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 /*
                                  * then switch to the DOCTYPE system identifier
                                  * (single-quoted) state.
                                  */
                                 state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
                                 continue stateloop;
                             default:
                                 bogusDoctype();
@@ -5290,31 +5230,31 @@ public class Tokenizer implements Locato
                                 state = transition(state, Tokenizer.DATA, reconsume, pos);
                                 continue stateloop;
                             case '"':
                                 /*
                                  * U+0022 QUOTATION MARK (") Set the DOCTYPE
                                  * token's system identifier to the empty string
                                  * (not missing),
                                  */
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 /*
                                  * then switch to the DOCTYPE system identifier
                                  * (double-quoted) state.
                                  */
                                 state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
                                 break betweendoctypepublicandsystemidentifiersloop;
                             // continue stateloop;
                             case '\'':
                                 /*
                                  * U+0027 APOSTROPHE (') Set the DOCTYPE token's
                                  * system identifier to the empty string (not
                                  * missing),
                                  */
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 /*
                                  * then switch to the DOCTYPE system identifier
                                  * (single-quoted) state.
                                  */
                                 state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
                                 continue stateloop;
                             default:
                                 bogusDoctype();
@@ -5553,33 +5493,33 @@ public class Tokenizer implements Locato
                                 /*
                                  * U+0022 QUOTATION MARK (") Parse Error.
                                  */
                                 errNoSpaceBetweenDoctypeSystemKeywordAndQuote();
                                 /*
                                  * Set the DOCTYPE token's system identifier to
                                  * the empty string (not missing),
                                  */
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 /*
                                  * then switch to the DOCTYPE public identifier
                                  * (double-quoted) state.
                                  */
                                 state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
                                 continue stateloop;
                             case '\'':
                                 /*
                                  * U+0027 APOSTROPHE (') Parse Error.
                                  */
                                 errNoSpaceBetweenDoctypeSystemKeywordAndQuote();
                                 /*
                                  * Set the DOCTYPE token's public identifier to
                                  * the empty string (not missing),
                                  */
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 /*
                                  * then switch to the DOCTYPE public identifier
                                  * (single-quoted) state.
                                  */
                                 state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
                                 continue stateloop;
                             case '>':
                                 /* U+003E GREATER-THAN SIGN (>) Parse error. */
@@ -5640,30 +5580,30 @@ public class Tokenizer implements Locato
                                  */
                                 continue;
                             case '"':
                                 /*
                                  * U+0022 QUOTATION MARK (") Set the DOCTYPE
                                  * token's system identifier to the empty string
                                  * (not missing),
                                  */
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 /*
                                  * then switch to the DOCTYPE system identifier
                                  * (double-quoted) state.
                                  */
                                 state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
                                 continue stateloop;
                             case '\'':
                                 /*
                                  * U+0027 APOSTROPHE (') Set the DOCTYPE token's
                                  * system identifier to the empty string (not
                                  * missing),
                                  */
-                                clearStrBufBeforeUse();
+                                clearStrBuf();
                                 /*
                                  * then switch to the DOCTYPE system identifier
                                  * (single-quoted) state.
                                  */
                                 state = transition(state, Tokenizer.DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
                                 break beforedoctypesystemidentifierloop;
                             // continue stateloop;
                             case '>':
@@ -5869,19 +5809,16 @@ public class Tokenizer implements Locato
     
     protected int transition(int from, int to, boolean reconsume, int pos) throws SAXException {
         return to;
     }
 
     // ]NOCPP]
     
     private void initDoctypeFields() {
-        // Discard the characters "DOCTYPE" accumulated as a potential bogus
-        // comment into strBuf.
-        clearStrBufAfterUse();
         doctypeName = "";
         if (systemIdentifier != null) {
             Portability.releaseString(systemIdentifier);
             systemIdentifier = null;
         }
         if (publicIdentifier != null) {
             Portability.releaseString(publicIdentifier);
             publicIdentifier = null;
@@ -6159,16 +6096,17 @@ public class Tokenizer implements Locato
                 case BOGUS_COMMENT_HYPHEN:
                     // [NOCPP[
                     maybeAppendSpaceToBogusComment();
                     // ]NOCPP]
                     emitComment(0, 0);
                     break eofloop;
                 case MARKUP_DECLARATION_OPEN:
                     errBogusComment();
+                    clearStrBuf();
                     emitComment(0, 0);
                     break eofloop;
                 case MARKUP_DECLARATION_HYPHEN:
                     errBogusComment();
                     emitComment(0, 0);
                     break eofloop;
                 case MARKUP_DECLARATION_OCTYPE:
                     if (index < 6) {
@@ -6514,17 +6452,16 @@ public class Tokenizer implements Locato
                             if ((returnState & DATA_AND_RCDATA_MASK) != 0) {
                                 appendStrBuf(charRefBuf, charRefBufMark,
                                         charRefBufLen - charRefBufMark);
                             } else {
                                 tokenHandler.characters(charRefBuf, charRefBufMark,
                                         charRefBufLen - charRefBufMark);
                             }
                         }
-                        charRefBufLen = 0;
                         state = returnState;
                         continue eofloop;
                         /*
                          * If the markup contains I'm &notit; I tell you, the
                          * entity is parsed as "not", as in, I'm ¬it; I tell
                          * you. But if the markup was I'm &notin; I tell you,
                          * the entity would be parsed as "notin;", resulting in
                          * I'm ∉ I tell you.
@@ -6694,17 +6631,17 @@ public class Tokenizer implements Locato
 
     // ]NOCPP]
     
     public boolean isInDataState() {
         return (stateSave == DATA);
     }
 
     public void resetToDataState() {
-        clearStrBufAfterUse();
+        strBufLen = 0;
         charRefBufLen = 0;
         stateSave = Tokenizer.DATA;
         // line = 1; XXX line numbers
         lastCR = false;
         index = 0;
         forceQuirks = false;
         additional = '\u0000';
         entCol = -1;
--- a/parser/html/nsHtml5Tokenizer.cpp
+++ b/parser/html/nsHtml5Tokenizer.cpp
@@ -212,81 +212,79 @@ nsHtml5Tokenizer::emptyAttributes()
 void 
 nsHtml5Tokenizer::emitOrAppendCharRefBuf(int32_t returnState)
 {
   if ((returnState & NS_HTML5TOKENIZER_DATA_AND_RCDATA_MASK)) {
     appendCharRefBufToStrBuf();
   } else {
     if (charRefBufLen > 0) {
       tokenHandler->characters(charRefBuf, 0, charRefBufLen);
-      charRefBufLen = 0;
     }
   }
 }
 
+void 
+nsHtml5Tokenizer::appendStrBuf(char16_t c)
+{
+  strBuf[strBufLen++] = c;
+}
+
 nsString* 
 nsHtml5Tokenizer::strBufToString()
 {
-  nsString* str = nsHtml5Portability::newStringFromBuffer(strBuf, 0, strBufLen, tokenHandler);
-  clearStrBufAfterUse();
-  return str;
+  return nsHtml5Portability::newStringFromBuffer(strBuf, 0, strBufLen, tokenHandler);
 }
 
 void 
 nsHtml5Tokenizer::strBufToDoctypeName()
 {
   doctypeName = nsHtml5Portability::newLocalNameFromBuffer(strBuf, 0, strBufLen, interner);
-  clearStrBufAfterUse();
 }
 
 void 
 nsHtml5Tokenizer::emitStrBuf()
 {
   if (strBufLen > 0) {
     tokenHandler->characters(strBuf, 0, strBufLen);
-    clearStrBufAfterUse();
   }
 }
 
 void 
 nsHtml5Tokenizer::appendStrBuf(char16_t* buffer, int32_t offset, int32_t length)
 {
-  int32_t newLen = strBufLen + length;
-  MOZ_ASSERT(newLen <= strBuf.length, "Previous buffer length insufficient.");
-  if (MOZ_UNLIKELY(strBuf.length < newLen)) {
-    if (MOZ_UNLIKELY(!EnsureBufferSpace(length))) {
-      MOZ_CRASH("Unable to recover from buffer reallocation failure");
-    }
+  int32_t reqLen = strBufLen + length;
+  if (strBuf.length < reqLen) {
+    jArray<char16_t,int32_t> newBuf = jArray<char16_t,int32_t>::newJArray(reqLen + (reqLen >> 1));
+    nsHtml5ArrayCopy::arraycopy(strBuf, newBuf, strBuf.length);
+    strBuf = newBuf;
   }
   nsHtml5ArrayCopy::arraycopy(buffer, offset, strBuf, strBufLen, length);
-  strBufLen = newLen;
+  strBufLen = reqLen;
 }
 
 void 
 nsHtml5Tokenizer::emitComment(int32_t provisionalHyphens, int32_t pos)
 {
   tokenHandler->comment(strBuf, 0, strBufLen - provisionalHyphens);
-  clearStrBufAfterUse();
   cstart = pos + 1;
 }
 
 void 
 nsHtml5Tokenizer::flushChars(char16_t* buf, int32_t pos)
 {
   if (pos > cstart) {
     tokenHandler->characters(buf, cstart, pos - cstart);
   }
   cstart = INT32_MAX;
 }
 
 void 
 nsHtml5Tokenizer::strBufToElementNameString()
 {
   tagName = nsHtml5ElementName::elementNameByBuffer(strBuf, 0, strBufLen, interner);
-  clearStrBufAfterUse();
 }
 
 int32_t 
 nsHtml5Tokenizer::emitCurrentTagToken(bool selfClosing, int32_t pos)
 {
   cstart = pos + 1;
   maybeErrSlashInEndTag(selfClosing);
   stateSave = NS_HTML5TOKENIZER_DATA;
@@ -318,17 +316,16 @@ nsHtml5Tokenizer::emitCurrentTagToken(bo
   }
   return stateSave;
 }
 
 void 
 nsHtml5Tokenizer::attributeNameComplete()
 {
   attributeName = nsHtml5AttributeName::nameByBuffer(strBuf, 0, strBufLen, interner);
-  clearStrBufAfterUse();
   if (!attributes) {
     attributes = new nsHtml5HtmlAttributes(0);
   }
   if (attributes->contains(attributeName)) {
     errDuplicateAttribute();
     attributeName->release();
     attributeName = nullptr;
   }
@@ -336,18 +333,16 @@ nsHtml5Tokenizer::attributeNameComplete(
 
 void 
 nsHtml5Tokenizer::addAttributeWithoutValue()
 {
 
   if (attributeName) {
     attributes->addAttribute(attributeName, nsHtml5Portability::newEmptyString(), attributeLine);
     attributeName = nullptr;
-  } else {
-    clearStrBufAfterUse();
   }
 }
 
 void 
 nsHtml5Tokenizer::addAttributeWithValue()
 {
   if (attributeName) {
     nsString* val = strBufToString();
@@ -432,18 +427,17 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
             if (++pos == endPos) {
               NS_HTML5_BREAK(stateloop);
             }
             c = checkChar(buf, pos);
           }
           switch(c) {
             case '&': {
               flushChars(buf, pos);
-              MOZ_ASSERT(!charRefBufLen, "charRefBufLen not reset after previous use!");
-              appendCharRefBuf(c);
+              clearCharRefBufAndAppend(c);
               setAdditionalAndRememberAmpersandLocation('\0');
               returnState = state;
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_CONSUME_CHARACTER_REFERENCE, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '<': {
               flushChars(buf, pos);
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_TAG_OPEN, reconsume, pos);
@@ -470,24 +464,22 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
       case NS_HTML5TOKENIZER_TAG_OPEN: {
         for (; ; ) {
           if (++pos == endPos) {
             NS_HTML5_BREAK(stateloop);
           }
           c = checkChar(buf, pos);
           if (c >= 'A' && c <= 'Z') {
             endTag = false;
-            clearStrBufBeforeUse();
-            appendStrBuf((char16_t) (c + 0x20));
+            clearStrBufAndAppend((char16_t) (c + 0x20));
             state = P::transition(mViewSource, NS_HTML5TOKENIZER_TAG_NAME, reconsume, pos);
             NS_HTML5_BREAK(tagopenloop);
           } else if (c >= 'a' && c <= 'z') {
             endTag = false;
-            clearStrBufBeforeUse();
-            appendStrBuf(c);
+            clearStrBufAndAppend(c);
             state = P::transition(mViewSource, NS_HTML5TOKENIZER_TAG_NAME, reconsume, pos);
             NS_HTML5_BREAK(tagopenloop);
           }
           switch(c) {
             case '!': {
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_MARKUP_DECLARATION_OPEN, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
@@ -498,18 +490,17 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
             case '\?': {
               if (viewingXmlSource) {
                 state = P::transition(mViewSource, NS_HTML5TOKENIZER_PROCESSING_INSTRUCTION, reconsume, pos);
                 NS_HTML5_CONTINUE(stateloop);
               }
               if (P::reportErrors) {
                 errProcessingInstruction();
               }
-              clearStrBufBeforeUse();
-              appendStrBuf(c);
+              clearStrBufAndAppend(c);
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_BOGUS_COMMENT, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '>': {
               if (P::reportErrors) {
                 errLtGt();
               }
               tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 2);
@@ -626,18 +617,17 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
                 errBadCharBeforeAttributeNameOrNull(c);
               }
             }
             default: {
               if (c >= 'A' && c <= 'Z') {
                 c += 0x20;
               }
               attributeLine = line;
-              clearStrBufBeforeUse();
-              appendStrBuf(c);
+              clearStrBufAndAppend(c);
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_ATTRIBUTE_NAME, reconsume, pos);
               NS_HTML5_BREAK(beforeattributenameloop);
             }
           }
         }
         beforeattributenameloop_end: ;
       }
       case NS_HTML5TOKENIZER_ATTRIBUTE_NAME: {
@@ -720,31 +710,31 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
             }
             case ' ':
             case '\t':
             case '\f': {
               continue;
             }
             case '\"': {
               attributeLine = line;
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_ATTRIBUTE_VALUE_DOUBLE_QUOTED, reconsume, pos);
               NS_HTML5_BREAK(beforeattributevalueloop);
             }
             case '&': {
               attributeLine = line;
-              clearStrBufBeforeUse();
+              clearStrBuf();
               reconsume = true;
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_ATTRIBUTE_VALUE_UNQUOTED, reconsume, pos);
 
               NS_HTML5_CONTINUE(stateloop);
             }
             case '\'': {
               attributeLine = line;
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_ATTRIBUTE_VALUE_SINGLE_QUOTED, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '>': {
               if (P::reportErrors) {
                 errAttributeValueMissing();
               }
               addAttributeWithoutValue();
@@ -761,18 +751,17 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
             case '=':
             case '`': {
               if (P::reportErrors) {
                 errLtOrEqualsOrGraveInUnquotedAttributeOrNull(c);
               }
             }
             default: {
               attributeLine = line;
-              clearStrBufBeforeUse();
-              appendStrBuf(c);
+              clearStrBufAndAppend(c);
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_ATTRIBUTE_VALUE_UNQUOTED, reconsume, pos);
 
               NS_HTML5_CONTINUE(stateloop);
             }
           }
         }
         beforeattributevalueloop_end: ;
       }
@@ -788,18 +777,17 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
           }
           switch(c) {
             case '\"': {
               addAttributeWithValue();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_AFTER_ATTRIBUTE_VALUE_QUOTED, reconsume, pos);
               NS_HTML5_BREAK(attributevaluedoublequotedloop);
             }
             case '&': {
-              MOZ_ASSERT(!charRefBufLen, "charRefBufLen not reset after previous use!");
-              appendCharRefBuf(c);
+              clearCharRefBufAndAppend(c);
               setAdditionalAndRememberAmpersandLocation('\"');
               returnState = state;
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_CONSUME_CHARACTER_REFERENCE, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '\r': {
               appendStrBufCarriageReturn();
               NS_HTML5_BREAK(stateloop);
@@ -909,18 +897,17 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
             case ' ':
             case '\t':
             case '\f': {
               addAttributeWithValue();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '&': {
-              MOZ_ASSERT(!charRefBufLen, "charRefBufLen not reset after previous use!");
-              appendCharRefBuf(c);
+              clearCharRefBufAndAppend(c);
               setAdditionalAndRememberAmpersandLocation('>');
               returnState = state;
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_CONSUME_CHARACTER_REFERENCE, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '>': {
               addAttributeWithValue();
               state = P::transition(mViewSource, emitCurrentTagToken(false, pos), reconsume, pos);
@@ -995,59 +982,55 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
                 errQuoteOrLtInAttributeNameOrNull(c);
               }
             }
             default: {
               addAttributeWithoutValue();
               if (c >= 'A' && c <= 'Z') {
                 c += 0x20;
               }
-              clearStrBufBeforeUse();
-              appendStrBuf(c);
+              clearStrBufAndAppend(c);
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_ATTRIBUTE_NAME, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
           }
         }
       }
       case NS_HTML5TOKENIZER_MARKUP_DECLARATION_OPEN: {
         for (; ; ) {
           if (++pos == endPos) {
             NS_HTML5_BREAK(stateloop);
           }
           c = checkChar(buf, pos);
           switch(c) {
             case '-': {
-              clearStrBufBeforeUse();
-              appendStrBuf(c);
+              clearStrBufAndAppend(c);
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_MARKUP_DECLARATION_HYPHEN, reconsume, pos);
               NS_HTML5_BREAK(markupdeclarationopenloop);
             }
             case 'd':
             case 'D': {
-              clearStrBufBeforeUse();
-              appendStrBuf(c);
+              clearStrBufAndAppend(c);
               index = 0;
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_MARKUP_DECLARATION_OCTYPE, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '[': {
               if (tokenHandler->cdataSectionAllowed()) {
-                clearStrBufBeforeUse();
-                appendStrBuf(c);
+                clearStrBufAndAppend(c);
                 index = 0;
                 state = P::transition(mViewSource, NS_HTML5TOKENIZER_CDATA_START, reconsume, pos);
                 NS_HTML5_CONTINUE(stateloop);
               }
             }
             default: {
               if (P::reportErrors) {
                 errBogusComment();
               }
-              clearStrBufBeforeUse();
+              clearStrBuf();
               reconsume = true;
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_BOGUS_COMMENT, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
           }
         }
         markupdeclarationopenloop_end: ;
       }
@@ -1057,17 +1040,17 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
             NS_HTML5_BREAK(stateloop);
           }
           c = checkChar(buf, pos);
           switch(c) {
             case '\0': {
               NS_HTML5_BREAK(stateloop);
             }
             case '-': {
-              clearStrBufAfterOneHyphen();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_COMMENT_START, reconsume, pos);
               NS_HTML5_BREAK(markupdeclarationhyphenloop);
             }
             default: {
               if (P::reportErrors) {
                 errBogusComment();
               }
               reconsume = true;
@@ -1321,17 +1304,16 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
               }
               reconsume = true;
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_BOGUS_COMMENT, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             index++;
             continue;
           } else {
-            clearStrBufAfterUse();
             cstart = pos;
             reconsume = true;
             state = P::transition(mViewSource, NS_HTML5TOKENIZER_CDATA_SECTION, reconsume, pos);
             break;
           }
         }
       }
       case NS_HTML5TOKENIZER_CDATA_SECTION: {
@@ -1429,18 +1411,17 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
           }
           switch(c) {
             case '\'': {
               addAttributeWithValue();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_AFTER_ATTRIBUTE_VALUE_QUOTED, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '&': {
-              MOZ_ASSERT(!charRefBufLen, "charRefBufLen not reset after previous use!");
-              appendCharRefBuf(c);
+              clearCharRefBufAndAppend(c);
               setAdditionalAndRememberAmpersandLocation('\'');
               returnState = state;
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_CONSUME_CHARACTER_REFERENCE, reconsume, pos);
               NS_HTML5_BREAK(attributevaluesinglequotedloop);
             }
             case '\r': {
               appendStrBufCarriageReturn();
               NS_HTML5_BREAK(stateloop);
@@ -1662,17 +1643,16 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
           if (charRefBufMark < charRefBufLen) {
             if ((returnState & NS_HTML5TOKENIZER_DATA_AND_RCDATA_MASK)) {
               appendStrBuf(charRefBuf, charRefBufMark, charRefBufLen - charRefBufMark);
             } else {
               tokenHandler->characters(charRefBuf, charRefBufMark, charRefBufLen - charRefBufMark);
             }
           }
           bool earlyBreak = (c == ';' && charRefBufMark == charRefBufLen);
-          charRefBufLen = 0;
           if (!(returnState & NS_HTML5TOKENIZER_DATA_AND_RCDATA_MASK)) {
             cstart = earlyBreak ? pos + 1 : pos;
           }
           reconsume = !earlyBreak;
           state = P::transition(mViewSource, returnState, reconsume, pos);
           NS_HTML5_CONTINUE(stateloop);
         }
       }
@@ -1756,17 +1736,16 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_HANDLE_NCR_VALUE, reconsume, pos);
               NS_HTML5_BREAK(decimalloop);
             }
           }
         }
         decimalloop_end: ;
       }
       case NS_HTML5TOKENIZER_HANDLE_NCR_VALUE: {
-        charRefBufLen = 0;
         handleNcrValue(returnState);
         state = P::transition(mViewSource, returnState, reconsume, pos);
         NS_HTML5_CONTINUE(stateloop);
       }
       case NS_HTML5TOKENIZER_HEX_NCR_LOOP: {
         for (; ; ) {
           if (++pos == endPos) {
             NS_HTML5_BREAK(stateloop);
@@ -1882,50 +1861,46 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
             state = P::transition(mViewSource, NS_HTML5TOKENIZER_DATA, reconsume, pos);
             NS_HTML5_CONTINUE(stateloop);
           }
           case '\r': {
             silentCarriageReturn();
             if (P::reportErrors) {
               errGarbageAfterLtSlash();
             }
-            clearStrBufBeforeUse();
-            appendStrBuf('\n');
+            clearStrBufAndAppend('\n');
             state = P::transition(mViewSource, NS_HTML5TOKENIZER_BOGUS_COMMENT, reconsume, pos);
             NS_HTML5_BREAK(stateloop);
           }
           case '\n': {
             silentLineFeed();
             if (P::reportErrors) {
               errGarbageAfterLtSlash();
             }
-            clearStrBufBeforeUse();
-            appendStrBuf(c);
+            clearStrBufAndAppend('\n');
             state = P::transition(mViewSource, NS_HTML5TOKENIZER_BOGUS_COMMENT, reconsume, pos);
             NS_HTML5_CONTINUE(stateloop);
           }
           case '\0': {
             c = 0xfffd;
           }
           default: {
             if (c >= 'A' && c <= 'Z') {
               c += 0x20;
             }
             if (c >= 'a' && c <= 'z') {
               endTag = true;
-              clearStrBufBeforeUse();
-              appendStrBuf(c);
+              clearStrBufAndAppend(c);
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_TAG_NAME, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             } else {
               if (P::reportErrors) {
                 errGarbageAfterLtSlash();
               }
-              clearStrBufBeforeUse();
-              appendStrBuf(c);
+              clearStrBufAndAppend(c);
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_BOGUS_COMMENT, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
           }
         }
       }
       case NS_HTML5TOKENIZER_RCDATA: {
         for (; ; ) {
@@ -1935,18 +1910,17 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
             if (++pos == endPos) {
               NS_HTML5_BREAK(stateloop);
             }
             c = checkChar(buf, pos);
           }
           switch(c) {
             case '&': {
               flushChars(buf, pos);
-              MOZ_ASSERT(!charRefBufLen, "charRefBufLen not reset after previous use!");
-              appendCharRefBuf(c);
+              clearCharRefBufAndAppend(c);
               setAdditionalAndRememberAmpersandLocation('\0');
               returnState = state;
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_CONSUME_CHARACTER_REFERENCE, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '<': {
               flushChars(buf, pos);
               returnState = state;
@@ -2010,17 +1984,17 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
         for (; ; ) {
           if (++pos == endPos) {
             NS_HTML5_BREAK(stateloop);
           }
           c = checkChar(buf, pos);
           switch(c) {
             case '/': {
               index = 0;
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_NON_DATA_END_TAG_NAME, reconsume, pos);
               NS_HTML5_BREAK(rawtextrcdatalessthansignloop);
             }
             default: {
               tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
               cstart = pos;
               reconsume = true;
               state = P::transition(mViewSource, returnState, reconsume, pos);
@@ -2054,37 +2028,33 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
             index++;
             continue;
           } else {
             endTag = true;
             tagName = endTagExpectation;
             switch(c) {
               case '\r': {
                 silentCarriageReturn();
-                clearStrBufAfterUse();
                 state = P::transition(mViewSource, NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME, reconsume, pos);
                 NS_HTML5_BREAK(stateloop);
               }
               case '\n': {
                 silentLineFeed();
               }
               case ' ':
               case '\t':
               case '\f': {
-                clearStrBufAfterUse();
                 state = P::transition(mViewSource, NS_HTML5TOKENIZER_BEFORE_ATTRIBUTE_NAME, reconsume, pos);
                 NS_HTML5_CONTINUE(stateloop);
               }
               case '/': {
-                clearStrBufAfterUse();
                 state = P::transition(mViewSource, NS_HTML5TOKENIZER_SELF_CLOSING_START_TAG, reconsume, pos);
                 NS_HTML5_CONTINUE(stateloop);
               }
               case '>': {
-                clearStrBufAfterUse();
                 state = P::transition(mViewSource, emitCurrentTagToken(false, pos), reconsume, pos);
                 if (shouldSuspend) {
                   NS_HTML5_BREAK(stateloop);
                 }
                 NS_HTML5_CONTINUE(stateloop);
               }
               default: {
                 tokenHandler->characters(nsHtml5Tokenizer::LT_SOLIDUS, 0, 2);
@@ -2218,17 +2188,17 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
         for (; ; ) {
           if (++pos == endPos) {
             NS_HTML5_BREAK(stateloop);
           }
           c = checkChar(buf, pos);
           switch(c) {
             case '/': {
               index = 0;
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_NON_DATA_END_TAG_NAME, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '!': {
               tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
               cstart = pos;
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_SCRIPT_DATA_ESCAPE_START, reconsume, pos);
               NS_HTML5_BREAK(scriptdatalessthansignloop);
@@ -2403,17 +2373,17 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
         for (; ; ) {
           if (++pos == endPos) {
             NS_HTML5_BREAK(stateloop);
           }
           c = checkChar(buf, pos);
           switch(c) {
             case '/': {
               index = 0;
-              clearStrBufBeforeUse();
+              clearStrBuf();
               returnState = NS_HTML5TOKENIZER_SCRIPT_DATA_ESCAPED;
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_NON_DATA_END_TAG_NAME, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case 'S':
             case 's': {
               tokenHandler->characters(nsHtml5Tokenizer::LT_GT, 0, 1);
               cstart = pos;
@@ -2759,18 +2729,17 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
             }
             case '\0': {
               c = 0xfffd;
             }
             default: {
               if (c >= 'A' && c <= 'Z') {
                 c += 0x20;
               }
-              clearStrBufBeforeUse();
-              appendStrBuf(c);
+              clearStrBufAndAppend(c);
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DOCTYPE_NAME, reconsume, pos);
               NS_HTML5_BREAK(beforedoctypenameloop);
             }
           }
         }
         beforedoctypenameloop_end: ;
       }
       case NS_HTML5TOKENIZER_DOCTYPE_NAME: {
@@ -2912,25 +2881,25 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
             case '\f': {
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_BEFORE_DOCTYPE_PUBLIC_IDENTIFIER, reconsume, pos);
               NS_HTML5_BREAK(afterdoctypepublickeywordloop);
             }
             case '\"': {
               if (P::reportErrors) {
                 errNoSpaceBetweenDoctypePublicKeywordAndQuote();
               }
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '\'': {
               if (P::reportErrors) {
                 errNoSpaceBetweenDoctypePublicKeywordAndQuote();
               }
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '>': {
               if (P::reportErrors) {
                 errExpectedPublicId();
               }
               forceQuirks = true;
@@ -2962,22 +2931,22 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
               silentLineFeed();
             }
             case ' ':
             case '\t':
             case '\f': {
               continue;
             }
             case '\"': {
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
               NS_HTML5_BREAK(beforedoctypepublicidentifierloop);
             }
             case '\'': {
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '>': {
               if (P::reportErrors) {
                 errExpectedPublicId();
               }
               forceQuirks = true;
@@ -3060,25 +3029,25 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
               emitDoctypeToken(pos);
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DATA, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '\"': {
               if (P::reportErrors) {
                 errNoSpaceBetweenPublicAndSystemIds();
               }
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '\'': {
               if (P::reportErrors) {
                 errNoSpaceBetweenPublicAndSystemIds();
               }
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             default: {
               bogusDoctype();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_BOGUS_DOCTYPE, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
@@ -3106,22 +3075,22 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
               continue;
             }
             case '>': {
               emitDoctypeToken(pos);
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DATA, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '\"': {
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
               NS_HTML5_BREAK(betweendoctypepublicandsystemidentifiersloop);
             }
             case '\'': {
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             default: {
               bogusDoctype();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_BOGUS_DOCTYPE, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
@@ -3283,25 +3252,25 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
             case '\f': {
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_BEFORE_DOCTYPE_SYSTEM_IDENTIFIER, reconsume, pos);
               NS_HTML5_BREAK(afterdoctypesystemkeywordloop);
             }
             case '\"': {
               if (P::reportErrors) {
                 errNoSpaceBetweenDoctypeSystemKeywordAndQuote();
               }
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '\'': {
               if (P::reportErrors) {
                 errNoSpaceBetweenDoctypeSystemKeywordAndQuote();
               }
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '>': {
               if (P::reportErrors) {
                 errExpectedPublicId();
               }
               forceQuirks = true;
@@ -3333,22 +3302,22 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
               silentLineFeed();
             }
             case ' ':
             case '\t':
             case '\f': {
               continue;
             }
             case '\"': {
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED, reconsume, pos);
               NS_HTML5_CONTINUE(stateloop);
             }
             case '\'': {
-              clearStrBufBeforeUse();
+              clearStrBuf();
               state = P::transition(mViewSource, NS_HTML5TOKENIZER_DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED, reconsume, pos);
               NS_HTML5_BREAK(beforedoctypesystemidentifierloop);
             }
             case '>': {
               if (P::reportErrors) {
                 errExpectedSystemId();
               }
               forceQuirks = true;
@@ -3486,17 +3455,16 @@ nsHtml5Tokenizer::stateLoop(int32_t stat
   stateSave = state;
   returnStateSave = returnState;
   return pos;
 }
 
 void 
 nsHtml5Tokenizer::initDoctypeFields()
 {
-  clearStrBufAfterUse();
   doctypeName = nsHtml5Atoms::emptystring;
   if (systemIdentifier) {
     nsHtml5Portability::releaseString(systemIdentifier);
     systemIdentifier = nullptr;
   }
   if (publicIdentifier) {
     nsHtml5Portability::releaseString(publicIdentifier);
     publicIdentifier = nullptr;
@@ -3639,16 +3607,17 @@ nsHtml5Tokenizer::eof()
         NS_HTML5_BREAK(eofloop);
       }
       case NS_HTML5TOKENIZER_BOGUS_COMMENT_HYPHEN: {
         emitComment(0, 0);
         NS_HTML5_BREAK(eofloop);
       }
       case NS_HTML5TOKENIZER_MARKUP_DECLARATION_OPEN: {
         errBogusComment();
+        clearStrBuf();
         emitComment(0, 0);
         NS_HTML5_BREAK(eofloop);
       }
       case NS_HTML5TOKENIZER_MARKUP_DECLARATION_HYPHEN: {
         errBogusComment();
         emitComment(0, 0);
         NS_HTML5_BREAK(eofloop);
       }
@@ -3844,17 +3813,16 @@ nsHtml5Tokenizer::eof()
           }
           if (charRefBufMark < charRefBufLen) {
             if ((returnState & NS_HTML5TOKENIZER_DATA_AND_RCDATA_MASK)) {
               appendStrBuf(charRefBuf, charRefBufMark, charRefBufLen - charRefBufMark);
             } else {
               tokenHandler->characters(charRefBuf, charRefBufMark, charRefBufLen - charRefBufMark);
             }
           }
-          charRefBufLen = 0;
           state = returnState;
           NS_HTML5_CONTINUE(eofloop);
         }
       }
       case NS_HTML5TOKENIZER_CONSUME_NCR:
       case NS_HTML5TOKENIZER_DECIMAL_NRC_LOOP:
       case NS_HTML5TOKENIZER_HEX_NCR_LOOP: {
         if (!seenDigits) {
@@ -3967,17 +3935,17 @@ bool
 nsHtml5Tokenizer::isInDataState()
 {
   return (stateSave == NS_HTML5TOKENIZER_DATA);
 }
 
 void 
 nsHtml5Tokenizer::resetToDataState()
 {
-  clearStrBufAfterUse();
+  strBufLen = 0;
   charRefBufLen = 0;
   stateSave = NS_HTML5TOKENIZER_DATA;
   lastCR = false;
   index = 0;
   forceQuirks = false;
   additional = '\0';
   entCol = -1;
   firstCharKey = -1;
--- a/parser/html/nsHtml5Tokenizer.h
+++ b/parser/html/nsHtml5Tokenizer.h
@@ -153,50 +153,38 @@ class nsHtml5Tokenizer
     {
       return line;
     }
 
     nsHtml5HtmlAttributes* emptyAttributes();
   private:
     inline void appendCharRefBuf(char16_t c)
     {
-      MOZ_RELEASE_ASSERT(charRefBufLen < charRefBuf.length, "Attempted to overrun charRefBuf!");
       charRefBuf[charRefBufLen++] = c;
     }
 
+    inline void clearCharRefBufAndAppend(char16_t c)
+    {
+      charRefBuf[0] = c;
+      charRefBufLen = 1;
+    }
+
     void emitOrAppendCharRefBuf(int32_t returnState);
-    inline void clearStrBufAfterUse()
+    inline void clearStrBufAndAppend(char16_t c)
+    {
+      strBuf[0] = c;
+      strBufLen = 1;
+    }
+
+    inline void clearStrBuf()
     {
       strBufLen = 0;
     }
 
-    inline void clearStrBufBeforeUse()
-    {
-      MOZ_ASSERT(!strBufLen, "strBufLen not reset after previous use!");
-      strBufLen = 0;
-    }
-
-    inline void clearStrBufAfterOneHyphen()
-    {
-      MOZ_ASSERT(strBufLen == 1, "strBufLen length not one!");
-      MOZ_ASSERT(strBuf[0] == '-', "strBuf does not start with a hyphen!");
-      strBufLen = 0;
-    }
-
-    inline void appendStrBuf(char16_t c)
-    {
-      MOZ_ASSERT(strBufLen < strBuf.length, "Previous buffer length insufficient.");
-      if (MOZ_UNLIKELY(strBufLen == strBuf.length)) {
-        if (MOZ_UNLIKELY(!EnsureBufferSpace(1))) {
-          MOZ_CRASH("Unable to recover from buffer reallocation failure");
-        }
-      }
-      strBuf[strBufLen++] = c;
-    }
-
+    void appendStrBuf(char16_t c);
   protected:
     nsString* strBufToString();
   private:
     void strBufToDoctypeName();
     void emitStrBuf();
     inline void appendSecondHyphenToBogusComment()
     {
       appendStrBuf('-');
@@ -207,17 +195,16 @@ class nsHtml5Tokenizer
       errConsecutiveHyphens();
       appendStrBuf(c);
     }
 
     void appendStrBuf(char16_t* buffer, int32_t offset, int32_t length);
     inline void appendCharRefBufToStrBuf()
     {
       appendStrBuf(charRefBuf, 0, charRefBufLen);
-      charRefBufLen = 0;
     }
 
     void emitComment(int32_t provisionalHyphens, int32_t pos);
   protected:
     void flushChars(char16_t* buf, int32_t pos);
   private:
     void strBufToElementNameString();
     int32_t emitCurrentTagToken(bool selfClosing, int32_t pos);
--- a/parser/html/nsHtml5TreeBuilderCppSupplement.h
+++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h
@@ -950,18 +950,18 @@ nsHtml5TreeBuilder::elementPopped(int32_
     mSpeculativeLoadQueue.AppendElement()->InitEndPicture();
   }
   return;
 }
 
 void
 nsHtml5TreeBuilder::accumulateCharacters(const char16_t* aBuf, int32_t aStart, int32_t aLength)
 {
-  MOZ_RELEASE_ASSERT(charBufferLen + aLength <= charBuffer.length,
-                     "About to memcpy past the end of the buffer!");
+  MOZ_ASSERT(charBufferLen + aLength <= charBuffer.length,
+             "About to memcpy past the end of the buffer!");
   memcpy(charBuffer + charBufferLen, aBuf + aStart, sizeof(char16_t) * aLength);
   charBufferLen += aLength;
 }
 
 bool
 nsHtml5TreeBuilder::EnsureBufferSpace(size_t aLength)
 {
   // TODO: Unify nsHtml5Tokenizer::strBuf and nsHtml5TreeBuilder::charBuffer