Bug 1638154: Refresh import r=tcampbell
authorIain Ireland <iireland@mozilla.com>
Thu, 21 May 2020 17:33:29 +0000
changeset 531520 1011b207d264908077a1ac1aeefbe28bc386dfdb
parent 531519 a2078244558da928f2df9943595ab8ad03485c29
child 531521 979cea3e1aa94b6234d7863df2f905d066329816
push id116700
push useriireland@mozilla.com
push dateThu, 21 May 2020 19:38:40 +0000
treeherderautoland@979cea3e1aa9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1638154
milestone78.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 1638154: Refresh import r=tcampbell This patch was auto-generated with `new-regexp/import-irregexp.py`. Differential Revision: https://phabricator.services.mozilla.com/D76250
js/src/new-regexp/IRREGEXP_VERSION
js/src/new-regexp/regexp-bytecode-generator.cc
js/src/new-regexp/regexp-bytecode-generator.h
js/src/new-regexp/regexp-bytecodes.h
js/src/new-regexp/regexp-compiler-tonode.cc
js/src/new-regexp/regexp-interpreter.cc
js/src/new-regexp/regexp-nodes.h
--- a/js/src/new-regexp/IRREGEXP_VERSION
+++ b/js/src/new-regexp/IRREGEXP_VERSION
@@ -1,2 +1,2 @@
 Imported using import-irregexp.py from:
