Backed out 11 changesets (bug 1478892, bug 1478587) for build bustages in ../../../dist/bin/gdb-tests on a CLOSED TREE
authorshindli <shindli@mozilla.com>
Sun, 29 Jul 2018 13:33:00 +0300
changeset 428907 fd12c0a357b378feaf48266389bfa0e5c27d766b
parent 428906 9202a03ea48978bc95a2c3c7b23916323649282d
child 428908 a48d7bf63d28c06833e75abcedbd40459b857d9d
push id105803
push usershindli@mozilla.com
push dateSun, 29 Jul 2018 10:33:12 +0000
treeherdermozilla-inbound@fd12c0a357b3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1478892, 1478587
milestone63.0a1
backs out185a4564afa54e1ae4b1fb659d5fc68b656aab6b
c4b339472f4bbe8d5415d668947ac1bb9e3843f4
1a4669e53b4672d06e0bf76ec9ce64e6cad2850d
aa8a0735f30395cbc9ff637a87feec2a0422f624
d1cd66e6d3c3a76928f19ffa7f2f0a045999c8d6
63ccd68e1da3a41f1e99d4e7bb991b6c9308761b
3a111fdc418dc36085b4d1a9a8a5526fedf7c5b3
756cbd89533afb92baffa098676656c01b28761a
9546bfc93c7af1391bbcf901ed1ddc1304da8b80
b335930f96b4ae8bbd1dd168ba258076592ad69a
a47cd872a700a331b13c598a26ec956a28d14308
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 11 changesets (bug 1478892, bug 1478587) for build bustages in ../../../dist/bin/gdb-tests on a CLOSED TREE Backed out changeset 185a4564afa5 (bug 1478892) Backed out changeset c4b339472f4b (bug 1478587) Backed out changeset 1a4669e53b46 (bug 1478587) Backed out changeset aa8a0735f303 (bug 1478587) Backed out changeset d1cd66e6d3c3 (bug 1478587) Backed out changeset 63ccd68e1da3 (bug 1478587) Backed out changeset 3a111fdc418d (bug 1478587) Backed out changeset 756cbd89533a (bug 1478587) Backed out changeset 9546bfc93c7a (bug 1478587) Backed out changeset b335930f96b4 (bug 1478587) Backed out changeset a47cd872a700 (bug 1478587)
js/src/frontend/Parser.cpp
js/src/frontend/TokenStream.cpp
js/src/frontend/TokenStream.h
js/src/jsnum.cpp
js/src/jsnum.h
js/src/vm/JSONParser.cpp
mfbt/Utf8.h
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -18,17 +18,16 @@
  */
 
 #include "frontend/Parser.h"
 
 #include "mozilla/Range.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/TypeTraits.h"
 #include "mozilla/Unused.h"
-#include "mozilla/Utf8.h"
 
 #include <memory>
 #include <new>
 
 #include "jsapi.h"
 #include "jstypes.h"
 
 #include "builtin/ModuleObject.h"
@@ -56,17 +55,16 @@ using namespace js;
 using namespace js::gc;
 
 using mozilla::Maybe;
 using mozilla::Nothing;
 using mozilla::PodCopy;
 using mozilla::PodZero;
 using mozilla::Some;
 using mozilla::Unused;
