Bug 1542736 - Part 2: Replace JS7_ISHEX with mozilla::IsAsciiHexDigit. r=jwalden
authorAndré Bargull <andre.bargull@gmail.com>
Thu, 11 Apr 2019 11:34:16 +0000
changeset 469053 bac7b9ec895ca1b8da43d3f2b8e1c9f191dac508
parent 469052 5b6bf24882cee31b0d344a0fe1f5f7d5076d3cec
child 469054 ae1ac8554873f1e9b4a574a5110aedb19f99c0c3
push id35856
push usercsabou@mozilla.com
push dateFri, 12 Apr 2019 03:19:48 +0000
treeherdermozilla-central@940684cd1065 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs1542736
milestone68.0a1
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
Bug 1542736 - Part 2: Replace JS7_ISHEX with mozilla::IsAsciiHexDigit. r=jwalden Clang and GCC generate slightly better assembly when IsAsciiHexDigit is called, because the `cmp` instruction for the `< 127` check in JS7_ISHEX is no longer emitted. Differential Revision: https://phabricator.services.mozilla.com/D26505
js/src/builtin/String.cpp
js/src/frontend/TokenStream.cpp
js/src/frontend/TokenStream.h
js/src/util/Text.h
js/src/vm/JSONParser.cpp
--- a/js/src/builtin/String.cpp
+++ b/js/src/builtin/String.cpp
@@ -64,16 +64,17 @@
 
 using namespace js;
 
 using JS::Symbol;
 using JS::SymbolCode;
 
 using mozilla::AsciiAlphanumericToNumber;
 using mozilla::CheckedInt;
+using mozilla::IsAsciiHexDigit;
 using mozilla::IsNaN;
 using mozilla::IsSame;
 using mozilla::PodCopy;
 using mozilla::RangedPtr;
 
 using JS::AutoCheckCannotGC;
 using JS::AutoStableStringChars;
 
