Bug 1531716 - Part 1: Remove macros for generating the SmallChars array. r=jonco
authorAndré Bargull <andre.bargull@gmail.com>
Mon, 04 Nov 2019 14:02:14 +0000
changeset 500381 0e0afb29911a5a373119caf27b5b65d70a04a731
parent 500380 de9d244524e4be16623f91e9738517baaef75ad7
child 500382 865b84a23e9e349a5556a8a296ddcab73431d761
push id36763
push userrmaries@mozilla.com
push dateMon, 04 Nov 2019 21:44:06 +0000
treeherdermozilla-central@75a7a3400888 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1531716
milestone72.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 1531716 - Part 1: Remove macros for generating the SmallChars array. r=jonco And the two macros to convert to and from SmallChars. Differential Revision: https://phabricator.services.mozilla.com/D51139
js/src/vm/StringType.cpp
js/src/vm/StringType.h
--- a/js/src/vm/StringType.cpp
+++ b/js/src/vm/StringType.cpp
@@ -1191,57 +1191,54 @@ bool JSLinearString::isIndexSlow(const C
 
 template bool JSLinearString::isIndexSlow(const Latin1Char* s, size_t length,
                                           uint32_t* indexp);
 
 template bool JSLinearString::isIndexSlow(const char16_t* s, size_t length,
                                           uint32_t* indexp);
 
 /*
- * Set up some tools to make it easier to generate large tables. After constant
- * folding, for each n, Rn(0) is the comma-separated list R(0), R(1), ...,
- * R(2^n-1). Similary, Rn(k) (for any k and n) generates the list R(k), R(k+1),
- * ..., R(k+2^n-1). To use this, define R appropriately, then use Rn(0) (for
- * some value of n), then undefine R.
- */
-#define R2(n) R(n), R((n) + (1 << 0)), R((n) + (2 << 0)), R((n) + (3 << 0))
-#define R4(n) R2(n), R2((n) + (1 << 2)), R2((n) + (2 << 2)), R2((n) + (3 << 2))
-#define R6(n) R4(n), R4((n) + (1 << 4)), R4((n) + (2 << 4)), R4((n) + (3 << 4))
-#define R7(n) R6(n), R6((n) + (1 << 6))
-
-/*
- * This is used when we generate our table of short strings, so the compiler is
- * happier if we use |c| as few times as possible.
- */
-// clang-format off
-#define FROM_SMALL_CHAR(c) Latin1Char((c) + ((c) < 10 ? '0' :      \
-                                             (c) < 36 ? 'a' - 10 : \
-                                             'A' - 36))
-// clang-format on
-
-/*
  * Declare length-2 strings. We only store strings where both characters are
  * alphanumeric. The lower 10 short chars are the numerals, the next 26 are
  * the lowercase letters, and the next 26 are the uppercase letters.
  */
-// clang-format off
-#define TO_SMALL_CHAR(c) ((c) >= '0' && (c) <= '9' ? (c) - '0' :              \
-                          (c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 10 :         \
-                          (c) >= 'A' && (c) <= 'Z' ? (c) - 'A' + 36 :         \
-                          StaticStrings::INVALID_SMALL_CHAR)
-// clang-format on
+
+constexpr Latin1Char StaticStrings::fromSmallChar(SmallChar c) {
+  if (c < 10) {
+    return c + '0';
+  }
+  if (c < 36) {
+    return c + 'a' - 10;
+  }
+  return c + 'A' - 36;
+}
 
-#define R TO_SMALL_CHAR
-const StaticStrings::SmallChar StaticStrings::toSmallChar[] = {R7(0)};
-#undef R
+constexpr StaticStrings::SmallChar StaticStrings::toSmallChar(uint32_t c) {
+  if (mozilla::IsAsciiDigit(c)) {
+    return c - '0';
+  }
+  if (mozilla::IsAsciiLowercaseAlpha(c)) {
+    return c - 'a' + 10;
+  }
+  if (mozilla::IsAsciiUppercaseAlpha(c)) {
+    return c - 'A' + 36;
+  }
+  return StaticStrings::INVALID_SMALL_CHAR;
+}
 