-using mozilla::Utf8Unit;
 
 using JS::AutoGCRooter;
 
 namespace js {
 namespace frontend {
 
 using DeclaredNamePtr = ParseContext::Scope::DeclaredNamePtr;
 using AddDeclaredNamePtr = ParseContext::Scope::AddDeclaredNamePtr;
@@ -4111,19 +4109,19 @@ Parser<SyntaxParseHandler, CharT>::asmJS
     // Record that the current script source constains some AsmJS, to disable
     // any incremental encoder, as AsmJS cannot be encoded with XDR at the
     // moment.
     if (ss)
         ss->setContainsAsmJS();
     return false;
 }
 
-template <>
+template <typename CharT>
 bool
-Parser<FullParseHandler, char16_t>::asmJS(Node list)
+Parser<FullParseHandler, CharT>::asmJS(Node list)
 {
     // Disable syntax parsing in anything nested inside the asm.js module.
     disableSyntaxParser();
 
     // We should be encountering the "use asm" directive for the first time; if
     // the directive is already, we must have failed asm.js validation and we're
     // reparsing. In that case, don't try to validate again. A non-null
     // newDirectives means we're not in a normal function.
@@ -4149,26 +4147,16 @@ Parser<FullParseHandler, char16_t>::asmJ
     if (!validated) {
         pc->newDirectives->setAsmJS();
         return false;
     }
 
     return true;
 }
 
-template <>
-bool
-Parser<FullParseHandler, Utf8Unit>::asmJS(Node list)
-{
-    // Just succeed without setting the asm.js directive flag.  Given Web
-    // Assembly's rapid advance, it's probably not worth the trouble to really
-    // support UTF-8 asm.js.
-    return true;
-}
-
 template <class ParseHandler, typename CharT>
 inline bool
 GeneralParser<ParseHandler, CharT>::asmJS(Node list)
 {
     return asFinalParser()->asmJS(list);
 }
 
 /*
@@ -9126,16 +9114,19 @@ GeneralParser<ParseHandler, CharT>::noSu
 }
 
 template <typename CharT>
 ParseNode*
 Parser<FullParseHandler, CharT>::newRegExp()
 {
     MOZ_ASSERT(!options().selfHostingMode);
 
+    static_assert(mozilla::IsSame<CharT, char16_t>::value,
+                  "code below will need changing for UTF-8 handling");
+
     // Create the regexp and check its syntax.
     const auto& chars = tokenStream.getCharBuffer();
     RegExpFlag flags = anyChars.currentToken().regExpFlags();
 
     Rooted<RegExpObject*> reobj(context);
     reobj = RegExpObject::create(context, chars.begin(), chars.length(), flags, anyChars, alloc,
                                  TenuredObject);
     if (!reobj)
@@ -9145,21 +9136,24 @@ Parser<FullParseHandler, CharT>::newRegE
 }
 
 template <typename CharT>
 SyntaxParseHandler::Node
 Parser<SyntaxParseHandler, CharT>::newRegExp()
 {
     MOZ_ASSERT(!options().selfHostingMode);
 
+    static_assert(mozilla::IsSame<CharT, char16_t>::value,
+                  "code below will need changing for UTF-8 handling");
+
     // Only check the regexp's syntax, but don't create a regexp object.
     const auto& chars = tokenStream.getCharBuffer();
     RegExpFlag flags = anyChars.currentToken().regExpFlags();
 
-    mozilla::Range<const char16_t> source(chars.begin(), chars.length());
+    mozilla::Range<const CharT> source(chars.begin(), chars.length());
     if (!js::irregexp::ParsePatternSyntax(anyChars, alloc, source, flags & UnicodeFlag))
         return null();
 
     return handler.newRegExp(SyntaxParseHandler::NodeGeneric, pos(), *this);
 }
 
 template <class ParseHandler, typename CharT>
 typename ParseHandler::Node
@@ -10154,19 +10148,15 @@ GeneralParser<ParseHandler, CharT>::expr
                                                  PossibleError* possibleError /* = nullptr */)
 {
     MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Lp));
     return expr(inHandling, yieldHandling, tripledotHandling, possibleError, PredictInvoked);
 }
 
 template class PerHandlerParser<FullParseHandler>;
 template class PerHandlerParser<SyntaxParseHandler>;
-template class GeneralParser<FullParseHandler, Utf8Unit>;
-template class GeneralParser<SyntaxParseHandler, Utf8Unit>;
 template class GeneralParser<FullParseHandler, char16_t>;
 template class GeneralParser<SyntaxParseHandler, char16_t>;
-template class Parser<FullParseHandler, Utf8Unit>;
-template class Parser<SyntaxParseHandler, Utf8Unit>;
 template class Parser<FullParseHandler, char16_t>;
 template class Parser<SyntaxParseHandler, char16_t>;
 
 } /* namespace frontend */
 } /* namespace js */
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -94,32 +94,25 @@ FindReservedWord(const CharT* s, size_t 
 
   got_match:
     return &reservedWords[i];
 
   test_guess:
     rw = &reservedWords[i];
     chars = rw->chars;
     do {
-        if (*s++ != static_cast<unsigned char>(*chars++))
+        if (*s++ != (unsigned char)(*chars++))
             goto no_match;
     } while (--length != 0);
     return rw;
 
   no_match:
     return nullptr;
 }
 
-template <>
-MOZ_ALWAYS_INLINE const ReservedWordInfo*
-FindReservedWord<Utf8Unit>(const Utf8Unit* units, size_t length)
-{
-    return FindReservedWord(Utf8AsUnsignedChars(units), length);
-}
-
 static const ReservedWordInfo*
 FindReservedWord(JSLinearString* str)
 {
     JS::AutoCheckCannotGC nogc;
     return str->hasLatin1Chars()
            ? FindReservedWord(str->latin1Chars(nogc), str->length())
            : FindReservedWord(str->twoByteChars(nogc), str->length());
 }