-https://github.com/v8/v8/tree/a3fbabc726384ea1021955a640add8cfe6a431af/src/regexp
+https://github.com/v8/v8/tree/ccd53957650b556cec412d1fd490cb9c50d2a6ff/src/regexp
--- a/js/src/new-regexp/regexp-bytecode-generator.cc
+++ b/js/src/new-regexp/regexp-bytecode-generator.cc
@@ -175,17 +175,17 @@ void RegExpBytecodeGenerator::CheckGreed
 
 void RegExpBytecodeGenerator::LoadCurrentCharacterImpl(int cp_offset,
                                                        Label* on_failure,
                                                        bool check_bounds,
                                                        int characters,
                                                        int eats_at_least) {
   DCHECK_GE(eats_at_least, characters);
   if (eats_at_least > characters && check_bounds) {
-    DCHECK(is_uint24(cp_offset + eats_at_least));
+    DCHECK(is_int24(cp_offset + eats_at_least));
     Emit(BC_CHECK_CURRENT_POSITION, cp_offset + eats_at_least);
     EmitOrLink(on_failure);
     check_bounds = false;  // Load below doesn't need to check.
   }
 
   DCHECK_LE(kMinCPOffset, cp_offset);
   DCHECK_GE(kMaxCPOffset, cp_offset);
   int bytecode;
--- a/js/src/new-regexp/regexp-bytecode-generator.h
+++ b/js/src/new-regexp/regexp-bytecode-generator.h
@@ -17,71 +17,70 @@ class V8_EXPORT_PRIVATE RegExpBytecodeGe
   // into a buffer, with the instructions starting from the beginning and the
   // relocation information starting from the end of the buffer. See CodeDesc
   // for a detailed comment on the layout (globals.h).
   //
   // The assembler allocates and grows its own buffer, and buffer_size
   // determines the initial buffer size. The buffer is owned by the assembler
   // and deallocated upon destruction of the assembler.
   RegExpBytecodeGenerator(Isolate* isolate, Zone* zone);
-  virtual ~RegExpBytecodeGenerator();
+  ~RegExpBytecodeGenerator() override;
   // The byte-code interpreter checks on each push anyway.
-  virtual int stack_limit_slack() { return 1; }
-  virtual bool CanReadUnaligned() { return false; }
-  virtual void Bind(Label* label);
-  virtual void AdvanceCurrentPosition(int by);  // Signed cp change.
-  virtual void PopCurrentPosition();
-  virtual void PushCurrentPosition();
-  virtual void Backtrack();
-  virtual void GoTo(Label* label);
-  virtual void PushBacktrack(Label* label);
-  virtual bool Succeed();
-  virtual void Fail();
-  virtual void PopRegister(int register_index);
-  virtual void PushRegister(int register_index,
-                            StackCheckFlag check_stack_limit);
-  virtual void AdvanceRegister(int reg, int by);  // r[reg] += by.
-  virtual void SetCurrentPositionFromEnd(int by);
-  virtual void SetRegister(int register_index, int to);
-  virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
-  virtual void ClearRegisters(int reg_from, int reg_to);
-  virtual void ReadCurrentPositionFromRegister(int reg);
-  virtual void WriteStackPointerToRegister(int reg);
-  virtual void ReadStackPointerFromRegister(int reg);
-  virtual void LoadCurrentCharacterImpl(int cp_offset, Label* on_end_of_input,
-                                        bool check_bounds, int characters,
-                                        int eats_at_least);
-  virtual void CheckCharacter(unsigned c, Label* on_equal);
-  virtual void CheckCharacterAfterAnd(unsigned c, unsigned mask,
-                                      Label* on_equal);
-  virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
-  virtual void CheckCharacterLT(uc16 limit, Label* on_less);
-  virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
-  virtual void CheckAtStart(int cp_offset, Label* on_at_start);
-  virtual void CheckNotAtStart(int cp_offset, Label* on_not_at_start);
-  virtual void CheckNotCharacter(unsigned c, Label* on_not_equal);
-  virtual void CheckNotCharacterAfterAnd(unsigned c, unsigned mask,
-                                         Label* on_not_equal);
-  virtual void CheckNotCharacterAfterMinusAnd(uc16 c, uc16 minus, uc16 mask,
-                                              Label* on_not_equal);
-  virtual void CheckCharacterInRange(uc16 from, uc16 to, Label* on_in_range);
-  virtual void CheckCharacterNotInRange(uc16 from, uc16 to,
-                                        Label* on_not_in_range);
-  virtual void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set);
-  virtual void CheckNotBackReference(int start_reg, bool read_backward,
-                                     Label* on_no_match);
-  virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
-                                               bool read_backward,
-                                               Label* on_no_match);
-  virtual void IfRegisterLT(int register_index, int comparand, Label* if_lt);
-  virtual void IfRegisterGE(int register_index, int comparand, Label* if_ge);
-  virtual void IfRegisterEqPos(int register_index, Label* if_eq);
+  int stack_limit_slack() override { return 1; }
+  bool CanReadUnaligned() override { return false; }
+  void Bind(Label* label) override;
+  void AdvanceCurrentPosition(int by) override;  // Signed cp change.
+  void PopCurrentPosition() override;
+  void PushCurrentPosition() override;
+  void Backtrack() override;
+  void GoTo(Label* label) override;
+  void PushBacktrack(Label* label) override;
+  bool Succeed() override;
+  void Fail() override;
+  void PopRegister(int register_index) override;
+  void PushRegister(int register_index,
+                    StackCheckFlag check_stack_limit) override;
+  void AdvanceRegister(int reg, int by) override;  // r[reg] += by.
+  void SetCurrentPositionFromEnd(int by) override;
+  void SetRegister(int register_index, int to) override;
+  void WriteCurrentPositionToRegister(int reg, int cp_offset) override;
+  void ClearRegisters(int reg_from, int reg_to) override;
+  void ReadCurrentPositionFromRegister(int reg) override;
+  void WriteStackPointerToRegister(int reg) override;
+  void ReadStackPointerFromRegister(int reg) override;
+  void LoadCurrentCharacterImpl(int cp_offset, Label* on_end_of_input,
+                                bool check_bounds, int characters,
+                                int eats_at_least) override;
+  void CheckCharacter(unsigned c, Label* on_equal) override;
+  void CheckCharacterAfterAnd(unsigned c, unsigned mask,
+                              Label* on_equal) override;
+  void CheckCharacterGT(uc16 limit, Label* on_greater) override;
+  void CheckCharacterLT(uc16 limit, Label* on_less) override;
+  void CheckGreedyLoop(Label* on_tos_equals_current_position) override;
+  void CheckAtStart(int cp_offset, Label* on_at_start) override;
+  void CheckNotAtStart(int cp_offset, Label* on_not_at_start) override;
+  void CheckNotCharacter(unsigned c, Label* on_not_equal) override;
+  void CheckNotCharacterAfterAnd(unsigned c, unsigned mask,
+                                 Label* on_not_equal) override;
+  void CheckNotCharacterAfterMinusAnd(uc16 c, uc16 minus, uc16 mask,
+                                      Label* on_not_equal) override;
+  void CheckCharacterInRange(uc16 from, uc16 to, Label* on_in_range) override;
+  void CheckCharacterNotInRange(uc16 from, uc16 to,
+                                Label* on_not_in_range) override;
+  void CheckBitInTable(Handle<ByteArray> table, Label* on_bit_set) override;
+  void CheckNotBackReference(int start_reg, bool read_backward,
+                             Label* on_no_match) override;
+  void CheckNotBackReferenceIgnoreCase(int start_reg, bool read_backward,
+                                       Label* on_no_match) override;
+  void IfRegisterLT(int register_index, int comparand, Label* if_lt) override;
+  void IfRegisterGE(int register_index, int comparand, Label* if_ge) override;
+  void IfRegisterEqPos(int register_index, Label* if_eq) override;
 
-  virtual IrregexpImplementation Implementation();
-  virtual Handle<HeapObject> GetCode(Handle<String> source);
+  IrregexpImplementation Implementation() override;
+  Handle<HeapObject> GetCode(Handle<String> source) override;
 
  private:
   void Expand();
   // Code and bitmap emission.
   inline void EmitOrLink(Label* label);
   inline void Emit32(uint32_t x);
   inline void Emit16(uint32_t x);
   inline void Emit8(uint32_t x);
--- a/js/src/new-regexp/regexp-bytecodes.h
+++ b/js/src/new-regexp/regexp-bytecodes.h
@@ -21,16 +21,17 @@ constexpr int BYTECODE_MASK = kRegExpPad
 // has 24 bits, but it can be positive and negative so only use 23 bits for
 // positive values.
 const unsigned int MAX_FIRST_ARG = 0x7fffffu;
 const int BYTECODE_SHIFT = 8;
 STATIC_ASSERT(1 << BYTECODE_SHIFT > BYTECODE_MASK);
 
 // TODO(pthier): Argument offsets of bytecodes should be easily accessible by
 // name or at least by position.