@@ -225,34 +226,35 @@ static bool str_escape(JSContext* cx, un
   return true;
 }
 
 template <typename CharT>
 static inline bool Unhex4(const RangedPtr<const CharT> chars,
                           char16_t* result) {
   CharT a = chars[0], b = chars[1], c = chars[2], d = chars[3];
 
-  if (!(JS7_ISHEX(a) && JS7_ISHEX(b) && JS7_ISHEX(c) && JS7_ISHEX(d))) {
+  if (!(IsAsciiHexDigit(a) && IsAsciiHexDigit(b) && IsAsciiHexDigit(c) &&
+        IsAsciiHexDigit(d))) {
     return false;
   }
 
   char16_t unhex = AsciiAlphanumericToNumber(a);
   unhex = (unhex << 4) + AsciiAlphanumericToNumber(b);
   unhex = (unhex << 4) + AsciiAlphanumericToNumber(c);
   unhex = (unhex << 4) + AsciiAlphanumericToNumber(d);
   *result = unhex;
   return true;
 }
 
 template <typename CharT>
 static inline bool Unhex2(const RangedPtr<const CharT> chars,
                           char16_t* result) {
   CharT a = chars[0], b = chars[1];
 
-  if (!(JS7_ISHEX(a) && JS7_ISHEX(b))) {
+  if (!(IsAsciiHexDigit(a) && IsAsciiHexDigit(b))) {
     return false;
   }
 
   *result = (AsciiAlphanumericToNumber(a) << 4) + AsciiAlphanumericToNumber(b);
   return true;
 }
 
 template <typename CharT>
@@ -3975,17 +3977,17 @@ static DecodeResult Decode(StringBuffer&
   for (size_t k = 0; k < length; k++) {
     CharT c = chars[k];
     if (c == '%') {
       size_t start = k;
       if ((k + 2) >= length) {
         return Decode_BadUri;
       }
 
-      if (!JS7_ISHEX(chars[k + 1]) || !JS7_ISHEX(chars[k + 2])) {
+      if (!IsAsciiHexDigit(chars[k + 1]) || !IsAsciiHexDigit(chars[k + 2])) {
         return Decode_BadUri;
       }
 
       uint32_t B = AsciiAlphanumericToNumber(chars[k + 1]) * 16 +
                    AsciiAlphanumericToNumber(chars[k + 2]);
       k += 2;
       if (B < 128) {
         Latin1Char ch = Latin1Char(B);
@@ -4016,17 +4018,18 @@ static DecodeResult Decode(StringBuffer&
         }
 
         for (int j = 1; j < n; j++) {
           k++;
           if (chars[k] != '%') {
             return Decode_BadUri;
           }
 
-          if (!JS7_ISHEX(chars[k + 1]) || !JS7_ISHEX(chars[k + 2])) {
+          if (!IsAsciiHexDigit(chars[k + 1]) ||
+              !IsAsciiHexDigit(chars[k + 2])) {
             return Decode_BadUri;
           }
 
           B = AsciiAlphanumericToNumber(chars[k + 1]) * 16 +
               AsciiAlphanumericToNumber(chars[k + 2]);
           if ((B & 0xC0) != 0x80) {
             return Decode_BadUri;
           }
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -45,16 +45,17 @@
 
 using mozilla::ArrayLength;
 using mozilla::AsciiAlphanumericToNumber;
 using mozilla::AssertedCast;
 using mozilla::DecodeOneUtf8CodePoint;
 using mozilla::IsAscii;
 using mozilla::IsAsciiAlpha;
 using mozilla::IsAsciiDigit;
+using mozilla::IsAsciiHexDigit;
 using mozilla::IsTrailingUnit;
 using mozilla::MakeScopeExit;
 using mozilla::MakeSpan;
 using mozilla::Maybe;
 using mozilla::PointerRangeSize;
 using mozilla::Utf8Unit;
 
 using JS::ReadOnlyCompileOptions;
@@ -1545,17 +1546,17 @@ uint32_t GeneralTokenStreamChars<Unit, A
     // NOTE: |unit| may be EOF here.
     ungetCodeUnit(unit);
     MOZ_ASSERT(this->sourceUnits.previousCodeUnit() == Unit('\\'));
     return 0;
   }
 
   char16_t v;
   unit = getCodeUnit();
-  if (JS7_ISHEX(unit) && this->sourceUnits.matchHexDigits(3, &v)) {
+  if (IsAsciiHexDigit(unit) && this->sourceUnits.matchHexDigits(3, &v)) {
     *codePoint = (AsciiAlphanumericToNumber(unit) << 12) | v;
     return 5;
   }
 
   if (unit == '{') {
     return matchExtendedUnicodeEscape(codePoint);
   }
 
@@ -1578,17 +1579,17 @@ GeneralTokenStreamChars<Unit, AnyCharsAc
   uint32_t leadingZeroes = 0;
   while (unit == '0') {
     leadingZeroes++;
     unit = getCodeUnit();
   }
 
   size_t i = 0;
   uint32_t code = 0;
-  while (JS7_ISHEX(unit) && i < 6) {
+  while (IsAsciiHexDigit(unit) && i < 6) {
     code = (code << 4) | AsciiAlphanumericToNumber(unit);
     unit = getCodeUnit();
     i++;
   }
 
   uint32_t gotten =
       2 +                  // 'u{'
       leadingZeroes + i +  // significant hexdigits
@@ -2586,27 +2587,27 @@ MOZ_MUST_USE bool TokenStreamSpecific<Un
       int radix;
       bool isLegacyOctalOrNoctal = false;
       bool isBigInt = false;
       const Unit* numStart;
       unit = getCodeUnit();
       if (unit == 'x' || unit == 'X') {
         radix = 16;
         unit = getCodeUnit();
-        if (!JS7_ISHEX(unit)) {
+        if (!IsAsciiHexDigit(unit)) {
           // NOTE: |unit| may be EOF here.
           ungetCodeUnit(unit);
           error(JSMSG_MISSING_HEXDIGITS);
           return badToken();
         }
 
         // one past the '0x'
         numStart = this->sourceUnits.addressOfNextCodeUnit() - 1;
 
-        while (JS7_ISHEX(unit)) {
+        while (IsAsciiHexDigit(unit)) {
           unit = getCodeUnit();
         }
       } else if (unit == 'b' || unit == 'B') {
         radix = 2;
         unit = getCodeUnit();
         if (unit != '0' && unit != '1') {
           // NOTE: |unit| may be EOF here.
           ungetCodeUnit(unit);
@@ -3168,17 +3169,17 @@ bool TokenStreamSpecific<Unit, AnyCharsA
                   reportInvalidEscapeError(start, InvalidEscapeType::Unicode);
                   return false;
                 }
                 break;
               }
 
               // Beware: |u3| may be a non-ASCII code point here; if
               // so it'll pass into this |if|-block.
-              if (!JS7_ISHEX(u3)) {
+              if (!IsAsciiHexDigit(u3)) {
                 if (parsingTemplate) {
                   // We put the code unit back so that we read it
                   // on the next pass, which matters if it was
                   // '`' or '\'.
                   ungetCodeUnit(u3);
 
                   TokenStreamAnyChars& anyChars = anyCharsAccess();
                   anyChars.setInvalidTemplateEscape(start,
@@ -3219,17 +3220,17 @@ bool TokenStreamSpecific<Unit, AnyCharsA
             continue;
           }  // end of delimited Unicode escape handling
 
           // Otherwise it must be a fixed-length \uXXXX Unicode escape.
           // If it isn't, this is usually an error -- but if this is a
           // template literal, we must defer error reporting because
           // malformed escapes are okay in *tagged* template literals.
           char16_t v;
-          if (JS7_ISHEX(c2) && this->sourceUnits.matchHexDigits(3, &v)) {
+          if (IsAsciiHexDigit(c2) && this->sourceUnits.matchHexDigits(3, &v)) {
             unit = (AsciiAlphanumericToNumber(c2) << 12) | v;
           } else {
             // Beware: |c2| may not be an ASCII code point here!
             ungetCodeUnit(c2);
             uint32_t start = this->sourceUnits.offset() - 2;
             if (parsingTemplate) {
               TokenStreamAnyChars& anyChars = anyCharsAccess();
               anyChars.setInvalidTemplateEscape(start,
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -1215,17 +1215,17 @@ class SourceUnits {
     MOZ_ASSERT(n <= 4, "hexdigit value can't overflow char16_t");
     if (n > remaining()) {
       return false;
     }
 
     char16_t v = 0;
     for (uint8_t i = 0; i < n; i++) {
       auto unit = CodeUnitValue(ptr[i]);
-      if (!JS7_ISHEX(unit)) {
+      if (!mozilla::IsAsciiHexDigit(unit)) {
         return false;
       }
 
       v = (v << 4) | mozilla::AsciiAlphanumericToNumber(unit);
     }
 
     *out = v;
     ptr += n;
--- a/js/src/util/Text.h
+++ b/js/src/util/Text.h
@@ -27,22 +27,19 @@
 
 class JSLinearString;
 
 /*
  * Shorthands for ASCII (7-bit) decimal and hex conversion.
  * Manually inline isdigit and isxdigit for performance; MSVC doesn't do this
  * for us.
  */
-#define JS7_ISA2F(c) \
-  ((((((unsigned)(c)) - 'a') <= 5) || (((unsigned)(c)) - 'A') <= 5))
 #define JS7_UNDEC(c) ((c) - '0')
 #define JS7_ISOCT(c) ((((unsigned)(c)) - '0') <= 7)
 #define JS7_UNOCT(c) (JS7_UNDEC(c))
-#define JS7_ISHEX(c) ((c) < 128 && (mozilla::IsAsciiDigit(c) || JS7_ISA2F(c)))
 
 static MOZ_ALWAYS_INLINE size_t js_strlen(const char16_t* s) {
   return std::char_traits<char16_t>::length(s);
 }
 
 template <typename CharT>
 extern const CharT* js_strchr_limit(const CharT* s, char16_t c,
                                     const CharT* limit);
--- a/js/src/vm/JSONParser.cpp
+++ b/js/src/vm/JSONParser.cpp
@@ -20,16 +20,17 @@
 #include "vm/Realm.h"
 
 #include "vm/NativeObject-inl.h"
 
 using namespace js;
 
 using mozilla::AsciiAlphanumericToNumber;
 using mozilla::IsAsciiDigit;
+using mozilla::IsAsciiHexDigit;
 using mozilla::RangedPtr;
 
 JSONParserBase::~JSONParserBase() {
   for (size_t i = 0; i < stack.length(); i++) {
     if (stack[i].state == FinishArrayElement) {
       js_delete(&stack[i].elements());
     } else {
       js_delete(&stack[i].properties());
@@ -199,27 +200,27 @@ JSONParserBase::Token JSONParser<CharT>:
         c = '\r';
         break;
       case 't':
         c = '\t';
         break;
 
       case 'u':
         if (end - current < 4 ||
-            !(JS7_ISHEX(current[0]) && JS7_ISHEX(current[1]) &&
-              JS7_ISHEX(current[2]) && JS7_ISHEX(current[3]))) {
+            !(IsAsciiHexDigit(current[0]) && IsAsciiHexDigit(current[1]) &&
+              IsAsciiHexDigit(current[2]) && IsAsciiHexDigit(current[3]))) {
           // Point to the first non-hexadecimal character (which may be
           // missing).
-          if (current == end || !JS7_ISHEX(current[0])) {
+          if (current == end || !IsAsciiHexDigit(current[0])) {
             ;  // already at correct location
-          } else if (current + 1 == end || !JS7_ISHEX(current[1])) {
+          } else if (current + 1 == end || !IsAsciiHexDigit(current[1])) {
             current += 1;
-          } else if (current + 2 == end || !JS7_ISHEX(current[2])) {
+          } else if (current + 2 == end || !IsAsciiHexDigit(current[2])) {
             current += 2;
-          } else if (current + 3 == end || !JS7_ISHEX(current[3])) {
+          } else if (current + 3 == end || !IsAsciiHexDigit(current[3])) {
             current += 3;
           } else {
             MOZ_CRASH("logic error determining first erroneous character");
           }
 
           error("bad Unicode escape");
           return token(Error);
         }