@@ -1496,48 +1489,48 @@ TokenStreamSpecific<CharT, AnyCharsAcces
 // We have encountered a '\': check for a Unicode escape sequence after it.
 // Return the length of the escape sequence and the encoded code point (by
 // value) if we found a Unicode escape sequence, and skip all code units
 // involed.  Otherwise, return 0 and don't advance along the buffer.
 template<typename CharT, class AnyCharsAccess>
 uint32_t
 GeneralTokenStreamChars<CharT, AnyCharsAccess>::matchUnicodeEscape(uint32_t* codePoint)
 {
-    MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('\\'));
+    MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == '\\');
 
     int32_t unit = getCodeUnit();
     if (unit != 'u') {
         // NOTE: |unit| may be EOF here.
         ungetCodeUnit(unit);
-        MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('\\'));
+        MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == '\\');
         return 0;
     }
 
     char16_t v;
     unit = getCodeUnit();
     if (JS7_ISHEX(unit) && this->sourceUnits.matchHexDigits(3, &v)) {
         *codePoint = (JS7_UNHEX(unit) << 12) | v;
         return 5;
     }
 
     if (unit == '{')
         return matchExtendedUnicodeEscape(codePoint);
 
     // NOTE: |unit| may be EOF here, so this ungets either one or two units.
     ungetCodeUnit(unit);
     ungetCodeUnit('u');
-    MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('\\'));
+    MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == '\\');
     return 0;
 }
 
 template<typename CharT, class AnyCharsAccess>
 uint32_t
 GeneralTokenStreamChars<CharT, AnyCharsAccess>::matchExtendedUnicodeEscape(uint32_t* codePoint)
 {
-    MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('{'));
+    MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == '{');
 
     int32_t unit = getCodeUnit();
 
     // Skip leading zeroes.
     uint32_t leadingZeroes = 0;
     while (unit == '0') {
         leadingZeroes++;
         unit = getCodeUnit();
@@ -1558,49 +1551,49 @@ GeneralTokenStreamChars<CharT, AnyCharsA
         (unit != EOF); // subtract a get if it didn't contribute to length
 
     if (unit == '}' && (leadingZeroes > 0 || i > 0) && code <= unicode::NonBMPMax) {
         *codePoint = code;
         return gotten;
     }
 
     this->sourceUnits.unskipCodeUnits(gotten);
-    MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('\\'));
+    MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == '\\');
     return 0;
 }
 
 template<typename CharT, class AnyCharsAccess>
 uint32_t
 GeneralTokenStreamChars<CharT, AnyCharsAccess>::matchUnicodeEscapeIdStart(uint32_t* codePoint)
 {
     uint32_t length = matchUnicodeEscape(codePoint);
     if (MOZ_LIKELY(length > 0)) {
         if (MOZ_LIKELY(unicode::IsIdentifierStart(*codePoint)))
             return length;
 
         this->sourceUnits.unskipCodeUnits(length);
     }
 
-    MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('\\'));
+    MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == '\\');
     return 0;
 }
 
 template<typename CharT, class AnyCharsAccess>
 bool
 GeneralTokenStreamChars<CharT, AnyCharsAccess>::matchUnicodeEscapeIdent(uint32_t* codePoint)
 {
     uint32_t length = matchUnicodeEscape(codePoint);
     if (MOZ_LIKELY(length > 0)) {
         if (MOZ_LIKELY(unicode::IsIdentifierPart(*codePoint)))
             return true;
 
         this->sourceUnits.unskipCodeUnits(length);
     }
 
-    MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('\\'));
+    MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == '\\');
     return false;
 }
 
 template<typename CharT, class AnyCharsAccess>
 bool
 TokenStreamSpecific<CharT, AnyCharsAccess>::getDirectives(bool isMultiline,
                                                           bool shouldWarnDeprecated)
 {
@@ -1830,17 +1823,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces
             }
 
             if (unit != '\\' || !matchUnicodeEscapeIdent(&codePoint))
                 break;
         } else {
             // |restoreNextRawCharAddress| undoes all gets, and this function
             // doesn't update line/column info.
             char32_t cp;
-            if (!getNonAsciiCodePointDontNormalize(toCharT(unit), &cp))
+            if (!getNonAsciiCodePointDontNormalize(unit, &cp))
                 return false;
 
             codePoint = cp;
             if (!unicode::IsIdentifierPart(codePoint))
                 break;
         }
 
         if (!appendCodePointToCharBuffer(codePoint))
@@ -2108,21 +2101,19 @@ TokenStreamSpecific<CharT, AnyCharsAcces
             // Consume exponential digits.
             do {
                 unit = getCodeUnit();
             } while (IsAsciiDigit(unit));
         }
 
         ungetCodeUnit(unit);
 
-        // "0." and "0e..." numbers parse "." or "e..." here.  Neither range
-        // contains a number, so we can't use |FullStringToDouble|.  (Parse
-        // failures return 0.0, so we'll still get the right result.)
-        if (!StringToDouble(anyCharsAccess().cx,
-                            numStart, this->sourceUnits.addressOfNextCodeUnit(), &dval))
+        const CharT* dummy;
+        if (!js_strtod(anyCharsAccess().cx, numStart, this->sourceUnits.addressOfNextCodeUnit(),
+                       &dummy, &dval))
         {
            return false;
         }
     }
 
     // Number followed by IdentifierStart is an error.  (This is the only place
     // in ECMAScript where token boundary is inadequate to properly separate
     // two tokens, necessitating this unaesthetic lookahead.)