+// TODO(jgruber): More precise types (e.g. int32/uint32 instead of value32).
 #define BYTECODE_ITERATOR(V)                                                   \
   V(BREAK, 0, 4)              /* bc8                                        */ \
   V(PUSH_CP, 1, 4)            /* bc8 pad24                                  */ \
   V(PUSH_BT, 2, 8)            /* bc8 pad24 offset32                         */ \
   V(PUSH_REGISTER, 3, 4)      /* bc8 reg_idx24                              */ \
   V(SET_REGISTER_TO_CP, 4, 8) /* bc8 reg_idx24 offset32                     */ \
   V(SET_CP_TO_REGISTER, 5, 4) /* bc8 reg_idx24                              */ \
   V(SET_REGISTER_TO_SP, 6, 4) /* bc8 reg_idx24                              */ \
--- a/js/src/new-regexp/regexp-compiler-tonode.cc
+++ b/js/src/new-regexp/regexp-compiler-tonode.cc
@@ -431,16 +431,18 @@ RegExpNode* RegExpCharacterClass::ToNode
       return UnanchoredAdvance(compiler, on_success);
     } else {
       ChoiceNode* result = new (zone) ChoiceNode(2, zone);
       UnicodeRangeSplitter splitter(ranges);
       AddBmpCharacters(compiler, result, on_success, &splitter);
       AddNonBmpSurrogatePairs(compiler, result, on_success, &splitter);
       AddLoneLeadSurrogates(compiler, result, on_success, &splitter);
       AddLoneTrailSurrogates(compiler, result, on_success, &splitter);
+      static constexpr int kMaxRangesToInline = 32;  // Arbitrary.
+      if (ranges->length() > kMaxRangesToInline) result->SetDoNotInline();
       return result;
     }
   } else {
     return new (zone) TextNode(this, compiler->read_backward(), on_success);
   }
 }
 
 int CompareFirstChar(RegExpTree* const* a, RegExpTree* const* b) {
--- a/js/src/new-regexp/regexp-interpreter.cc
+++ b/js/src/new-regexp/regexp-interpreter.cc
@@ -88,16 +88,28 @@ uint32_t Load16Aligned(const byte* pc) {
   return *reinterpret_cast<const uint16_t*>(pc);
 }
 
 int32_t Load16AlignedSigned(const byte* pc) {
   DCHECK_EQ(0, reinterpret_cast<intptr_t>(pc) & 1);
   return *reinterpret_cast<const int16_t*>(pc);
 }
 
+// Helpers to access the packed argument. Takes the 32 bits containing the
+// current bytecode, where the 8 LSB contain the bytecode and the rest contains
+// a packed 24-bit argument.
+// TODO(jgruber): Specify signed-ness in bytecode signature declarations, and
+// police restrictions during bytecode generation.
+int32_t LoadPacked24Signed(int32_t bytecode_and_packed_arg) {
+  return bytecode_and_packed_arg >> BYTECODE_SHIFT;
+}
+uint32_t LoadPacked24Unsigned(int32_t bytecode_and_packed_arg) {
+  return static_cast<uint32_t>(bytecode_and_packed_arg) >> BYTECODE_SHIFT;
+}
+
 // A simple abstraction over the backtracking stack used by the interpreter.
 //
 // Despite the name 'backtracking' stack, it's actually used as a generic stack
 // that stores both program counters (= offsets into the bytecode) and generic
 // integer values.
 class BacktrackStack {
  public:
   BacktrackStack() = default;
@@ -284,16 +296,22 @@ IrregexpInterpreter::Result HandleInterr
 
 bool CheckBitInTable(const uint32_t current_char, const byte* const table) {
   int mask = RegExpMacroAssembler::kTableMask;
   int b = table[(current_char & mask) >> kBitsPerByteLog2];
   int bit = (current_char & (kBitsPerByte - 1));
   return (b & (1 << bit)) != 0;
 }
 
+// Returns true iff 0 <= index < length.
+bool IndexIsInBounds(int index, int length) {
+  DCHECK_GE(length, 0);
+  return static_cast<uintptr_t>(index) < static_cast<uintptr_t>(length);
+}
+
 // If computed gotos are supported by the compiler, we can get addresses to
 // labels directly in C/C++. Every bytecode handler has its own label and we
 // store the addresses in a dispatch table indexed by bytecode. To execute the
 // next handler we simply jump (goto) directly to its address.
 #if V8_USE_COMPUTED_GOTO
 #define BC_LABEL(name) BC_##name:
 #define DECODE()                                                   \
   do {                                                             \
@@ -325,16 +343,24 @@ bool CheckBitInTable(const uint32_t curr
 // potentially be executed unconditionally, reducing memory stall.
 #define ADVANCE(name)                             \
   next_pc = pc + RegExpBytecodeLength(BC_##name); \
   DECODE()
 #define SET_PC_FROM_OFFSET(offset) \
   next_pc = code_base + offset;    \
   DECODE()
 
+// Current position mutations.
+#define SET_CURRENT_POSITION(value)                        \
+  do {                                                     \
+    current = (value);                                     \
+    DCHECK(base::IsInRange(current, 0, subject.length())); \
+  } while (false)
+#define ADVANCE_CURRENT_POSITION(by) SET_CURRENT_POSITION(current + (by))
+
 #ifdef DEBUG
 #define BYTECODE(name)                                                \
   BC_LABEL(name)                                                      \
   MaybeTraceInterpreter(code_base, pc, backtrack_stack.sp(), current, \
                         current_char, RegExpBytecodeLength(BC_##name), #name);
 #else
 #define BYTECODE(name) BC_LABEL(name)
 #endif  // DEBUG
@@ -435,54 +461,54 @@ IrregexpInterpreter::Result RawMatch(
       ADVANCE(PUSH_BT);
       if (!backtrack_stack.push(Load32Aligned(pc + 4))) {
         return MaybeThrowStackOverflow(isolate, call_origin);
       }
       DISPATCH();
     }
     BYTECODE(PUSH_REGISTER) {
       ADVANCE(PUSH_REGISTER);
-      if (!backtrack_stack.push(registers[insn >> BYTECODE_SHIFT])) {
+      if (!backtrack_stack.push(registers[LoadPacked24Unsigned(insn)])) {
         return MaybeThrowStackOverflow(isolate, call_origin);
       }
       DISPATCH();
     }
     BYTECODE(SET_REGISTER) {
       ADVANCE(SET_REGISTER);
-      registers[insn >> BYTECODE_SHIFT] = Load32Aligned(pc + 4);
+      registers[LoadPacked24Unsigned(insn)] = Load32Aligned(pc + 4);
       DISPATCH();
     }
     BYTECODE(ADVANCE_REGISTER) {
       ADVANCE(ADVANCE_REGISTER);
-      registers[insn >> BYTECODE_SHIFT] += Load32Aligned(pc + 4);
+      registers[LoadPacked24Unsigned(insn)] += Load32Aligned(pc + 4);
       DISPATCH();
     }
     BYTECODE(SET_REGISTER_TO_CP) {
       ADVANCE(SET_REGISTER_TO_CP);
-      registers[insn >> BYTECODE_SHIFT] = current + Load32Aligned(pc + 4);
+      registers[LoadPacked24Unsigned(insn)] = current + Load32Aligned(pc + 4);
       DISPATCH();
     }
     BYTECODE(SET_CP_TO_REGISTER) {
       ADVANCE(SET_CP_TO_REGISTER);
-      current = registers[insn >> BYTECODE_SHIFT];
+      SET_CURRENT_POSITION(registers[LoadPacked24Unsigned(insn)]);
       DISPATCH();
     }
     BYTECODE(SET_REGISTER_TO_SP) {
       ADVANCE(SET_REGISTER_TO_SP);
-      registers[insn >> BYTECODE_SHIFT] = backtrack_stack.sp();
+      registers[LoadPacked24Unsigned(insn)] = backtrack_stack.sp();
       DISPATCH();
     }
     BYTECODE(SET_SP_TO_REGISTER) {
       ADVANCE(SET_SP_TO_REGISTER);
-      backtrack_stack.set_sp(registers[insn >> BYTECODE_SHIFT]);
+      backtrack_stack.set_sp(registers[LoadPacked24Unsigned(insn)]);
       DISPATCH();
     }
     BYTECODE(POP_CP) {
       ADVANCE(POP_CP);
-      current = backtrack_stack.pop();
+      SET_CURRENT_POSITION(backtrack_stack.pop());
       DISPATCH();
     }
     BYTECODE(POP_BT) {
       STATIC_ASSERT(JSRegExp::kNoBacktrackLimit == 0);
       if (++backtrack_count == backtrack_limit) {
         // Exceeded limits are treated as a failed match.
         return IrregexpInterpreter::FAILURE;
       }
@@ -492,106 +518,106 @@ IrregexpInterpreter::Result RawMatch(
                            &code_base, &subject, &pc);
       if (return_code != IrregexpInterpreter::SUCCESS) return return_code;
 
       SET_PC_FROM_OFFSET(backtrack_stack.pop());
       DISPATCH();
     }
     BYTECODE(POP_REGISTER) {
       ADVANCE(POP_REGISTER);
-      registers[insn >> BYTECODE_SHIFT] = backtrack_stack.pop();
+      registers[LoadPacked24Unsigned(insn)] = backtrack_stack.pop();
       DISPATCH();
     }
     BYTECODE(FAIL) {
       isolate->counters()->regexp_backtracks()->AddSample(
           static_cast<int>(backtrack_count));
       return IrregexpInterpreter::FAILURE;
     }
     BYTECODE(SUCCEED) {
       isolate->counters()->regexp_backtracks()->AddSample(
           static_cast<int>(backtrack_count));
       registers.CopyToOutputRegisters();
       return IrregexpInterpreter::SUCCESS;
     }
     BYTECODE(ADVANCE_CP) {
       ADVANCE(ADVANCE_CP);
-      current += insn >> BYTECODE_SHIFT;
+      ADVANCE_CURRENT_POSITION(LoadPacked24Signed(insn));
       DISPATCH();
     }
     BYTECODE(GOTO) {
       SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
       DISPATCH();
     }
     BYTECODE(ADVANCE_CP_AND_GOTO) {
       SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
-      current += insn >> BYTECODE_SHIFT;
+      ADVANCE_CURRENT_POSITION(LoadPacked24Signed(insn));
       DISPATCH();
     }
     BYTECODE(CHECK_GREEDY) {
       if (current == backtrack_stack.peek()) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
         backtrack_stack.pop();
       } else {
         ADVANCE(CHECK_GREEDY);
       }
       DISPATCH();
     }
     BYTECODE(LOAD_CURRENT_CHAR) {
-      int pos = current + (insn >> BYTECODE_SHIFT);
+      int pos = current + LoadPacked24Signed(insn);
       if (pos >= subject.length() || pos < 0) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
       } else {
         ADVANCE(LOAD_CURRENT_CHAR);
         current_char = subject[pos];
       }
       DISPATCH();
     }
     BYTECODE(LOAD_CURRENT_CHAR_UNCHECKED) {
       ADVANCE(LOAD_CURRENT_CHAR_UNCHECKED);
-      int pos = current + (insn >> BYTECODE_SHIFT);
+      int pos = current + LoadPacked24Signed(insn);
       current_char = subject[pos];
       DISPATCH();
     }
     BYTECODE(LOAD_2_CURRENT_CHARS) {
-      int pos = current + (insn >> BYTECODE_SHIFT);
+      int pos = current + LoadPacked24Signed(insn);
       if (pos + 2 > subject.length() || pos < 0) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
       } else {
         ADVANCE(LOAD_2_CURRENT_CHARS);
         Char next = subject[pos + 1];
         current_char = (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
       }
       DISPATCH();
     }
     BYTECODE(LOAD_2_CURRENT_CHARS_UNCHECKED) {
       ADVANCE(LOAD_2_CURRENT_CHARS_UNCHECKED);
-      int pos = current + (insn >> BYTECODE_SHIFT);
+      int pos = current + LoadPacked24Signed(insn);
       Char next = subject[pos + 1];
       current_char = (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
       DISPATCH();
     }
     BYTECODE(LOAD_4_CURRENT_CHARS) {
       DCHECK_EQ(1, sizeof(Char));
-      int pos = current + (insn >> BYTECODE_SHIFT);
+      int pos = current + LoadPacked24Signed(insn);
       if (pos + 4 > subject.length() || pos < 0) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
       } else {
         ADVANCE(LOAD_4_CURRENT_CHARS);
         Char next1 = subject[pos + 1];
         Char next2 = subject[pos + 2];
         Char next3 = subject[pos + 3];
         current_char =
             (subject[pos] | (next1 << 8) | (next2 << 16) | (next3 << 24));
       }
       DISPATCH();
     }
     BYTECODE(LOAD_4_CURRENT_CHARS_UNCHECKED) {
       ADVANCE(LOAD_4_CURRENT_CHARS_UNCHECKED);
       DCHECK_EQ(1, sizeof(Char));
-      int pos = current + (insn >> BYTECODE_SHIFT);
+      int pos = current + LoadPacked24Signed(insn);
       Char next1 = subject[pos + 1];
       Char next2 = subject[pos + 2];
       Char next3 = subject[pos + 3];
       current_char =
           (subject[pos] | (next1 << 8) | (next2 << 16) | (next3 << 24));
       DISPATCH();
     }
     BYTECODE(CHECK_4_CHARS) {
@@ -599,17 +625,17 @@ IrregexpInterpreter::Result RawMatch(
       if (c == current_char) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
       } else {
         ADVANCE(CHECK_4_CHARS);
       }
       DISPATCH();
     }
     BYTECODE(CHECK_CHAR) {
-      uint32_t c = (insn >> BYTECODE_SHIFT);
+      uint32_t c = LoadPacked24Unsigned(insn);
       if (c == current_char) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
       } else {
         ADVANCE(CHECK_CHAR);
       }
       DISPATCH();
     }
     BYTECODE(CHECK_NOT_4_CHARS) {
@@ -617,17 +643,17 @@ IrregexpInterpreter::Result RawMatch(
       if (c != current_char) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
       } else {
         ADVANCE(CHECK_NOT_4_CHARS);
       }
       DISPATCH();
     }
     BYTECODE(CHECK_NOT_CHAR) {
-      uint32_t c = (insn >> BYTECODE_SHIFT);
+      uint32_t c = LoadPacked24Unsigned(insn);
       if (c != current_char) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
       } else {
         ADVANCE(CHECK_NOT_CHAR);
       }
       DISPATCH();
     }
     BYTECODE(AND_CHECK_4_CHARS) {
@@ -635,17 +661,17 @@ IrregexpInterpreter::Result RawMatch(
       if (c == (current_char & Load32Aligned(pc + 8))) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 12));
       } else {
         ADVANCE(AND_CHECK_4_CHARS);
       }
       DISPATCH();
     }
     BYTECODE(AND_CHECK_CHAR) {
-      uint32_t c = (insn >> BYTECODE_SHIFT);
+      uint32_t c = LoadPacked24Unsigned(insn);
       if (c == (current_char & Load32Aligned(pc + 4))) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
       } else {
         ADVANCE(AND_CHECK_CHAR);
       }
       DISPATCH();
     }
     BYTECODE(AND_CHECK_NOT_4_CHARS) {
@@ -653,26 +679,26 @@ IrregexpInterpreter::Result RawMatch(
       if (c != (current_char & Load32Aligned(pc + 8))) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 12));
       } else {
         ADVANCE(AND_CHECK_NOT_4_CHARS);
       }
       DISPATCH();
     }
     BYTECODE(AND_CHECK_NOT_CHAR) {
-      uint32_t c = (insn >> BYTECODE_SHIFT);
+      uint32_t c = LoadPacked24Unsigned(insn);
       if (c != (current_char & Load32Aligned(pc + 4))) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
       } else {
         ADVANCE(AND_CHECK_NOT_CHAR);
       }
       DISPATCH();
     }
     BYTECODE(MINUS_AND_CHECK_NOT_CHAR) {
-      uint32_t c = (insn >> BYTECODE_SHIFT);
+      uint32_t c = LoadPacked24Unsigned(insn);
       uint32_t minus = Load16Aligned(pc + 4);
       uint32_t mask = Load16Aligned(pc + 6);
       if (c != ((current_char - minus) & mask)) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
       } else {
         ADVANCE(MINUS_AND_CHECK_NOT_CHAR);
       }
       DISPATCH();