-#undef R2
-#undef R4
-#undef R6
-#undef R7
+constexpr StaticStrings::SmallCharArray StaticStrings::createSmallCharArray() {
+  SmallCharArray array{};
+  for (size_t i = 0; i < SMALL_CHAR_LIMIT; i++) {
+    array[i] = toSmallChar(i);
+  }
+  return array;
+}
+
+const StaticStrings::SmallCharArray StaticStrings::toSmallCharArray =
+    createSmallCharArray();
 
 bool StaticStrings::init(JSContext* cx) {
   AutoAllocInAtomsZone az(cx);
 
   static_assert(UNIT_STATIC_LIMIT - 1 <= JSString::MAX_LATIN1_CHAR,
                 "Unit strings must fit in Latin1Char.");
 
   using Latin1Range = mozilla::Range<const Latin1Char>;
@@ -1252,31 +1249,31 @@ bool StaticStrings::init(JSContext* cx) 
     if (!s) {
       return false;
     }
     HashNumber hash = mozilla::HashString(&ch, 1);
     unitStaticTable[i] = s->morphAtomizedStringIntoPermanentAtom(hash);
   }
 
   for (uint32_t i = 0; i < NUM_SMALL_CHARS * NUM_SMALL_CHARS; i++) {
-    Latin1Char buffer[] = {FROM_SMALL_CHAR(i >> 6), FROM_SMALL_CHAR(i & 0x3F)};
+    Latin1Char buffer[] = {fromSmallChar(i >> 6), fromSmallChar(i & 0x3F)};
     JSLinearString* s = NewInlineString<NoGC>(cx, Latin1Range(buffer, 2));
     if (!s) {
       return false;
     }
     HashNumber hash = mozilla::HashString(buffer, 2);
     length2StaticTable[i] = s->morphAtomizedStringIntoPermanentAtom(hash);
   }
 
   for (uint32_t i = 0; i < INT_STATIC_LIMIT; i++) {
     if (i < 10) {
       intStaticTable[i] = unitStaticTable[i + '0'];
     } else if (i < 100) {
-      size_t index = ((size_t)TO_SMALL_CHAR((i / 10) + '0') << 6) +
-                     TO_SMALL_CHAR((i % 10) + '0');
+      size_t index = ((size_t)toSmallChar((i / 10) + '0') << 6) +
+                     toSmallChar((i % 10) + '0');
       intStaticTable[i] = length2StaticTable[index];
     } else {
       Latin1Char buffer[] = {Latin1Char('0' + (i / 100)),
                              Latin1Char('0' + ((i / 10) % 10)),
                              Latin1Char('0' + (i % 10))};
       JSLinearString* s = NewInlineString<NoGC>(cx, Latin1Range(buffer, 3));
       if (!s) {
         return false;
--- a/js/src/vm/StringType.h
+++ b/js/src/vm/StringType.h
@@ -1350,29 +1350,45 @@ class StaticStrings {
                                 !std::is_const<CharT>::value>::type>
   MOZ_ALWAYS_INLINE JSAtom* lookup(CharT* chars, size_t length) {
     // Collapse the remaining |CharT*| to |const CharT*| to avoid excess
     // instantiations.
     return lookup(const_cast<const CharT*>(chars), length);
   }
 
  private:
-  typedef uint8_t SmallChar;
+  using SmallChar = uint8_t;
+
+  struct SmallCharArray {
+    SmallChar storage[SMALL_CHAR_LIMIT];
+
+    constexpr SmallChar& operator[](size_t idx) { return storage[idx]; }
+    constexpr const SmallChar& operator[](size_t idx) const {
+      return storage[idx];
+    }
+  };
+
   static const SmallChar INVALID_SMALL_CHAR = -1;
 
   static bool fitsInSmallChar(char16_t c) {
-    return c < SMALL_CHAR_LIMIT && toSmallChar[c] != INVALID_SMALL_CHAR;
+    return c < SMALL_CHAR_LIMIT && toSmallCharArray[c] != INVALID_SMALL_CHAR;
   }
 
-  static const SmallChar toSmallChar[];
+  static constexpr Latin1Char fromSmallChar(SmallChar c);
+
+  static constexpr SmallChar toSmallChar(uint32_t c);
+
+  static constexpr SmallCharArray createSmallCharArray();
+
+  static const SmallCharArray toSmallCharArray;
 
   MOZ_ALWAYS_INLINE JSAtom* getLength2(char16_t c1, char16_t c2) {
     MOZ_ASSERT(fitsInSmallChar(c1));
     MOZ_ASSERT(fitsInSmallChar(c2));
-    size_t index = (size_t(toSmallChar[c1]) << 6) + toSmallChar[c2];
+    size_t index = (size_t(toSmallCharArray[c1]) << 6) + toSmallCharArray[c2];
     return length2StaticTable[index];
   }
   JSAtom* getLength2(uint32_t u) {
     MOZ_ASSERT(u < 100);
     return getLength2('0' + u / 10, '0' + u % 10);
   }
 };