@@ -2147,39 +2138,39 @@ TokenStreamSpecific<CharT, AnyCharsAcces
     newNumberToken(dval, decimalPoint, start, modifier, out);
     return true;
 }
 
 template<typename CharT, class AnyCharsAccess>
 MOZ_MUST_USE bool
 TokenStreamSpecific<CharT, AnyCharsAccess>::regexpLiteral(TokenStart start, TokenKind* out)
 {
-    MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == CharT('/'));
+    MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == '/');
     this->charBuffer.clear();
 
     auto ProcessNonAsciiCodePoint = [this](int32_t lead) {
         MOZ_ASSERT(lead != EOF);
         MOZ_ASSERT(!this->isAsciiCodePoint(lead));
 
         char32_t codePoint;
-        if (!this->getNonAsciiCodePointDontNormalize(this->toCharT(lead), &codePoint))
+        if (!this->getNonAsciiCodePointDontNormalize(lead, &codePoint))
             return false;
 
         if (MOZ_UNLIKELY(codePoint == unicode::LINE_SEPARATOR ||
                          codePoint == unicode::PARA_SEPARATOR))
         {
             this->sourceUnits.ungetLineOrParagraphSeparator();
             this->reportError(JSMSG_UNTERMINATED_REGEXP);
             return false;
         }
 
         return this->appendCodePointToCharBuffer(codePoint);
     };
 