@@ -701,270 +727,266 @@ IrregexpInterpreter::Result RawMatch(
       if (CheckBitInTable(current_char, pc + 8)) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
       } else {
         ADVANCE(CHECK_BIT_IN_TABLE);
       }
       DISPATCH();
     }
     BYTECODE(CHECK_LT) {
-      uint32_t limit = (insn >> BYTECODE_SHIFT);
+      uint32_t limit = LoadPacked24Unsigned(insn);
       if (current_char < limit) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
       } else {
         ADVANCE(CHECK_LT);
       }
       DISPATCH();
     }
     BYTECODE(CHECK_GT) {
-      uint32_t limit = (insn >> BYTECODE_SHIFT);
+      uint32_t limit = LoadPacked24Unsigned(insn);
       if (current_char > limit) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
       } else {
         ADVANCE(CHECK_GT);
       }
       DISPATCH();
     }
     BYTECODE(CHECK_REGISTER_LT) {
-      if (registers[insn >> BYTECODE_SHIFT] < Load32Aligned(pc + 4)) {
+      if (registers[LoadPacked24Unsigned(insn)] < Load32Aligned(pc + 4)) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
       } else {
         ADVANCE(CHECK_REGISTER_LT);
       }
       DISPATCH();
     }
     BYTECODE(CHECK_REGISTER_GE) {
-      if (registers[insn >> BYTECODE_SHIFT] >= Load32Aligned(pc + 4)) {
+      if (registers[LoadPacked24Unsigned(insn)] >= Load32Aligned(pc + 4)) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
       } else {
         ADVANCE(CHECK_REGISTER_GE);
       }
       DISPATCH();
     }
     BYTECODE(CHECK_REGISTER_EQ_POS) {
-      if (registers[insn >> BYTECODE_SHIFT] == current) {
+      if (registers[LoadPacked24Unsigned(insn)] == current) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
       } else {
         ADVANCE(CHECK_REGISTER_EQ_POS);
       }
       DISPATCH();
     }
     BYTECODE(CHECK_NOT_REGS_EQUAL) {
-      if (registers[insn >> BYTECODE_SHIFT] ==
+      if (registers[LoadPacked24Unsigned(insn)] ==
           registers[Load32Aligned(pc + 4)]) {
         ADVANCE(CHECK_NOT_REGS_EQUAL);
       } else {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
       }
       DISPATCH();
     }
     BYTECODE(CHECK_NOT_BACK_REF) {
-      int from = registers[insn >> BYTECODE_SHIFT];
-      int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
+      int from = registers[LoadPacked24Unsigned(insn)];
+      int len = registers[LoadPacked24Unsigned(insn) + 1] - from;
       if (from >= 0 && len > 0) {
         if (current + len > subject.length() ||
             CompareChars(&subject[from], &subject[current], len) != 0) {
           SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
           DISPATCH();
         }
-        current += len;
+        ADVANCE_CURRENT_POSITION(len);
       }
       ADVANCE(CHECK_NOT_BACK_REF);
       DISPATCH();
     }
     BYTECODE(CHECK_NOT_BACK_REF_BACKWARD) {
-      int from = registers[insn >> BYTECODE_SHIFT];
-      int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
+      int from = registers[LoadPacked24Unsigned(insn)];
+      int len = registers[LoadPacked24Unsigned(insn) + 1] - from;
       if (from >= 0 && len > 0) {
         if (current - len < 0 ||
             CompareChars(&subject[from], &subject[current - len], len) != 0) {
           SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
           DISPATCH();
         }
-        current -= len;
+        SET_CURRENT_POSITION(current - len);
       }
       ADVANCE(CHECK_NOT_BACK_REF_BACKWARD);
       DISPATCH();
     }
     BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE) {
       UNREACHABLE();  // TODO(jgruber): Remove this unused bytecode.
     }
     BYTECODE(CHECK_NOT_BACK_REF_NO_CASE) {
-      int from = registers[insn >> BYTECODE_SHIFT];
-      int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
+      int from = registers[LoadPacked24Unsigned(insn)];
+      int len = registers[LoadPacked24Unsigned(insn) + 1] - from;
       if (from >= 0 && len > 0) {
         if (current + len > subject.length() ||
             !BackRefMatchesNoCase(isolate, from, current, len, subject)) {
           SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
           DISPATCH();
         }
-        current += len;
+        ADVANCE_CURRENT_POSITION(len);
       }
       ADVANCE(CHECK_NOT_BACK_REF_NO_CASE);
       DISPATCH();
     }
     BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE_BACKWARD) {
       UNREACHABLE();  // TODO(jgruber): Remove this unused bytecode.
     }
     BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD) {
-      int from = registers[insn >> BYTECODE_SHIFT];
-      int len = registers[(insn >> BYTECODE_SHIFT) + 1] - from;
+      int from = registers[LoadPacked24Unsigned(insn)];
+      int len = registers[LoadPacked24Unsigned(insn) + 1] - from;
       if (from >= 0 && len > 0) {
         if (current - len < 0 ||
             !BackRefMatchesNoCase(isolate, from, current - len, len, subject)) {
           SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
           DISPATCH();
         }
-        current -= len;
+        SET_CURRENT_POSITION(current - len);
       }
       ADVANCE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD);
       DISPATCH();
     }
     BYTECODE(CHECK_AT_START) {
-      if (current + (insn >> BYTECODE_SHIFT) == 0) {
+      if (current + LoadPacked24Signed(insn) == 0) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
       } else {
         ADVANCE(CHECK_AT_START);
       }
       DISPATCH();
     }
     BYTECODE(CHECK_NOT_AT_START) {
-      if (current + (insn >> BYTECODE_SHIFT) == 0) {
+      if (current + LoadPacked24Signed(insn) == 0) {
         ADVANCE(CHECK_NOT_AT_START);
       } else {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
       }
       DISPATCH();
     }
     BYTECODE(SET_CURRENT_POSITION_FROM_END) {
       ADVANCE(SET_CURRENT_POSITION_FROM_END);
-      int by = static_cast<uint32_t>(insn) >> BYTECODE_SHIFT;
+      int by = LoadPacked24Unsigned(insn);
       if (subject.length() - current > by) {
-        current = subject.length() - by;
+        SET_CURRENT_POSITION(subject.length() - by);
         current_char = subject[current - 1];
       }
       DISPATCH();
     }
     BYTECODE(CHECK_CURRENT_POSITION) {
-      int pos = current + (insn >> BYTECODE_SHIFT);
+      int pos = current + LoadPacked24Signed(insn);
       if (pos > subject.length() || pos < 0) {
         SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
       } else {
         ADVANCE(CHECK_CURRENT_POSITION);
       }
       DISPATCH();
     }
     BYTECODE(SKIP_UNTIL_CHAR) {
-      int load_offset = (insn >> BYTECODE_SHIFT);
+      int32_t load_offset = LoadPacked24Signed(insn);
       int32_t advance = Load16AlignedSigned(pc + 4);
       uint32_t c = Load16Aligned(pc + 6);
-      while (static_cast<uintptr_t>(current + load_offset) <
-             static_cast<uintptr_t>(subject.length())) {
+      while (IndexIsInBounds(current + load_offset, subject.length())) {
         current_char = subject[current + load_offset];
         if (c == current_char) {
           SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
           DISPATCH();
         }
-        current += advance;
+        ADVANCE_CURRENT_POSITION(advance);
       }
       SET_PC_FROM_OFFSET(Load32Aligned(pc + 12));
       DISPATCH();
     }
     BYTECODE(SKIP_UNTIL_CHAR_AND) {
-      int load_offset = (insn >> BYTECODE_SHIFT);
+      int32_t load_offset = LoadPacked24Signed(insn);
       int32_t advance = Load16AlignedSigned(pc + 4);
       uint16_t c = Load16Aligned(pc + 6);
       uint32_t mask = Load32Aligned(pc + 8);
       int32_t maximum_offset = Load32Aligned(pc + 12);
       while (static_cast<uintptr_t>(current + maximum_offset) <=
              static_cast<uintptr_t>(subject.length())) {
         current_char = subject[current + load_offset];
         if (c == (current_char & mask)) {
           SET_PC_FROM_OFFSET(Load32Aligned(pc + 16));
           DISPATCH();
         }
-        current += advance;
+        ADVANCE_CURRENT_POSITION(advance);
       }
       SET_PC_FROM_OFFSET(Load32Aligned(pc + 20));
       DISPATCH();
     }
     BYTECODE(SKIP_UNTIL_CHAR_POS_CHECKED) {
-      int load_offset = (insn >> BYTECODE_SHIFT);
+      int32_t load_offset = LoadPacked24Signed(insn);
       int32_t advance = Load16AlignedSigned(pc + 4);
       uint16_t c = Load16Aligned(pc + 6);
       int32_t maximum_offset = Load32Aligned(pc + 8);
       while (static_cast<uintptr_t>(current + maximum_offset) <=
              static_cast<uintptr_t>(subject.length())) {
         current_char = subject[current + load_offset];
         if (c == current_char) {
           SET_PC_FROM_OFFSET(Load32Aligned(pc + 12));
           DISPATCH();
         }
-        current += advance;
+        ADVANCE_CURRENT_POSITION(advance);
       }
       SET_PC_FROM_OFFSET(Load32Aligned(pc + 16));
       DISPATCH();
     }
     BYTECODE(SKIP_UNTIL_BIT_IN_TABLE) {
-      int load_offset = (insn >> BYTECODE_SHIFT);
+      int32_t load_offset = LoadPacked24Signed(insn);
       int32_t advance = Load16AlignedSigned(pc + 4);
       const byte* table = pc + 8;
-      while (static_cast<uintptr_t>(current + load_offset) <
-             static_cast<uintptr_t>(subject.length())) {
+      while (IndexIsInBounds(current + load_offset, subject.length())) {
         current_char = subject[current + load_offset];
         if (CheckBitInTable(current_char, table)) {
           SET_PC_FROM_OFFSET(Load32Aligned(pc + 24));
           DISPATCH();
         }
-        current += advance;
+        ADVANCE_CURRENT_POSITION(advance);
       }
       SET_PC_FROM_OFFSET(Load32Aligned(pc + 28));
       DISPATCH();
     }
     BYTECODE(SKIP_UNTIL_GT_OR_NOT_BIT_IN_TABLE) {
-      int load_offset = (insn >> BYTECODE_SHIFT);
+      int32_t load_offset = LoadPacked24Signed(insn);
       int32_t advance = Load16AlignedSigned(pc + 4);
       uint16_t limit = Load16Aligned(pc + 6);
       const byte* table = pc + 8;
-      while (static_cast<uintptr_t>(current + load_offset) <
-             static_cast<uintptr_t>(subject.length())) {
+      while (IndexIsInBounds(current + load_offset, subject.length())) {
         current_char = subject[current + load_offset];
         if (current_char > limit) {
           SET_PC_FROM_OFFSET(Load32Aligned(pc + 24));
           DISPATCH();
         }
         if (!CheckBitInTable(current_char, table)) {
           SET_PC_FROM_OFFSET(Load32Aligned(pc + 24));
           DISPATCH();
         }
-        current += advance;
+        ADVANCE_CURRENT_POSITION(advance);
       }
       SET_PC_FROM_OFFSET(Load32Aligned(pc + 28));
       DISPATCH();
     }
     BYTECODE(SKIP_UNTIL_CHAR_OR_CHAR) {
-      int load_offset = (insn >> BYTECODE_SHIFT);
+      int32_t load_offset = LoadPacked24Signed(insn);
       int32_t advance = Load32Aligned(pc + 4);
       uint16_t c = Load16Aligned(pc + 8);
       uint16_t c2 = Load16Aligned(pc + 10);
-      while (static_cast<uintptr_t>(current + load_offset) <
-             static_cast<uintptr_t>(subject.length())) {
+      while (IndexIsInBounds(current + load_offset, subject.length())) {
         current_char = subject[current + load_offset];
         // The two if-statements below are split up intentionally, as combining
         // them seems to result in register allocation behaving quite
         // differently and slowing down the resulting code.
         if (c == current_char) {
           SET_PC_FROM_OFFSET(Load32Aligned(pc + 12));
           DISPATCH();
         }
         if (c2 == current_char) {
           SET_PC_FROM_OFFSET(Load32Aligned(pc + 12));
           DISPATCH();
         }
-        current += advance;
+        ADVANCE_CURRENT_POSITION(advance);
       }
       SET_PC_FROM_OFFSET(Load32Aligned(pc + 16));
       DISPATCH();
     }
 #if V8_USE_COMPUTED_GOTO
 // Lint gets confused a lot if we just use !V8_USE_COMPUTED_GOTO or ifndef
 // V8_USE_COMPUTED_GOTO here.
 #else
@@ -974,16 +996,18 @@ IrregexpInterpreter::Result RawMatch(
   // Label we jump to in DISPATCH(). There must be no instructions between the
   // end of the switch, this label and the end of the loop.
   switch_dispatch_continuation : {}
 #endif  // V8_USE_COMPUTED_GOTO
   }
 }
 
 #undef BYTECODE
+#undef ADVANCE_CURRENT_POSITION
+#undef SET_CURRENT_POSITION
 #undef DISPATCH
 #undef DECODE
 #undef SET_PC_FROM_OFFSET
 #undef ADVANCE
 #undef BC_LABEL
 #undef V8_USE_COMPUTED_GOTO
 
 }  // namespace
--- a/js/src/new-regexp/regexp-nodes.h
+++ b/js/src/new-regexp/regexp-nodes.h
@@ -231,16 +231,25 @@ class RegExpNode : public ZoneObject {
   void set_on_work_list(bool value) { on_work_list_ = value; }
 
   NodeInfo* info() { return &info_; }
   const EatsAtLeastInfo* eats_at_least_info() const { return &eats_at_least_; }
   void set_eats_at_least_info(const EatsAtLeastInfo& eats_at_least) {
     eats_at_least_ = eats_at_least;
   }
 
+  // TODO(v8:10441): This is a hacky way to avoid exponential code size growth
+  // for very large choice nodes that can be generated by unicode property
+  // escapes. In order to avoid inlining (i.e. trace recursion), we pretend to
+  // have generated the maximum count of code copies already.
+  // We should instead fix this properly, e.g. by using the code size budget
+  // (flush_budget) or by generating property escape matches as calls to a C
+  // function.
+  void SetDoNotInline() { trace_count_ = kMaxCopiesCodeGenerated; }
+
   BoyerMooreLookahead* bm_info(bool not_at_start) {
     return bm_info_[not_at_start ? 1 : 0];
   }
 
   Zone* zone() const { return zone_; }
 
  protected:
   enum LimitResult { DONE, CONTINUE };