-    auto ReportUnterminatedRegExp = [this](int32_t unit) {
+    auto ReportUnterminatedRegExp = [this](CharT unit) {
         this->ungetCodeUnit(unit);
         this->error(JSMSG_UNTERMINATED_REGEXP);
     };
 
     bool inCharClass = false;
     do {
         int32_t unit = getCodeUnit();
         if (unit == EOF) {
@@ -2524,41 +2515,40 @@ TokenStreamSpecific<CharT, AnyCharsAcces
                 PeekedCodePoint<CharT> peeked = this->sourceUnits.peekCodePoint();
                 if (!peeked.isNone() && unicode::IsIdentifierStart(peeked.codePoint())) {
                     error(JSMSG_IDSTART_AFTER_NUMBER);
                     return badToken();
                 }
             }
 
             double dval;
-            if (!GetFullInteger(anyCharsAccess().cx, numStart,
-                                this->sourceUnits.addressOfNextCodeUnit(), radix, &dval))
+            const char16_t* dummy;
+            if (!GetPrefixInteger(anyCharsAccess().cx, numStart,
+                                  this->sourceUnits.addressOfNextCodeUnit(), radix, &dummy, &dval))
             {
                 return badToken();
             }
+
             newNumberToken(dval, NoDecimal, start, modifier, ttp);
             return true;
         }
 
         MOZ_ASSERT(c1kind == Other);
 
         // This handles everything else.  Simple tokens distinguished solely by
         // TokenKind should set |simpleKind| and break, to share simple-token
         // creation code for all such tokens.  All other tokens must be handled
         // by returning (or by continuing from the loop enclosing this).
         //
         TokenStart start(this->sourceUnits, -1);
         TokenKind simpleKind;
 #ifdef DEBUG
         simpleKind = TokenKind::Limit; // sentinel value for code after switch
 #endif
-
-        // The block a ways above eliminated all non-ASCII, so cast to the
-        // smallest type possible to assist the C++ compiler.
-        switch (AssertedCast<uint8_t>(CodeUnitValue(toCharT(unit)))) {
+        switch (static_cast<CharT>(unit)) {
           case '.':
             unit = getCodeUnit();
             if (IsAsciiDigit(unit)) {
                 return decimalNumber('.', start, this->sourceUnits.addressOfNextCodeUnit() - 2,
                                      modifier, ttp);
             }
 
             if (unit == '.') {
@@ -2757,17 +2747,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces
             break;
 
           default:
             // We consumed a bad ASCII code point/unit.  Put it back so the
             // error location is the bad code point.
             ungetCodeUnit(unit);
             error(JSMSG_ILLEGAL_CHARACTER);
             return badToken();
-        } // switch (AssertedCast<uint8_t>(CodeUnitValue(toCharT(unit))))
+        } // switch (static_cast<CharT>(unit))
 
         MOZ_ASSERT(simpleKind != TokenKind::Limit,
                    "switch-statement should have set |simpleKind| before "
                    "breaking");
 
         newSimpleToken(simpleKind, start, modifier, ttp);
         return true;
     } while (true);
@@ -2793,18 +2783,18 @@ TokenStreamSpecific<CharT, AnyCharsAcces
     auto noteBadToken = MakeScopeExit([this]() {
         this->badToken();
     });
 
     auto ReportPrematureEndOfLiteral = [this, untilChar](unsigned errnum) {
         // Unicode separators aren't end-of-line in template or (as of
         // recently) string literals, so this assertion doesn't allow them.
         MOZ_ASSERT(this->sourceUnits.atEnd() ||
-                   this->sourceUnits.peekCodeUnit() == CharT('\r') ||
-                   this->sourceUnits.peekCodeUnit() == CharT('\n'),
+                   this->sourceUnits.peekCodeUnit() == '\r' ||
+                   this->sourceUnits.peekCodeUnit() == '\n',
                    "must be parked at EOF or EOL to call this function");
 
         // The various errors reported here include language like "in a ''
         // literal" or similar, with '' being '', "", or `` as appropriate.
         const char delimiters[] = { untilChar, untilChar, '\0' };
 
         this->error(errnum, delimiters);
         return;
@@ -2820,32 +2810,36 @@ TokenStreamSpecific<CharT, AnyCharsAcces
             return false;
         }
 
         // Non-ASCII code points are always directly appended -- even
         // U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR that are
         // ordinarily LineTerminatorSequences.  (They contribute their literal
         // values to template and [as of recently] string literals, but they're
         // line terminators when computing line/column coordinates.)  Handle
-        // the non-ASCII case early for readability.
+        // the non-ASCI case early for readability.
         if (MOZ_UNLIKELY(!isAsciiCodePoint(unit))) {
-            char32_t cp;
-            if (!getNonAsciiCodePointDontNormalize(toCharT(unit), &cp))
-                return false;
-
-            if (MOZ_UNLIKELY(cp == unicode::LINE_SEPARATOR || cp == unicode::PARA_SEPARATOR)) {
+            static_assert(mozilla::IsSame<CharT, char16_t>::value,
+                          "need a getNonAsciiCodePoint that doesn't normalize "
+                          "LineTerminatorSequences to correctly handle UTF-8");
+
+            int32_t codePoint;
+            if (unit == unicode::LINE_SEPARATOR || unit == unicode::PARA_SEPARATOR) {
                 if (!updateLineInfoForEOL())
                     return false;
 
                 anyCharsAccess().updateFlagsForEOL();
+
+                codePoint = unit;
             } else {
-                MOZ_ASSERT(!IsLineTerminator(cp));
+                if (!getNonAsciiCodePoint(unit, &codePoint))
+                    return false;
             }
 
-            if (!appendCodePointToCharBuffer(cp))
+            if (!appendCodePointToCharBuffer(codePoint))
                 return false;
 
             continue;
         }
 
         if (unit == '\\') {
             // When parsing templates, we don't immediately report errors for
             // invalid escapes; these are handled by the parser.  We don't
@@ -2870,19 +2864,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces
                 if (codePoint != '\n') {
                     if (!this->charBuffer.append(unit))
                         return false;
                 }
 
                 continue;
             }
 
-            // The block above eliminated all non-ASCII, so cast to the
-            // smallest type possible to assist the C++ compiler.
-            switch (AssertedCast<uint8_t>(CodeUnitValue(toCharT(unit)))) {
+            switch (static_cast<CharT>(unit)) {
               case 'b': unit = '\b'; break;
               case 'f': unit = '\f'; break;
               case 'n': unit = '\n'; break;
               case 'r': unit = '\r'; break;
               case 't': unit = '\t'; break;
               case 'v': unit = '\v'; break;
 
               case '\r':
@@ -3069,17 +3061,17 @@ TokenStreamSpecific<CharT, AnyCharsAcces
                         else
                             val = save;
                     }
                 }
 
                 unit = char16_t(val);
                 break;
               } // default
-            } // switch (AssertedCast<uint8_t>(CodeUnitValue(toCharT(unit))))
+            }
 
             if (!this->charBuffer.append(unit))
                 return false;
 
             continue;
         } // (unit == '\\')
 
         if (unit == '\r' || unit == '\n') {
@@ -3166,20 +3158,16 @@ TokenStreamChars<Utf8Unit, ParserAnyChar
 template class
 TokenStreamChars<Utf8Unit, ParserAnyCharsAccess<GeneralParser<SyntaxParseHandler, Utf8Unit>>>;
 template class
 TokenStreamChars<char16_t, ParserAnyCharsAccess<GeneralParser<FullParseHandler, char16_t>>>;
 template class
 TokenStreamChars<char16_t, ParserAnyCharsAccess<GeneralParser<SyntaxParseHandler, char16_t>>>;
 
 template class
-TokenStreamSpecific<Utf8Unit, ParserAnyCharsAccess<GeneralParser<FullParseHandler, Utf8Unit>>>;
-template class
-TokenStreamSpecific<Utf8Unit, ParserAnyCharsAccess<GeneralParser<SyntaxParseHandler, Utf8Unit>>>;
-template class
 TokenStreamSpecific<char16_t, ParserAnyCharsAccess<GeneralParser<FullParseHandler, char16_t>>>;
 template class
 TokenStreamSpecific<char16_t, ParserAnyCharsAccess<GeneralParser<SyntaxParseHandler, char16_t>>>;
 
 } // namespace frontend
 
 } // namespace js
 
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -1920,17 +1920,17 @@ class GeneralTokenStreamChars
      *
      * Because of these limitations, only use this if (a) the resulting code
      * unit is guaranteed to be ungotten (by ungetCodeUnit()) if it's an EOL,
      * and (b) the line-related state (lineno, linebase) is not used before
      * it's ungotten.
      */
     int32_t getCodeUnit() {
         if (MOZ_LIKELY(!this->sourceUnits.atEnd()))
-            return CodeUnitValue(this->sourceUnits.getCodeUnit());
+            return this->sourceUnits.getCodeUnit();
 
         anyCharsAccess().flags.isEOF = true;
         return EOF;
     }
 
     void ungetCodeUnit(int32_t c) {
         MOZ_ASSERT_IF(c == EOF, anyCharsAccess().flags.isEOF);
 
@@ -2310,17 +2310,16 @@ class MOZ_STACK_CLASS TokenStreamSpecifi
     using GeneralCharsBase::matchUnicodeEscapeIdStart;
     using GeneralCharsBase::newAtomToken;
     using GeneralCharsBase::newNameToken;
     using GeneralCharsBase::newNumberToken;
     using GeneralCharsBase::newRegExpToken;
     using GeneralCharsBase::newSimpleToken;
     using CharsBase::peekCodeUnit;
     // Deliberately don't |using| |sourceUnits| because of bug 1472569.  :-(
-    using CharsBase::toCharT;
     using GeneralCharsBase::ungetCodeUnit;
     using GeneralCharsBase::updateLineInfoForEOL;
 
     template<typename CharU> friend class TokenStreamPosition;
 
   public:
     TokenStreamSpecific(JSContext* cx, const ReadOnlyCompileOptions& options,
                         const CharT* base, size_t length);
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -10,17 +10,16 @@
 
 #include "jsnum.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/RangedPtr.h"
 #include "mozilla/TextUtils.h"
-#include "mozilla/Utf8.h"
 
 #ifdef HAVE_LOCALECONV
 #include <locale.h>
 #endif
 #include <math.h>
 #include <string.h>
 
 #include "jstypes.h"
@@ -43,24 +42,21 @@
 #include "vm/StringType-inl.h"
 
 using namespace js;
 
 using mozilla::Abs;
 using mozilla::ArrayLength;
 using mozilla::AsciiAlphanumericToNumber;
 using mozilla::IsAsciiAlphanumeric;
-using mozilla::IsAsciiDigit;
 using mozilla::Maybe;
 using mozilla::MinNumberValue;
 using mozilla::NegativeInfinity;
 using mozilla::PositiveInfinity;
 using mozilla::RangedPtr;
-using mozilla::Utf8AsUnsignedChars;
-using mozilla::Utf8Unit;
 
 using JS::AutoCheckCannotGC;
 using JS::GenericNaN;
 using JS::ToInt8;
 using JS::ToInt16;
 using JS::ToInt32;
 using JS::ToInt64;
 using JS::ToUint8;
@@ -260,70 +256,48 @@ js::GetPrefixInteger(JSContext* cx, cons
         return ComputeAccurateDecimalInteger(cx, start, s, dp);
 
     if ((base & (base - 1)) == 0)
         *dp = ComputeAccurateBinaryBaseInteger(start, s, base);
 
     return true;
 }
 
-namespace js {
-
 template bool
-GetPrefixInteger(JSContext* cx, const char16_t* start, const char16_t* end, int base,
-                 const char16_t** endp, double* dp);
+js::GetPrefixInteger(JSContext* cx, const char16_t* start, const char16_t* end, int base,
+                     const char16_t** endp, double* dp);
 
 template bool
-GetPrefixInteger(JSContext* cx, const Latin1Char* start, const Latin1Char* end, int base,
-                 const Latin1Char** endp, double* dp);
+js::GetPrefixInteger(JSContext* cx, const Latin1Char* start, const Latin1Char* end,
+                     int base, const Latin1Char** endp, double* dp);
 
-} // namespace js
-
-template <typename CharT>
 bool
-js::GetDecimalInteger(JSContext* cx, const CharT* start, const CharT* end, double* dp)
+js::GetDecimalInteger(JSContext* cx, const char16_t* start, const char16_t* end, double* dp)
 {
     MOZ_ASSERT(start <= end);
 
-    const CharT* s = start;
+    const char16_t* s = start;
     double d = 0.0;
     for (; s < end; s++) {
-        CharT c = *s;
-        MOZ_ASSERT(IsAsciiDigit(c));
+        char16_t c = *s;
+        MOZ_ASSERT('0' <= c && c <= '9');
         int digit = c - '0';
         d = d * 10 + digit;
     }
 
     *dp = d;
 
     // If we haven't reached the limit of integer precision, we're done.
     if (d < DOUBLE_INTEGRAL_PRECISION_LIMIT)
         return true;
 
     // Otherwise compute the correct integer from the prefix of valid digits.
     return ComputeAccurateDecimalInteger(cx, start, s, dp);
 }
 
-namespace js {
-
-template bool
-GetDecimalInteger(JSContext* cx, const char16_t* start, const char16_t* end, double* dp);
-
-template bool
-GetDecimalInteger(JSContext* cx, const Latin1Char* start, const Latin1Char* end, double* dp);
-
-template <>
-bool
-GetDecimalInteger<Utf8Unit>(JSContext* cx, const Utf8Unit* start, const Utf8Unit* end, double* dp)
-{
-    return GetDecimalInteger(cx, Utf8AsUnsignedChars(start), Utf8AsUnsignedChars(end), dp);
-}
-
-} // namespace js
-
 static bool
 num_parseFloat(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() == 0) {
         args.rval().setNaN();
         return true;
--- a/js/src/jsnum.h
+++ b/js/src/jsnum.h
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jsnum_h
 #define jsnum_h
 
 #include "mozilla/Compiler.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/Range.h"
-#include "mozilla/Utf8.h"
 
 #include "NamespaceImports.h"
 
 #include "js/Conversions.h"
 
 #include "vm/StringType.h"
 
 
@@ -141,58 +140,23 @@ ParseDecimalNumber(const mozilla::Range<
  * If [start, end) does not begin with a number with the specified base,
  * *dp == 0 and *endp == start upon return.
  */
 template <typename CharT>
 extern MOZ_MUST_USE bool
 GetPrefixInteger(JSContext* cx, const CharT* start, const CharT* end, int base,
                  const CharT** endp, double* dp);
 
-inline const char16_t*
-ToRawChars(const char16_t* units)
-{
-    return units;
-}
-
-inline const unsigned char*
-ToRawChars(const unsigned char* units)
-{
-    return units;
-}
-
-inline const unsigned char*
-ToRawChars(const mozilla::Utf8Unit* units)
-{
-    return mozilla::Utf8AsUnsignedChars(units);
-}
-
-/**
- * Like the prior function, but [start, end) must all be digits in the given
- * base (and so this function doesn't take a useless outparam).
+/*
+ * This is like GetPrefixInteger, but only deals with base 10, and doesn't have
+ * and |endp| outparam.  It should only be used when the characters are known to
+ * only contain digits.
  */
-template <typename CharT>
 extern MOZ_MUST_USE bool
-GetFullInteger(JSContext* cx, const CharT* start, const CharT* end, int base, double* dp)
-{
-    decltype(ToRawChars(start)) realEnd;
-    if (GetPrefixInteger(cx, ToRawChars(start), ToRawChars(end), base, &realEnd, dp)) {
-        MOZ_ASSERT(end == static_cast<const void*>(realEnd));
-        return true;
-    }
-    return false;
-}
-
-/*
- * This is like GetPrefixInteger, but it only deals with base 10 and doesn't
- * have an |endp| outparam.  It should only be used when the characters are
- * known to only contain digits.
- */
-template <typename CharT>
-extern MOZ_MUST_USE bool
-GetDecimalInteger(JSContext* cx, const CharT* start, const CharT* end, double* dp);
+GetDecimalInteger(JSContext* cx, const char16_t* start, const char16_t* end, double* dp);
 
 extern MOZ_MUST_USE bool
 StringToNumber(JSContext* cx, JSString* str, double* result);
 
 /* ES5 9.3 ToNumber, overwriting *vp with the appropriate number value. */
 MOZ_ALWAYS_INLINE MOZ_MUST_USE bool
 ToNumber(JSContext* cx, JS::MutableHandleValue vp)
 {
@@ -242,45 +206,16 @@ num_parseInt(JSContext* cx, unsigned arg
  */
 template <typename CharT>
 extern MOZ_MUST_USE bool
 js_strtod(JSContext* cx, const CharT* begin, const CharT* end,
           const CharT** dEnd, double* d);
 
 namespace js {
 
-/**
- * Like js_strtod, but for when you don't require a |dEnd| argument *and* it's
- * possible that the number in the string will not occupy the full [begin, end)
- * range.
- */
-template <typename CharT>
-extern MOZ_MUST_USE bool
-StringToDouble(JSContext* cx, const CharT* begin, const CharT* end, double* d)
-{
-    decltype(ToRawChars(begin)) dummy;
-    return js_strtod(cx, ToRawChars(begin), ToRawChars(end), &dummy, d);
-}
-
-/**
- * Like js_strtod, but for when the number always constitutes the entire range
- * (and so |dEnd| would be a value already known).
- */
-template <typename CharT>
-extern MOZ_MUST_USE bool
-FullStringToDouble(JSContext* cx, const CharT* begin, const CharT* end, double* d)
-{
-    decltype(ToRawChars(begin)) realEnd;
-    if (js_strtod(cx, ToRawChars(begin), ToRawChars(end), &realEnd, d)) {
-        MOZ_ASSERT(end == static_cast<const void*>(realEnd));
-        return true;
-    }
-    return false;
-}
-
 extern MOZ_MUST_USE bool
 num_toString(JSContext* cx, unsigned argc, Value* vp);
 
 extern MOZ_MUST_USE bool
 num_valueOf(JSContext* cx, unsigned argc, Value* vp);
 
 /*
  * Returns true if the given value is definitely an index: that is, the value
--- a/js/src/vm/JSONParser.cpp
+++ b/js/src/vm/JSONParser.cpp
@@ -284,18 +284,20 @@ JSONParser<CharT>::readNumber()
             // largest number a double can represent with integral precision),
             // parse it using a decimal-only parser.  This comparison is
             // conservative but faster than a fully-precise check.
             double d = ParseDecimalNumber(chars);
             return numberToken(negative ? -d : d);
         }
 
         double d;
-        if (!GetFullInteger(cx, digitStart.get(), current.get(), 10, &d))
+        const CharT* dummy;
+        if (!GetPrefixInteger(cx, digitStart.get(), current.get(), 10, &dummy, &d))
             return token(OOM);
+        MOZ_ASSERT(current == dummy);
         return numberToken(negative ? -d : d);
     }
 
     /* (\.[0-9]+)? */
     if (current < end && *current == '.') {
         if (++current == end) {
             error("missing digits after decimal point");
             return token(Error);
@@ -328,18 +330,20 @@ JSONParser<CharT>::readNumber()
         }
         while (++current < end) {
             if (!IsAsciiDigit(*current))
                 break;
         }
     }
 
     double d;
-    if (!FullStringToDouble(cx, digitStart.get(), current.get(), &d))
+    const CharT* finish;
+    if (!js_strtod(cx, digitStart.get(), current.get(), &finish, &d))
         return token(OOM);
+    MOZ_ASSERT(current == finish);
     return numberToken(negative ? -d : d);
 }
 
 static inline bool
 IsJSONWhitespace(char16_t c)
 {
     return c == '\t' || c == '\r' || c == '\n' || c == ' ';
 }
--- a/mfbt/Utf8.h
+++ b/mfbt/Utf8.h
@@ -193,50 +193,16 @@ public:
     return static_cast<uint8_t>(mValue);
   }
 
   // We currently don't expose |&mValue|.  |UnicodeData| sort of does, but
   // that's a somewhat separate concern, justified in different comments in
   // that other code.
 };
 
-/**
- * Reinterpret the address of a UTF-8 code unit as |const unsigned char*|.
- *
- * Assuming proper backing has been set up, the resulting |const unsigned char*|
- * may validly be dereferenced.
- *
- * No access is provided to mutate this underlying memory as |unsigned char|.
- * Presently memory inside |Utf8Unit| is *only* stored as |char|, and we are
- * loath to offer a way to write non-|char| data until absolutely necessary.
- */
-inline const unsigned char*
-Utf8AsUnsignedChars(const Utf8Unit* aUnits)
-{
-  static_assert(sizeof(Utf8Unit) == sizeof(unsigned char),
-                "sizes must match to permissibly reinterpret_cast<>");
-  static_assert(alignof(Utf8Unit) == alignof(unsigned char),
-                "alignment must match to permissibly reinterpret_cast<>");
-
-  // The static_asserts above only enable the reinterpret_cast<> to occur.
-  //
-  // Dereferencing the resulting pointer is a separate question.  Any object's
-  // memory may be interpreted as |unsigned char| per C++11 [basic.lval]p10, but
-  // this doesn't guarantee what values will be observed.  If |char| is
-  // implemented to act like |unsigned char|, we're good to go: memory for the
-  // |char| in |Utf8Unit| acts as we need.  But if |char| is implemented to act
-  // like |signed char|, dereferencing produces the right value only if the
-  // |char| types all use two's-complement representation.  Every modern
-  // compiler does this, and there's a C++ proposal to standardize it.
-  // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0907r0.html   So
-  // *technically* this is implementation-defined -- but everyone does it and
-  // this behavior is being standardized.
-  return reinterpret_cast<const unsigned char*>(aUnits);
-}
-
 /** Returns true iff |aUnit| is an ASCII value. */
 inline bool
 IsAscii(Utf8Unit aUnit)
 {
   return IsAscii(aUnit.toUint8());
 }
 
 /**