11cb0ef41Sopenharmony_ci// Copyright 2011 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci// A simple interpreter for the Irregexp byte code.
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/regexp/regexp-interpreter.h"
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci#include "src/base/small-vector.h"
101cb0ef41Sopenharmony_ci#include "src/base/strings.h"
111cb0ef41Sopenharmony_ci#include "src/execution/isolate.h"
121cb0ef41Sopenharmony_ci#include "src/logging/counters.h"
131cb0ef41Sopenharmony_ci#include "src/objects/js-regexp-inl.h"
141cb0ef41Sopenharmony_ci#include "src/objects/string-inl.h"
151cb0ef41Sopenharmony_ci#include "src/regexp/regexp-bytecodes.h"
161cb0ef41Sopenharmony_ci#include "src/regexp/regexp-macro-assembler.h"
171cb0ef41Sopenharmony_ci#include "src/regexp/regexp-stack.h"  // For kMaximumStackSize.
181cb0ef41Sopenharmony_ci#include "src/regexp/regexp.h"
191cb0ef41Sopenharmony_ci#include "src/strings/unicode.h"
201cb0ef41Sopenharmony_ci#include "src/utils/memcopy.h"
211cb0ef41Sopenharmony_ci#include "src/utils/utils.h"
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci#ifdef V8_INTL_SUPPORT
241cb0ef41Sopenharmony_ci#include "unicode/uchar.h"
251cb0ef41Sopenharmony_ci#endif  // V8_INTL_SUPPORT
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci// Use token threaded dispatch iff the compiler supports computed gotos and the
281cb0ef41Sopenharmony_ci// build argument v8_enable_regexp_interpreter_threaded_dispatch was set.
291cb0ef41Sopenharmony_ci#if V8_HAS_COMPUTED_GOTO && \
301cb0ef41Sopenharmony_ci    defined(V8_ENABLE_REGEXP_INTERPRETER_THREADED_DISPATCH)
311cb0ef41Sopenharmony_ci#define V8_USE_COMPUTED_GOTO 1
321cb0ef41Sopenharmony_ci#endif  // V8_HAS_COMPUTED_GOTO
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_cinamespace v8 {
351cb0ef41Sopenharmony_cinamespace internal {
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_cinamespace {
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_cibool BackRefMatchesNoCase(Isolate* isolate, int from, int current, int len,
401cb0ef41Sopenharmony_ci                          base::Vector<const base::uc16> subject,
411cb0ef41Sopenharmony_ci                          bool unicode) {
421cb0ef41Sopenharmony_ci  Address offset_a =
431cb0ef41Sopenharmony_ci      reinterpret_cast<Address>(const_cast<base::uc16*>(&subject.at(from)));
441cb0ef41Sopenharmony_ci  Address offset_b =
451cb0ef41Sopenharmony_ci      reinterpret_cast<Address>(const_cast<base::uc16*>(&subject.at(current)));
461cb0ef41Sopenharmony_ci  size_t length = len * base::kUC16Size;
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  bool result = unicode
491cb0ef41Sopenharmony_ci                    ? RegExpMacroAssembler::CaseInsensitiveCompareUnicode(
501cb0ef41Sopenharmony_ci                          offset_a, offset_b, length, isolate)
511cb0ef41Sopenharmony_ci                    : RegExpMacroAssembler::CaseInsensitiveCompareNonUnicode(
521cb0ef41Sopenharmony_ci                          offset_a, offset_b, length, isolate);
531cb0ef41Sopenharmony_ci  return result == 1;
541cb0ef41Sopenharmony_ci}
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_cibool BackRefMatchesNoCase(Isolate* isolate, int from, int current, int len,
571cb0ef41Sopenharmony_ci                          base::Vector<const uint8_t> subject, bool unicode) {
581cb0ef41Sopenharmony_ci  // For Latin1 characters the unicode flag makes no difference.
591cb0ef41Sopenharmony_ci  for (int i = 0; i < len; i++) {
601cb0ef41Sopenharmony_ci    unsigned int old_char = subject[from++];
611cb0ef41Sopenharmony_ci    unsigned int new_char = subject[current++];
621cb0ef41Sopenharmony_ci    if (old_char == new_char) continue;
631cb0ef41Sopenharmony_ci    // Convert both characters to lower case.
641cb0ef41Sopenharmony_ci    old_char |= 0x20;
651cb0ef41Sopenharmony_ci    new_char |= 0x20;
661cb0ef41Sopenharmony_ci    if (old_char != new_char) return false;
671cb0ef41Sopenharmony_ci    // Not letters in the ASCII range and Latin-1 range.
681cb0ef41Sopenharmony_ci    if (!(old_char - 'a' <= 'z' - 'a') &&
691cb0ef41Sopenharmony_ci        !(old_char - 224 <= 254 - 224 && old_char != 247)) {
701cb0ef41Sopenharmony_ci      return false;
711cb0ef41Sopenharmony_ci    }
721cb0ef41Sopenharmony_ci  }
731cb0ef41Sopenharmony_ci  return true;
741cb0ef41Sopenharmony_ci}
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci#ifdef DEBUG
771cb0ef41Sopenharmony_civoid MaybeTraceInterpreter(const byte* code_base, const byte* pc,
781cb0ef41Sopenharmony_ci                           int stack_depth, int current_position,
791cb0ef41Sopenharmony_ci                           uint32_t current_char, int bytecode_length,
801cb0ef41Sopenharmony_ci                           const char* bytecode_name) {
811cb0ef41Sopenharmony_ci  if (FLAG_trace_regexp_bytecodes) {
821cb0ef41Sopenharmony_ci    const bool printable = std::isprint(current_char);
831cb0ef41Sopenharmony_ci    const char* format =
841cb0ef41Sopenharmony_ci        printable
851cb0ef41Sopenharmony_ci            ? "pc = %02x, sp = %d, curpos = %d, curchar = %08x (%c), bc = "
861cb0ef41Sopenharmony_ci            : "pc = %02x, sp = %d, curpos = %d, curchar = %08x .%c., bc = ";
871cb0ef41Sopenharmony_ci    PrintF(format, pc - code_base, stack_depth, current_position, current_char,
881cb0ef41Sopenharmony_ci           printable ? current_char : '.');
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci    RegExpBytecodeDisassembleSingle(code_base, pc);
911cb0ef41Sopenharmony_ci  }
921cb0ef41Sopenharmony_ci}
931cb0ef41Sopenharmony_ci#endif  // DEBUG
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ciint32_t Load32Aligned(const byte* pc) {
961cb0ef41Sopenharmony_ci  DCHECK_EQ(0, reinterpret_cast<intptr_t>(pc) & 3);
971cb0ef41Sopenharmony_ci  return *reinterpret_cast<const int32_t*>(pc);
981cb0ef41Sopenharmony_ci}
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci// TODO(jgruber): Rename to Load16AlignedUnsigned.
1011cb0ef41Sopenharmony_ciuint32_t Load16Aligned(const byte* pc) {
1021cb0ef41Sopenharmony_ci  DCHECK_EQ(0, reinterpret_cast<intptr_t>(pc) & 1);
1031cb0ef41Sopenharmony_ci  return *reinterpret_cast<const uint16_t*>(pc);
1041cb0ef41Sopenharmony_ci}
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ciint32_t Load16AlignedSigned(const byte* pc) {
1071cb0ef41Sopenharmony_ci  DCHECK_EQ(0, reinterpret_cast<intptr_t>(pc) & 1);
1081cb0ef41Sopenharmony_ci  return *reinterpret_cast<const int16_t*>(pc);
1091cb0ef41Sopenharmony_ci}
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci// Helpers to access the packed argument. Takes the 32 bits containing the
1121cb0ef41Sopenharmony_ci// current bytecode, where the 8 LSB contain the bytecode and the rest contains
1131cb0ef41Sopenharmony_ci// a packed 24-bit argument.
1141cb0ef41Sopenharmony_ci// TODO(jgruber): Specify signed-ness in bytecode signature declarations, and
1151cb0ef41Sopenharmony_ci// police restrictions during bytecode generation.
1161cb0ef41Sopenharmony_ciint32_t LoadPacked24Signed(int32_t bytecode_and_packed_arg) {
1171cb0ef41Sopenharmony_ci  return bytecode_and_packed_arg >> BYTECODE_SHIFT;
1181cb0ef41Sopenharmony_ci}
1191cb0ef41Sopenharmony_ciuint32_t LoadPacked24Unsigned(int32_t bytecode_and_packed_arg) {
1201cb0ef41Sopenharmony_ci  return static_cast<uint32_t>(bytecode_and_packed_arg) >> BYTECODE_SHIFT;
1211cb0ef41Sopenharmony_ci}
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci// A simple abstraction over the backtracking stack used by the interpreter.
1241cb0ef41Sopenharmony_ci//
1251cb0ef41Sopenharmony_ci// Despite the name 'backtracking' stack, it's actually used as a generic stack
1261cb0ef41Sopenharmony_ci// that stores both program counters (= offsets into the bytecode) and generic
1271cb0ef41Sopenharmony_ci// integer values.
1281cb0ef41Sopenharmony_ciclass BacktrackStack {
1291cb0ef41Sopenharmony_ci public:
1301cb0ef41Sopenharmony_ci  BacktrackStack() = default;
1311cb0ef41Sopenharmony_ci  BacktrackStack(const BacktrackStack&) = delete;
1321cb0ef41Sopenharmony_ci  BacktrackStack& operator=(const BacktrackStack&) = delete;
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci  V8_WARN_UNUSED_RESULT bool push(int v) {
1351cb0ef41Sopenharmony_ci    data_.emplace_back(v);
1361cb0ef41Sopenharmony_ci    return (static_cast<int>(data_.size()) <= kMaxSize);
1371cb0ef41Sopenharmony_ci  }
1381cb0ef41Sopenharmony_ci  int peek() const {
1391cb0ef41Sopenharmony_ci    DCHECK(!data_.empty());
1401cb0ef41Sopenharmony_ci    return data_.back();
1411cb0ef41Sopenharmony_ci  }
1421cb0ef41Sopenharmony_ci  int pop() {
1431cb0ef41Sopenharmony_ci    int v = peek();
1441cb0ef41Sopenharmony_ci    data_.pop_back();
1451cb0ef41Sopenharmony_ci    return v;
1461cb0ef41Sopenharmony_ci  }
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  // The 'sp' is the index of the first empty element in the stack.
1491cb0ef41Sopenharmony_ci  int sp() const { return static_cast<int>(data_.size()); }
1501cb0ef41Sopenharmony_ci  void set_sp(int new_sp) {
1511cb0ef41Sopenharmony_ci    DCHECK_LE(new_sp, sp());
1521cb0ef41Sopenharmony_ci    data_.resize_no_init(new_sp);
1531cb0ef41Sopenharmony_ci  }
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci private:
1561cb0ef41Sopenharmony_ci  // Semi-arbitrary. Should be large enough for common cases to remain in the
1571cb0ef41Sopenharmony_ci  // static stack-allocated backing store, but small enough not to waste space.
1581cb0ef41Sopenharmony_ci  static constexpr int kStaticCapacity = 64;
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci  using ValueT = int;
1611cb0ef41Sopenharmony_ci  base::SmallVector<ValueT, kStaticCapacity> data_;
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci  static constexpr int kMaxSize =
1641cb0ef41Sopenharmony_ci      RegExpStack::kMaximumStackSize / sizeof(ValueT);
1651cb0ef41Sopenharmony_ci};
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci// Registers used during interpreter execution. These consist of output
1681cb0ef41Sopenharmony_ci// registers in indices [0, output_register_count[ which will contain matcher
1691cb0ef41Sopenharmony_ci// results as a {start,end} index tuple for each capture (where the whole match
1701cb0ef41Sopenharmony_ci// counts as implicit capture 0); and internal registers in indices
1711cb0ef41Sopenharmony_ci// [output_register_count, total_register_count[.
1721cb0ef41Sopenharmony_ciclass InterpreterRegisters {
1731cb0ef41Sopenharmony_ci public:
1741cb0ef41Sopenharmony_ci  using RegisterT = int;
1751cb0ef41Sopenharmony_ci
1761cb0ef41Sopenharmony_ci  InterpreterRegisters(int total_register_count, RegisterT* output_registers,
1771cb0ef41Sopenharmony_ci                       int output_register_count)
1781cb0ef41Sopenharmony_ci      : registers_(total_register_count),
1791cb0ef41Sopenharmony_ci        output_registers_(output_registers),
1801cb0ef41Sopenharmony_ci        output_register_count_(output_register_count) {
1811cb0ef41Sopenharmony_ci    // TODO(jgruber): Use int32_t consistently for registers. Currently, CSA
1821cb0ef41Sopenharmony_ci    // uses int32_t while runtime uses int.
1831cb0ef41Sopenharmony_ci    STATIC_ASSERT(sizeof(int) == sizeof(int32_t));
1841cb0ef41Sopenharmony_ci    DCHECK_GE(output_register_count, 2);  // At least 2 for the match itself.
1851cb0ef41Sopenharmony_ci    DCHECK_GE(total_register_count, output_register_count);
1861cb0ef41Sopenharmony_ci    DCHECK_LE(total_register_count, RegExpMacroAssembler::kMaxRegisterCount);
1871cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(output_registers);
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci    // Initialize the output register region to -1 signifying 'no match'.
1901cb0ef41Sopenharmony_ci    std::memset(registers_.data(), -1,
1911cb0ef41Sopenharmony_ci                output_register_count * sizeof(RegisterT));
1921cb0ef41Sopenharmony_ci  }
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci  const RegisterT& operator[](size_t index) const { return registers_[index]; }
1951cb0ef41Sopenharmony_ci  RegisterT& operator[](size_t index) { return registers_[index]; }
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci  void CopyToOutputRegisters() {
1981cb0ef41Sopenharmony_ci    MemCopy(output_registers_, registers_.data(),
1991cb0ef41Sopenharmony_ci            output_register_count_ * sizeof(RegisterT));
2001cb0ef41Sopenharmony_ci  }
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci private:
2031cb0ef41Sopenharmony_ci  static constexpr int kStaticCapacity = 64;  // Arbitrary.
2041cb0ef41Sopenharmony_ci  base::SmallVector<RegisterT, kStaticCapacity> registers_;
2051cb0ef41Sopenharmony_ci  RegisterT* const output_registers_;
2061cb0ef41Sopenharmony_ci  const int output_register_count_;
2071cb0ef41Sopenharmony_ci};
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ciIrregexpInterpreter::Result ThrowStackOverflow(Isolate* isolate,
2101cb0ef41Sopenharmony_ci                                               RegExp::CallOrigin call_origin) {
2111cb0ef41Sopenharmony_ci  CHECK(call_origin == RegExp::CallOrigin::kFromRuntime);
2121cb0ef41Sopenharmony_ci  // We abort interpreter execution after the stack overflow is thrown, and thus
2131cb0ef41Sopenharmony_ci  // allow allocation here despite the outer DisallowGarbageCollectionScope.
2141cb0ef41Sopenharmony_ci  AllowGarbageCollection yes_gc;
2151cb0ef41Sopenharmony_ci  isolate->StackOverflow();
2161cb0ef41Sopenharmony_ci  return IrregexpInterpreter::EXCEPTION;
2171cb0ef41Sopenharmony_ci}
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci// Only throws if called from the runtime, otherwise just returns the EXCEPTION
2201cb0ef41Sopenharmony_ci// status code.
2211cb0ef41Sopenharmony_ciIrregexpInterpreter::Result MaybeThrowStackOverflow(
2221cb0ef41Sopenharmony_ci    Isolate* isolate, RegExp::CallOrigin call_origin) {
2231cb0ef41Sopenharmony_ci  if (call_origin == RegExp::CallOrigin::kFromRuntime) {
2241cb0ef41Sopenharmony_ci    return ThrowStackOverflow(isolate, call_origin);
2251cb0ef41Sopenharmony_ci  } else {
2261cb0ef41Sopenharmony_ci    return IrregexpInterpreter::EXCEPTION;
2271cb0ef41Sopenharmony_ci  }
2281cb0ef41Sopenharmony_ci}
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_citemplate <typename Char>
2311cb0ef41Sopenharmony_civoid UpdateCodeAndSubjectReferences(
2321cb0ef41Sopenharmony_ci    Isolate* isolate, Handle<ByteArray> code_array,
2331cb0ef41Sopenharmony_ci    Handle<String> subject_string, ByteArray* code_array_out,
2341cb0ef41Sopenharmony_ci    const byte** code_base_out, const byte** pc_out, String* subject_string_out,
2351cb0ef41Sopenharmony_ci    base::Vector<const Char>* subject_string_vector_out) {
2361cb0ef41Sopenharmony_ci  DisallowGarbageCollection no_gc;
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci  if (*code_base_out != code_array->GetDataStartAddress()) {
2391cb0ef41Sopenharmony_ci    *code_array_out = *code_array;
2401cb0ef41Sopenharmony_ci    const intptr_t pc_offset = *pc_out - *code_base_out;
2411cb0ef41Sopenharmony_ci    DCHECK_GT(pc_offset, 0);
2421cb0ef41Sopenharmony_ci    *code_base_out = code_array->GetDataStartAddress();
2431cb0ef41Sopenharmony_ci    *pc_out = *code_base_out + pc_offset;
2441cb0ef41Sopenharmony_ci  }
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci  DCHECK(subject_string->IsFlat());
2471cb0ef41Sopenharmony_ci  *subject_string_out = *subject_string;
2481cb0ef41Sopenharmony_ci  *subject_string_vector_out = subject_string->GetCharVector<Char>(no_gc);
2491cb0ef41Sopenharmony_ci}
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_ci// Runs all pending interrupts and updates unhandlified object references if
2521cb0ef41Sopenharmony_ci// necessary.
2531cb0ef41Sopenharmony_citemplate <typename Char>
2541cb0ef41Sopenharmony_ciIrregexpInterpreter::Result HandleInterrupts(
2551cb0ef41Sopenharmony_ci    Isolate* isolate, RegExp::CallOrigin call_origin, ByteArray* code_array_out,
2561cb0ef41Sopenharmony_ci    String* subject_string_out, const byte** code_base_out,
2571cb0ef41Sopenharmony_ci    base::Vector<const Char>* subject_string_vector_out, const byte** pc_out) {
2581cb0ef41Sopenharmony_ci  DisallowGarbageCollection no_gc;
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci  StackLimitCheck check(isolate);
2611cb0ef41Sopenharmony_ci  bool js_has_overflowed = check.JsHasOverflowed();
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci  if (call_origin == RegExp::CallOrigin::kFromJs) {
2641cb0ef41Sopenharmony_ci    // Direct calls from JavaScript can be interrupted in two ways:
2651cb0ef41Sopenharmony_ci    // 1. A real stack overflow, in which case we let the caller throw the
2661cb0ef41Sopenharmony_ci    //    exception.
2671cb0ef41Sopenharmony_ci    // 2. The stack guard was used to interrupt execution for another purpose,
2681cb0ef41Sopenharmony_ci    //    forcing the call through the runtime system.
2691cb0ef41Sopenharmony_ci    if (js_has_overflowed) {
2701cb0ef41Sopenharmony_ci      return IrregexpInterpreter::EXCEPTION;
2711cb0ef41Sopenharmony_ci    } else if (check.InterruptRequested()) {
2721cb0ef41Sopenharmony_ci      return IrregexpInterpreter::RETRY;
2731cb0ef41Sopenharmony_ci    }
2741cb0ef41Sopenharmony_ci  } else {
2751cb0ef41Sopenharmony_ci    DCHECK(call_origin == RegExp::CallOrigin::kFromRuntime);
2761cb0ef41Sopenharmony_ci    // Prepare for possible GC.
2771cb0ef41Sopenharmony_ci    HandleScope handles(isolate);
2781cb0ef41Sopenharmony_ci    Handle<ByteArray> code_handle(*code_array_out, isolate);
2791cb0ef41Sopenharmony_ci    Handle<String> subject_handle(*subject_string_out, isolate);
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci    if (js_has_overflowed) {
2821cb0ef41Sopenharmony_ci      return ThrowStackOverflow(isolate, call_origin);
2831cb0ef41Sopenharmony_ci    } else if (check.InterruptRequested()) {
2841cb0ef41Sopenharmony_ci      const bool was_one_byte =
2851cb0ef41Sopenharmony_ci          String::IsOneByteRepresentationUnderneath(*subject_string_out);
2861cb0ef41Sopenharmony_ci      Object result;
2871cb0ef41Sopenharmony_ci      {
2881cb0ef41Sopenharmony_ci        AllowGarbageCollection yes_gc;
2891cb0ef41Sopenharmony_ci        result = isolate->stack_guard()->HandleInterrupts();
2901cb0ef41Sopenharmony_ci      }
2911cb0ef41Sopenharmony_ci      if (result.IsException(isolate)) {
2921cb0ef41Sopenharmony_ci        return IrregexpInterpreter::EXCEPTION;
2931cb0ef41Sopenharmony_ci      }
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci      // If we changed between a LATIN1 and a UC16 string, we need to
2961cb0ef41Sopenharmony_ci      // restart regexp matching with the appropriate template instantiation of
2971cb0ef41Sopenharmony_ci      // RawMatch.
2981cb0ef41Sopenharmony_ci      if (String::IsOneByteRepresentationUnderneath(*subject_handle) !=
2991cb0ef41Sopenharmony_ci          was_one_byte) {
3001cb0ef41Sopenharmony_ci        return IrregexpInterpreter::RETRY;
3011cb0ef41Sopenharmony_ci      }
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci      UpdateCodeAndSubjectReferences(
3041cb0ef41Sopenharmony_ci          isolate, code_handle, subject_handle, code_array_out, code_base_out,
3051cb0ef41Sopenharmony_ci          pc_out, subject_string_out, subject_string_vector_out);
3061cb0ef41Sopenharmony_ci    }
3071cb0ef41Sopenharmony_ci  }
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci  return IrregexpInterpreter::SUCCESS;
3101cb0ef41Sopenharmony_ci}
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_cibool CheckBitInTable(const uint32_t current_char, const byte* const table) {
3131cb0ef41Sopenharmony_ci  int mask = RegExpMacroAssembler::kTableMask;
3141cb0ef41Sopenharmony_ci  int b = table[(current_char & mask) >> kBitsPerByteLog2];
3151cb0ef41Sopenharmony_ci  int bit = (current_char & (kBitsPerByte - 1));
3161cb0ef41Sopenharmony_ci  return (b & (1 << bit)) != 0;
3171cb0ef41Sopenharmony_ci}
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_ci// Returns true iff 0 <= index < length.
3201cb0ef41Sopenharmony_cibool IndexIsInBounds(int index, int length) {
3211cb0ef41Sopenharmony_ci  DCHECK_GE(length, 0);
3221cb0ef41Sopenharmony_ci  return static_cast<uintptr_t>(index) < static_cast<uintptr_t>(length);
3231cb0ef41Sopenharmony_ci}
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_ci// If computed gotos are supported by the compiler, we can get addresses to
3261cb0ef41Sopenharmony_ci// labels directly in C/C++. Every bytecode handler has its own label and we
3271cb0ef41Sopenharmony_ci// store the addresses in a dispatch table indexed by bytecode. To execute the
3281cb0ef41Sopenharmony_ci// next handler we simply jump (goto) directly to its address.
3291cb0ef41Sopenharmony_ci#if V8_USE_COMPUTED_GOTO
3301cb0ef41Sopenharmony_ci#define BC_LABEL(name) BC_##name:
3311cb0ef41Sopenharmony_ci#define DECODE()                                                   \
3321cb0ef41Sopenharmony_ci  do {                                                             \
3331cb0ef41Sopenharmony_ci    next_insn = Load32Aligned(next_pc);                            \
3341cb0ef41Sopenharmony_ci    next_handler_addr = dispatch_table[next_insn & BYTECODE_MASK]; \
3351cb0ef41Sopenharmony_ci  } while (false)
3361cb0ef41Sopenharmony_ci#define DISPATCH()  \
3371cb0ef41Sopenharmony_ci  pc = next_pc;     \
3381cb0ef41Sopenharmony_ci  insn = next_insn; \
3391cb0ef41Sopenharmony_ci  goto* next_handler_addr
3401cb0ef41Sopenharmony_ci// Without computed goto support, we fall back to a simple switch-based
3411cb0ef41Sopenharmony_ci// dispatch (A large switch statement inside a loop with a case for every
3421cb0ef41Sopenharmony_ci// bytecode).
3431cb0ef41Sopenharmony_ci#else  // V8_USE_COMPUTED_GOTO
3441cb0ef41Sopenharmony_ci#define BC_LABEL(name) case BC_##name:
3451cb0ef41Sopenharmony_ci#define DECODE() next_insn = Load32Aligned(next_pc)
3461cb0ef41Sopenharmony_ci#define DISPATCH()  \
3471cb0ef41Sopenharmony_ci  pc = next_pc;     \
3481cb0ef41Sopenharmony_ci  insn = next_insn; \
3491cb0ef41Sopenharmony_ci  goto switch_dispatch_continuation
3501cb0ef41Sopenharmony_ci#endif  // V8_USE_COMPUTED_GOTO
3511cb0ef41Sopenharmony_ci
3521cb0ef41Sopenharmony_ci// ADVANCE/SET_PC_FROM_OFFSET are separated from DISPATCH, because ideally some
3531cb0ef41Sopenharmony_ci// instructions can be executed between ADVANCE/SET_PC_FROM_OFFSET and DISPATCH.
3541cb0ef41Sopenharmony_ci// We want those two macros as far apart as possible, because the goto in
3551cb0ef41Sopenharmony_ci// DISPATCH is dependent on a memory load in ADVANCE/SET_PC_FROM_OFFSET. If we
3561cb0ef41Sopenharmony_ci// don't hit the cache and have to fetch the next handler address from physical
3571cb0ef41Sopenharmony_ci// memory, instructions between ADVANCE/SET_PC_FROM_OFFSET and DISPATCH can
3581cb0ef41Sopenharmony_ci// potentially be executed unconditionally, reducing memory stall.
3591cb0ef41Sopenharmony_ci#define ADVANCE(name)                             \
3601cb0ef41Sopenharmony_ci  next_pc = pc + RegExpBytecodeLength(BC_##name); \
3611cb0ef41Sopenharmony_ci  DECODE()
3621cb0ef41Sopenharmony_ci#define SET_PC_FROM_OFFSET(offset) \
3631cb0ef41Sopenharmony_ci  next_pc = code_base + offset;    \
3641cb0ef41Sopenharmony_ci  DECODE()
3651cb0ef41Sopenharmony_ci
3661cb0ef41Sopenharmony_ci// Current position mutations.
3671cb0ef41Sopenharmony_ci#define SET_CURRENT_POSITION(value)                        \
3681cb0ef41Sopenharmony_ci  do {                                                     \
3691cb0ef41Sopenharmony_ci    current = (value);                                     \
3701cb0ef41Sopenharmony_ci    DCHECK(base::IsInRange(current, 0, subject.length())); \
3711cb0ef41Sopenharmony_ci  } while (false)
3721cb0ef41Sopenharmony_ci#define ADVANCE_CURRENT_POSITION(by) SET_CURRENT_POSITION(current + (by))
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_ci#ifdef DEBUG
3751cb0ef41Sopenharmony_ci#define BYTECODE(name)                                                \
3761cb0ef41Sopenharmony_ci  BC_LABEL(name)                                                      \
3771cb0ef41Sopenharmony_ci  MaybeTraceInterpreter(code_base, pc, backtrack_stack.sp(), current, \
3781cb0ef41Sopenharmony_ci                        current_char, RegExpBytecodeLength(BC_##name), #name);
3791cb0ef41Sopenharmony_ci#else
3801cb0ef41Sopenharmony_ci#define BYTECODE(name) BC_LABEL(name)
3811cb0ef41Sopenharmony_ci#endif  // DEBUG
3821cb0ef41Sopenharmony_ci
3831cb0ef41Sopenharmony_citemplate <typename Char>
3841cb0ef41Sopenharmony_ciIrregexpInterpreter::Result RawMatch(
3851cb0ef41Sopenharmony_ci    Isolate* isolate, ByteArray code_array, String subject_string,
3861cb0ef41Sopenharmony_ci    base::Vector<const Char> subject, int* output_registers,
3871cb0ef41Sopenharmony_ci    int output_register_count, int total_register_count, int current,
3881cb0ef41Sopenharmony_ci    uint32_t current_char, RegExp::CallOrigin call_origin,
3891cb0ef41Sopenharmony_ci    const uint32_t backtrack_limit) {
3901cb0ef41Sopenharmony_ci  DisallowGarbageCollection no_gc;
3911cb0ef41Sopenharmony_ci
3921cb0ef41Sopenharmony_ci#if V8_USE_COMPUTED_GOTO
3931cb0ef41Sopenharmony_ci
3941cb0ef41Sopenharmony_ci// We have to make sure that no OOB access to the dispatch table is possible and
3951cb0ef41Sopenharmony_ci// all values are valid label addresses.
3961cb0ef41Sopenharmony_ci// Otherwise jumps to arbitrary addresses could potentially happen.
3971cb0ef41Sopenharmony_ci// This is ensured as follows:
3981cb0ef41Sopenharmony_ci// Every index to the dispatch table gets masked using BYTECODE_MASK in
3991cb0ef41Sopenharmony_ci// DECODE(). This way we can only get values between 0 (only the least
4001cb0ef41Sopenharmony_ci// significant byte of an integer is used) and kRegExpPaddedBytecodeCount - 1
4011cb0ef41Sopenharmony_ci// (BYTECODE_MASK is defined to be exactly this value).
4021cb0ef41Sopenharmony_ci// All entries from kRegExpBytecodeCount to kRegExpPaddedBytecodeCount have to
4031cb0ef41Sopenharmony_ci// be filled with BREAKs (invalid operation).
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ci// Fill dispatch table from last defined bytecode up to the next power of two
4061cb0ef41Sopenharmony_ci// with BREAK (invalid operation).
4071cb0ef41Sopenharmony_ci// TODO(pthier): Find a way to fill up automatically (at compile time)
4081cb0ef41Sopenharmony_ci// 59 real bytecodes -> 5 fillers
4091cb0ef41Sopenharmony_ci#define BYTECODE_FILLER_ITERATOR(V) \
4101cb0ef41Sopenharmony_ci  V(BREAK) /* 1 */                  \
4111cb0ef41Sopenharmony_ci  V(BREAK) /* 2 */                  \
4121cb0ef41Sopenharmony_ci  V(BREAK) /* 3 */                  \
4131cb0ef41Sopenharmony_ci  V(BREAK) /* 4 */                  \
4141cb0ef41Sopenharmony_ci  V(BREAK) /* 5 */
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_ci#define COUNT(...) +1
4171cb0ef41Sopenharmony_ci  static constexpr int kRegExpBytecodeFillerCount =
4181cb0ef41Sopenharmony_ci      BYTECODE_FILLER_ITERATOR(COUNT);
4191cb0ef41Sopenharmony_ci#undef COUNT
4201cb0ef41Sopenharmony_ci
4211cb0ef41Sopenharmony_ci  // Make sure kRegExpPaddedBytecodeCount is actually the closest possible power
4221cb0ef41Sopenharmony_ci  // of two.
4231cb0ef41Sopenharmony_ci  DCHECK_EQ(kRegExpPaddedBytecodeCount,
4241cb0ef41Sopenharmony_ci            base::bits::RoundUpToPowerOfTwo32(kRegExpBytecodeCount));
4251cb0ef41Sopenharmony_ci
4261cb0ef41Sopenharmony_ci  // Make sure every bytecode we get by using BYTECODE_MASK is well defined.
4271cb0ef41Sopenharmony_ci  STATIC_ASSERT(kRegExpBytecodeCount <= kRegExpPaddedBytecodeCount);
4281cb0ef41Sopenharmony_ci  STATIC_ASSERT(kRegExpBytecodeCount + kRegExpBytecodeFillerCount ==
4291cb0ef41Sopenharmony_ci                kRegExpPaddedBytecodeCount);
4301cb0ef41Sopenharmony_ci
4311cb0ef41Sopenharmony_ci#define DECLARE_DISPATCH_TABLE_ENTRY(name, ...) &&BC_##name,
4321cb0ef41Sopenharmony_ci  static const void* const dispatch_table[kRegExpPaddedBytecodeCount] = {
4331cb0ef41Sopenharmony_ci      BYTECODE_ITERATOR(DECLARE_DISPATCH_TABLE_ENTRY)
4341cb0ef41Sopenharmony_ci          BYTECODE_FILLER_ITERATOR(DECLARE_DISPATCH_TABLE_ENTRY)};
4351cb0ef41Sopenharmony_ci#undef DECLARE_DISPATCH_TABLE_ENTRY
4361cb0ef41Sopenharmony_ci#undef BYTECODE_FILLER_ITERATOR
4371cb0ef41Sopenharmony_ci
4381cb0ef41Sopenharmony_ci#endif  // V8_USE_COMPUTED_GOTO
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_ci  const byte* pc = code_array.GetDataStartAddress();
4411cb0ef41Sopenharmony_ci  const byte* code_base = pc;
4421cb0ef41Sopenharmony_ci
4431cb0ef41Sopenharmony_ci  InterpreterRegisters registers(total_register_count, output_registers,
4441cb0ef41Sopenharmony_ci                                 output_register_count);
4451cb0ef41Sopenharmony_ci  BacktrackStack backtrack_stack;
4461cb0ef41Sopenharmony_ci
4471cb0ef41Sopenharmony_ci  uint32_t backtrack_count = 0;
4481cb0ef41Sopenharmony_ci
4491cb0ef41Sopenharmony_ci#ifdef DEBUG
4501cb0ef41Sopenharmony_ci  if (FLAG_trace_regexp_bytecodes) {
4511cb0ef41Sopenharmony_ci    PrintF("\n\nStart bytecode interpreter\n\n");
4521cb0ef41Sopenharmony_ci  }
4531cb0ef41Sopenharmony_ci#endif
4541cb0ef41Sopenharmony_ci
4551cb0ef41Sopenharmony_ci  while (true) {
4561cb0ef41Sopenharmony_ci    const byte* next_pc = pc;
4571cb0ef41Sopenharmony_ci    int32_t insn;
4581cb0ef41Sopenharmony_ci    int32_t next_insn;
4591cb0ef41Sopenharmony_ci#if V8_USE_COMPUTED_GOTO
4601cb0ef41Sopenharmony_ci    const void* next_handler_addr;
4611cb0ef41Sopenharmony_ci    DECODE();
4621cb0ef41Sopenharmony_ci    DISPATCH();
4631cb0ef41Sopenharmony_ci#else
4641cb0ef41Sopenharmony_ci    insn = Load32Aligned(pc);
4651cb0ef41Sopenharmony_ci    switch (insn & BYTECODE_MASK) {
4661cb0ef41Sopenharmony_ci#endif  // V8_USE_COMPUTED_GOTO
4671cb0ef41Sopenharmony_ci    BYTECODE(BREAK) { UNREACHABLE(); }
4681cb0ef41Sopenharmony_ci    BYTECODE(PUSH_CP) {
4691cb0ef41Sopenharmony_ci      ADVANCE(PUSH_CP);
4701cb0ef41Sopenharmony_ci      if (!backtrack_stack.push(current)) {
4711cb0ef41Sopenharmony_ci        return MaybeThrowStackOverflow(isolate, call_origin);
4721cb0ef41Sopenharmony_ci      }
4731cb0ef41Sopenharmony_ci      DISPATCH();
4741cb0ef41Sopenharmony_ci    }
4751cb0ef41Sopenharmony_ci    BYTECODE(PUSH_BT) {
4761cb0ef41Sopenharmony_ci      ADVANCE(PUSH_BT);
4771cb0ef41Sopenharmony_ci      if (!backtrack_stack.push(Load32Aligned(pc + 4))) {
4781cb0ef41Sopenharmony_ci        return MaybeThrowStackOverflow(isolate, call_origin);
4791cb0ef41Sopenharmony_ci      }
4801cb0ef41Sopenharmony_ci      DISPATCH();
4811cb0ef41Sopenharmony_ci    }
4821cb0ef41Sopenharmony_ci    BYTECODE(PUSH_REGISTER) {
4831cb0ef41Sopenharmony_ci      ADVANCE(PUSH_REGISTER);
4841cb0ef41Sopenharmony_ci      if (!backtrack_stack.push(registers[LoadPacked24Unsigned(insn)])) {
4851cb0ef41Sopenharmony_ci        return MaybeThrowStackOverflow(isolate, call_origin);
4861cb0ef41Sopenharmony_ci      }
4871cb0ef41Sopenharmony_ci      DISPATCH();
4881cb0ef41Sopenharmony_ci    }
4891cb0ef41Sopenharmony_ci    BYTECODE(SET_REGISTER) {
4901cb0ef41Sopenharmony_ci      ADVANCE(SET_REGISTER);
4911cb0ef41Sopenharmony_ci      registers[LoadPacked24Unsigned(insn)] = Load32Aligned(pc + 4);
4921cb0ef41Sopenharmony_ci      DISPATCH();
4931cb0ef41Sopenharmony_ci    }
4941cb0ef41Sopenharmony_ci    BYTECODE(ADVANCE_REGISTER) {
4951cb0ef41Sopenharmony_ci      ADVANCE(ADVANCE_REGISTER);
4961cb0ef41Sopenharmony_ci      registers[LoadPacked24Unsigned(insn)] += Load32Aligned(pc + 4);
4971cb0ef41Sopenharmony_ci      DISPATCH();
4981cb0ef41Sopenharmony_ci    }
4991cb0ef41Sopenharmony_ci    BYTECODE(SET_REGISTER_TO_CP) {
5001cb0ef41Sopenharmony_ci      ADVANCE(SET_REGISTER_TO_CP);
5011cb0ef41Sopenharmony_ci      registers[LoadPacked24Unsigned(insn)] = current + Load32Aligned(pc + 4);
5021cb0ef41Sopenharmony_ci      DISPATCH();
5031cb0ef41Sopenharmony_ci    }
5041cb0ef41Sopenharmony_ci    BYTECODE(SET_CP_TO_REGISTER) {
5051cb0ef41Sopenharmony_ci      ADVANCE(SET_CP_TO_REGISTER);
5061cb0ef41Sopenharmony_ci      SET_CURRENT_POSITION(registers[LoadPacked24Unsigned(insn)]);
5071cb0ef41Sopenharmony_ci      DISPATCH();
5081cb0ef41Sopenharmony_ci    }
5091cb0ef41Sopenharmony_ci    BYTECODE(SET_REGISTER_TO_SP) {
5101cb0ef41Sopenharmony_ci      ADVANCE(SET_REGISTER_TO_SP);
5111cb0ef41Sopenharmony_ci      registers[LoadPacked24Unsigned(insn)] = backtrack_stack.sp();
5121cb0ef41Sopenharmony_ci      DISPATCH();
5131cb0ef41Sopenharmony_ci    }
5141cb0ef41Sopenharmony_ci    BYTECODE(SET_SP_TO_REGISTER) {
5151cb0ef41Sopenharmony_ci      ADVANCE(SET_SP_TO_REGISTER);
5161cb0ef41Sopenharmony_ci      backtrack_stack.set_sp(registers[LoadPacked24Unsigned(insn)]);
5171cb0ef41Sopenharmony_ci      DISPATCH();
5181cb0ef41Sopenharmony_ci    }
5191cb0ef41Sopenharmony_ci    BYTECODE(POP_CP) {
5201cb0ef41Sopenharmony_ci      ADVANCE(POP_CP);
5211cb0ef41Sopenharmony_ci      SET_CURRENT_POSITION(backtrack_stack.pop());
5221cb0ef41Sopenharmony_ci      DISPATCH();
5231cb0ef41Sopenharmony_ci    }
5241cb0ef41Sopenharmony_ci    BYTECODE(POP_BT) {
5251cb0ef41Sopenharmony_ci      STATIC_ASSERT(JSRegExp::kNoBacktrackLimit == 0);
5261cb0ef41Sopenharmony_ci      if (++backtrack_count == backtrack_limit) {
5271cb0ef41Sopenharmony_ci        int return_code = LoadPacked24Signed(insn);
5281cb0ef41Sopenharmony_ci        return static_cast<IrregexpInterpreter::Result>(return_code);
5291cb0ef41Sopenharmony_ci      }
5301cb0ef41Sopenharmony_ci
5311cb0ef41Sopenharmony_ci      IrregexpInterpreter::Result return_code =
5321cb0ef41Sopenharmony_ci          HandleInterrupts(isolate, call_origin, &code_array, &subject_string,
5331cb0ef41Sopenharmony_ci                           &code_base, &subject, &pc);
5341cb0ef41Sopenharmony_ci      if (return_code != IrregexpInterpreter::SUCCESS) return return_code;
5351cb0ef41Sopenharmony_ci
5361cb0ef41Sopenharmony_ci      SET_PC_FROM_OFFSET(backtrack_stack.pop());
5371cb0ef41Sopenharmony_ci      DISPATCH();
5381cb0ef41Sopenharmony_ci    }
5391cb0ef41Sopenharmony_ci    BYTECODE(POP_REGISTER) {
5401cb0ef41Sopenharmony_ci      ADVANCE(POP_REGISTER);
5411cb0ef41Sopenharmony_ci      registers[LoadPacked24Unsigned(insn)] = backtrack_stack.pop();
5421cb0ef41Sopenharmony_ci      DISPATCH();
5431cb0ef41Sopenharmony_ci    }
5441cb0ef41Sopenharmony_ci    BYTECODE(FAIL) {
5451cb0ef41Sopenharmony_ci      isolate->counters()->regexp_backtracks()->AddSample(
5461cb0ef41Sopenharmony_ci          static_cast<int>(backtrack_count));
5471cb0ef41Sopenharmony_ci      return IrregexpInterpreter::FAILURE;
5481cb0ef41Sopenharmony_ci    }
5491cb0ef41Sopenharmony_ci    BYTECODE(SUCCEED) {
5501cb0ef41Sopenharmony_ci      isolate->counters()->regexp_backtracks()->AddSample(
5511cb0ef41Sopenharmony_ci          static_cast<int>(backtrack_count));
5521cb0ef41Sopenharmony_ci      registers.CopyToOutputRegisters();
5531cb0ef41Sopenharmony_ci      return IrregexpInterpreter::SUCCESS;
5541cb0ef41Sopenharmony_ci    }
5551cb0ef41Sopenharmony_ci    BYTECODE(ADVANCE_CP) {
5561cb0ef41Sopenharmony_ci      ADVANCE(ADVANCE_CP);
5571cb0ef41Sopenharmony_ci      ADVANCE_CURRENT_POSITION(LoadPacked24Signed(insn));
5581cb0ef41Sopenharmony_ci      DISPATCH();
5591cb0ef41Sopenharmony_ci    }
5601cb0ef41Sopenharmony_ci    BYTECODE(GOTO) {
5611cb0ef41Sopenharmony_ci      SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
5621cb0ef41Sopenharmony_ci      DISPATCH();
5631cb0ef41Sopenharmony_ci    }
5641cb0ef41Sopenharmony_ci    BYTECODE(ADVANCE_CP_AND_GOTO) {
5651cb0ef41Sopenharmony_ci      SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
5661cb0ef41Sopenharmony_ci      ADVANCE_CURRENT_POSITION(LoadPacked24Signed(insn));
5671cb0ef41Sopenharmony_ci      DISPATCH();
5681cb0ef41Sopenharmony_ci    }
5691cb0ef41Sopenharmony_ci    BYTECODE(CHECK_GREEDY) {
5701cb0ef41Sopenharmony_ci      if (current == backtrack_stack.peek()) {
5711cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
5721cb0ef41Sopenharmony_ci        backtrack_stack.pop();
5731cb0ef41Sopenharmony_ci      } else {
5741cb0ef41Sopenharmony_ci        ADVANCE(CHECK_GREEDY);
5751cb0ef41Sopenharmony_ci      }
5761cb0ef41Sopenharmony_ci      DISPATCH();
5771cb0ef41Sopenharmony_ci    }
5781cb0ef41Sopenharmony_ci    BYTECODE(LOAD_CURRENT_CHAR) {
5791cb0ef41Sopenharmony_ci      int pos = current + LoadPacked24Signed(insn);
5801cb0ef41Sopenharmony_ci      if (pos >= subject.length() || pos < 0) {
5811cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
5821cb0ef41Sopenharmony_ci      } else {
5831cb0ef41Sopenharmony_ci        ADVANCE(LOAD_CURRENT_CHAR);
5841cb0ef41Sopenharmony_ci        current_char = subject[pos];
5851cb0ef41Sopenharmony_ci      }
5861cb0ef41Sopenharmony_ci      DISPATCH();
5871cb0ef41Sopenharmony_ci    }
5881cb0ef41Sopenharmony_ci    BYTECODE(LOAD_CURRENT_CHAR_UNCHECKED) {
5891cb0ef41Sopenharmony_ci      ADVANCE(LOAD_CURRENT_CHAR_UNCHECKED);
5901cb0ef41Sopenharmony_ci      int pos = current + LoadPacked24Signed(insn);
5911cb0ef41Sopenharmony_ci      current_char = subject[pos];
5921cb0ef41Sopenharmony_ci      DISPATCH();
5931cb0ef41Sopenharmony_ci    }
5941cb0ef41Sopenharmony_ci    BYTECODE(LOAD_2_CURRENT_CHARS) {
5951cb0ef41Sopenharmony_ci      int pos = current + LoadPacked24Signed(insn);
5961cb0ef41Sopenharmony_ci      if (pos + 2 > subject.length() || pos < 0) {
5971cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
5981cb0ef41Sopenharmony_ci      } else {
5991cb0ef41Sopenharmony_ci        ADVANCE(LOAD_2_CURRENT_CHARS);
6001cb0ef41Sopenharmony_ci        Char next = subject[pos + 1];
6011cb0ef41Sopenharmony_ci        current_char = (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
6021cb0ef41Sopenharmony_ci      }
6031cb0ef41Sopenharmony_ci      DISPATCH();
6041cb0ef41Sopenharmony_ci    }
6051cb0ef41Sopenharmony_ci    BYTECODE(LOAD_2_CURRENT_CHARS_UNCHECKED) {
6061cb0ef41Sopenharmony_ci      ADVANCE(LOAD_2_CURRENT_CHARS_UNCHECKED);
6071cb0ef41Sopenharmony_ci      int pos = current + LoadPacked24Signed(insn);
6081cb0ef41Sopenharmony_ci      Char next = subject[pos + 1];
6091cb0ef41Sopenharmony_ci      current_char = (subject[pos] | (next << (kBitsPerByte * sizeof(Char))));
6101cb0ef41Sopenharmony_ci      DISPATCH();
6111cb0ef41Sopenharmony_ci    }
6121cb0ef41Sopenharmony_ci    BYTECODE(LOAD_4_CURRENT_CHARS) {
6131cb0ef41Sopenharmony_ci      DCHECK_EQ(1, sizeof(Char));
6141cb0ef41Sopenharmony_ci      int pos = current + LoadPacked24Signed(insn);
6151cb0ef41Sopenharmony_ci      if (pos + 4 > subject.length() || pos < 0) {
6161cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
6171cb0ef41Sopenharmony_ci      } else {
6181cb0ef41Sopenharmony_ci        ADVANCE(LOAD_4_CURRENT_CHARS);
6191cb0ef41Sopenharmony_ci        Char next1 = subject[pos + 1];
6201cb0ef41Sopenharmony_ci        Char next2 = subject[pos + 2];
6211cb0ef41Sopenharmony_ci        Char next3 = subject[pos + 3];
6221cb0ef41Sopenharmony_ci        current_char =
6231cb0ef41Sopenharmony_ci            (subject[pos] | (next1 << 8) | (next2 << 16) | (next3 << 24));
6241cb0ef41Sopenharmony_ci      }
6251cb0ef41Sopenharmony_ci      DISPATCH();
6261cb0ef41Sopenharmony_ci    }
6271cb0ef41Sopenharmony_ci    BYTECODE(LOAD_4_CURRENT_CHARS_UNCHECKED) {
6281cb0ef41Sopenharmony_ci      ADVANCE(LOAD_4_CURRENT_CHARS_UNCHECKED);
6291cb0ef41Sopenharmony_ci      DCHECK_EQ(1, sizeof(Char));
6301cb0ef41Sopenharmony_ci      int pos = current + LoadPacked24Signed(insn);
6311cb0ef41Sopenharmony_ci      Char next1 = subject[pos + 1];
6321cb0ef41Sopenharmony_ci      Char next2 = subject[pos + 2];
6331cb0ef41Sopenharmony_ci      Char next3 = subject[pos + 3];
6341cb0ef41Sopenharmony_ci      current_char =
6351cb0ef41Sopenharmony_ci          (subject[pos] | (next1 << 8) | (next2 << 16) | (next3 << 24));
6361cb0ef41Sopenharmony_ci      DISPATCH();
6371cb0ef41Sopenharmony_ci    }
6381cb0ef41Sopenharmony_ci    BYTECODE(CHECK_4_CHARS) {
6391cb0ef41Sopenharmony_ci      uint32_t c = Load32Aligned(pc + 4);
6401cb0ef41Sopenharmony_ci      if (c == current_char) {
6411cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
6421cb0ef41Sopenharmony_ci      } else {
6431cb0ef41Sopenharmony_ci        ADVANCE(CHECK_4_CHARS);
6441cb0ef41Sopenharmony_ci      }
6451cb0ef41Sopenharmony_ci      DISPATCH();
6461cb0ef41Sopenharmony_ci    }
6471cb0ef41Sopenharmony_ci    BYTECODE(CHECK_CHAR) {
6481cb0ef41Sopenharmony_ci      uint32_t c = LoadPacked24Unsigned(insn);
6491cb0ef41Sopenharmony_ci      if (c == current_char) {
6501cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
6511cb0ef41Sopenharmony_ci      } else {
6521cb0ef41Sopenharmony_ci        ADVANCE(CHECK_CHAR);
6531cb0ef41Sopenharmony_ci      }
6541cb0ef41Sopenharmony_ci      DISPATCH();
6551cb0ef41Sopenharmony_ci    }
6561cb0ef41Sopenharmony_ci    BYTECODE(CHECK_NOT_4_CHARS) {
6571cb0ef41Sopenharmony_ci      uint32_t c = Load32Aligned(pc + 4);
6581cb0ef41Sopenharmony_ci      if (c != current_char) {
6591cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
6601cb0ef41Sopenharmony_ci      } else {
6611cb0ef41Sopenharmony_ci        ADVANCE(CHECK_NOT_4_CHARS);
6621cb0ef41Sopenharmony_ci      }
6631cb0ef41Sopenharmony_ci      DISPATCH();
6641cb0ef41Sopenharmony_ci    }
6651cb0ef41Sopenharmony_ci    BYTECODE(CHECK_NOT_CHAR) {
6661cb0ef41Sopenharmony_ci      uint32_t c = LoadPacked24Unsigned(insn);
6671cb0ef41Sopenharmony_ci      if (c != current_char) {
6681cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
6691cb0ef41Sopenharmony_ci      } else {
6701cb0ef41Sopenharmony_ci        ADVANCE(CHECK_NOT_CHAR);
6711cb0ef41Sopenharmony_ci      }
6721cb0ef41Sopenharmony_ci      DISPATCH();
6731cb0ef41Sopenharmony_ci    }
6741cb0ef41Sopenharmony_ci    BYTECODE(AND_CHECK_4_CHARS) {
6751cb0ef41Sopenharmony_ci      uint32_t c = Load32Aligned(pc + 4);
6761cb0ef41Sopenharmony_ci      if (c == (current_char & Load32Aligned(pc + 8))) {
6771cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 12));
6781cb0ef41Sopenharmony_ci      } else {
6791cb0ef41Sopenharmony_ci        ADVANCE(AND_CHECK_4_CHARS);
6801cb0ef41Sopenharmony_ci      }
6811cb0ef41Sopenharmony_ci      DISPATCH();
6821cb0ef41Sopenharmony_ci    }
6831cb0ef41Sopenharmony_ci    BYTECODE(AND_CHECK_CHAR) {
6841cb0ef41Sopenharmony_ci      uint32_t c = LoadPacked24Unsigned(insn);
6851cb0ef41Sopenharmony_ci      if (c == (current_char & Load32Aligned(pc + 4))) {
6861cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
6871cb0ef41Sopenharmony_ci      } else {
6881cb0ef41Sopenharmony_ci        ADVANCE(AND_CHECK_CHAR);
6891cb0ef41Sopenharmony_ci      }
6901cb0ef41Sopenharmony_ci      DISPATCH();
6911cb0ef41Sopenharmony_ci    }
6921cb0ef41Sopenharmony_ci    BYTECODE(AND_CHECK_NOT_4_CHARS) {
6931cb0ef41Sopenharmony_ci      uint32_t c = Load32Aligned(pc + 4);
6941cb0ef41Sopenharmony_ci      if (c != (current_char & Load32Aligned(pc + 8))) {
6951cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 12));
6961cb0ef41Sopenharmony_ci      } else {
6971cb0ef41Sopenharmony_ci        ADVANCE(AND_CHECK_NOT_4_CHARS);
6981cb0ef41Sopenharmony_ci      }
6991cb0ef41Sopenharmony_ci      DISPATCH();
7001cb0ef41Sopenharmony_ci    }
7011cb0ef41Sopenharmony_ci    BYTECODE(AND_CHECK_NOT_CHAR) {
7021cb0ef41Sopenharmony_ci      uint32_t c = LoadPacked24Unsigned(insn);
7031cb0ef41Sopenharmony_ci      if (c != (current_char & Load32Aligned(pc + 4))) {
7041cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
7051cb0ef41Sopenharmony_ci      } else {
7061cb0ef41Sopenharmony_ci        ADVANCE(AND_CHECK_NOT_CHAR);
7071cb0ef41Sopenharmony_ci      }
7081cb0ef41Sopenharmony_ci      DISPATCH();
7091cb0ef41Sopenharmony_ci    }
7101cb0ef41Sopenharmony_ci    BYTECODE(MINUS_AND_CHECK_NOT_CHAR) {
7111cb0ef41Sopenharmony_ci      uint32_t c = LoadPacked24Unsigned(insn);
7121cb0ef41Sopenharmony_ci      uint32_t minus = Load16Aligned(pc + 4);
7131cb0ef41Sopenharmony_ci      uint32_t mask = Load16Aligned(pc + 6);
7141cb0ef41Sopenharmony_ci      if (c != ((current_char - minus) & mask)) {
7151cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
7161cb0ef41Sopenharmony_ci      } else {
7171cb0ef41Sopenharmony_ci        ADVANCE(MINUS_AND_CHECK_NOT_CHAR);
7181cb0ef41Sopenharmony_ci      }
7191cb0ef41Sopenharmony_ci      DISPATCH();
7201cb0ef41Sopenharmony_ci    }
7211cb0ef41Sopenharmony_ci    BYTECODE(CHECK_CHAR_IN_RANGE) {
7221cb0ef41Sopenharmony_ci      uint32_t from = Load16Aligned(pc + 4);
7231cb0ef41Sopenharmony_ci      uint32_t to = Load16Aligned(pc + 6);
7241cb0ef41Sopenharmony_ci      if (from <= current_char && current_char <= to) {
7251cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
7261cb0ef41Sopenharmony_ci      } else {
7271cb0ef41Sopenharmony_ci        ADVANCE(CHECK_CHAR_IN_RANGE);
7281cb0ef41Sopenharmony_ci      }
7291cb0ef41Sopenharmony_ci      DISPATCH();
7301cb0ef41Sopenharmony_ci    }
7311cb0ef41Sopenharmony_ci    BYTECODE(CHECK_CHAR_NOT_IN_RANGE) {
7321cb0ef41Sopenharmony_ci      uint32_t from = Load16Aligned(pc + 4);
7331cb0ef41Sopenharmony_ci      uint32_t to = Load16Aligned(pc + 6);
7341cb0ef41Sopenharmony_ci      if (from > current_char || current_char > to) {
7351cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
7361cb0ef41Sopenharmony_ci      } else {
7371cb0ef41Sopenharmony_ci        ADVANCE(CHECK_CHAR_NOT_IN_RANGE);
7381cb0ef41Sopenharmony_ci      }
7391cb0ef41Sopenharmony_ci      DISPATCH();
7401cb0ef41Sopenharmony_ci    }
7411cb0ef41Sopenharmony_ci    BYTECODE(CHECK_BIT_IN_TABLE) {
7421cb0ef41Sopenharmony_ci      if (CheckBitInTable(current_char, pc + 8)) {
7431cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
7441cb0ef41Sopenharmony_ci      } else {
7451cb0ef41Sopenharmony_ci        ADVANCE(CHECK_BIT_IN_TABLE);
7461cb0ef41Sopenharmony_ci      }
7471cb0ef41Sopenharmony_ci      DISPATCH();
7481cb0ef41Sopenharmony_ci    }
7491cb0ef41Sopenharmony_ci    BYTECODE(CHECK_LT) {
7501cb0ef41Sopenharmony_ci      uint32_t limit = LoadPacked24Unsigned(insn);
7511cb0ef41Sopenharmony_ci      if (current_char < limit) {
7521cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
7531cb0ef41Sopenharmony_ci      } else {
7541cb0ef41Sopenharmony_ci        ADVANCE(CHECK_LT);
7551cb0ef41Sopenharmony_ci      }
7561cb0ef41Sopenharmony_ci      DISPATCH();
7571cb0ef41Sopenharmony_ci    }
7581cb0ef41Sopenharmony_ci    BYTECODE(CHECK_GT) {
7591cb0ef41Sopenharmony_ci      uint32_t limit = LoadPacked24Unsigned(insn);
7601cb0ef41Sopenharmony_ci      if (current_char > limit) {
7611cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
7621cb0ef41Sopenharmony_ci      } else {
7631cb0ef41Sopenharmony_ci        ADVANCE(CHECK_GT);
7641cb0ef41Sopenharmony_ci      }
7651cb0ef41Sopenharmony_ci      DISPATCH();
7661cb0ef41Sopenharmony_ci    }
7671cb0ef41Sopenharmony_ci    BYTECODE(CHECK_REGISTER_LT) {
7681cb0ef41Sopenharmony_ci      if (registers[LoadPacked24Unsigned(insn)] < Load32Aligned(pc + 4)) {
7691cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
7701cb0ef41Sopenharmony_ci      } else {
7711cb0ef41Sopenharmony_ci        ADVANCE(CHECK_REGISTER_LT);
7721cb0ef41Sopenharmony_ci      }
7731cb0ef41Sopenharmony_ci      DISPATCH();
7741cb0ef41Sopenharmony_ci    }
7751cb0ef41Sopenharmony_ci    BYTECODE(CHECK_REGISTER_GE) {
7761cb0ef41Sopenharmony_ci      if (registers[LoadPacked24Unsigned(insn)] >= Load32Aligned(pc + 4)) {
7771cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
7781cb0ef41Sopenharmony_ci      } else {
7791cb0ef41Sopenharmony_ci        ADVANCE(CHECK_REGISTER_GE);
7801cb0ef41Sopenharmony_ci      }
7811cb0ef41Sopenharmony_ci      DISPATCH();
7821cb0ef41Sopenharmony_ci    }
7831cb0ef41Sopenharmony_ci    BYTECODE(CHECK_REGISTER_EQ_POS) {
7841cb0ef41Sopenharmony_ci      if (registers[LoadPacked24Unsigned(insn)] == current) {
7851cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
7861cb0ef41Sopenharmony_ci      } else {
7871cb0ef41Sopenharmony_ci        ADVANCE(CHECK_REGISTER_EQ_POS);
7881cb0ef41Sopenharmony_ci      }
7891cb0ef41Sopenharmony_ci      DISPATCH();
7901cb0ef41Sopenharmony_ci    }
7911cb0ef41Sopenharmony_ci    BYTECODE(CHECK_NOT_REGS_EQUAL) {
7921cb0ef41Sopenharmony_ci      if (registers[LoadPacked24Unsigned(insn)] ==
7931cb0ef41Sopenharmony_ci          registers[Load32Aligned(pc + 4)]) {
7941cb0ef41Sopenharmony_ci        ADVANCE(CHECK_NOT_REGS_EQUAL);
7951cb0ef41Sopenharmony_ci      } else {
7961cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
7971cb0ef41Sopenharmony_ci      }
7981cb0ef41Sopenharmony_ci      DISPATCH();
7991cb0ef41Sopenharmony_ci    }
8001cb0ef41Sopenharmony_ci    BYTECODE(CHECK_NOT_BACK_REF) {
8011cb0ef41Sopenharmony_ci      int from = registers[LoadPacked24Unsigned(insn)];
8021cb0ef41Sopenharmony_ci      int len = registers[LoadPacked24Unsigned(insn) + 1] - from;
8031cb0ef41Sopenharmony_ci      if (from >= 0 && len > 0) {
8041cb0ef41Sopenharmony_ci        if (current + len > subject.length() ||
8051cb0ef41Sopenharmony_ci            !CompareCharsEqual(&subject[from], &subject[current], len)) {
8061cb0ef41Sopenharmony_ci          SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
8071cb0ef41Sopenharmony_ci          DISPATCH();
8081cb0ef41Sopenharmony_ci        }
8091cb0ef41Sopenharmony_ci        ADVANCE_CURRENT_POSITION(len);
8101cb0ef41Sopenharmony_ci      }
8111cb0ef41Sopenharmony_ci      ADVANCE(CHECK_NOT_BACK_REF);
8121cb0ef41Sopenharmony_ci      DISPATCH();
8131cb0ef41Sopenharmony_ci    }
8141cb0ef41Sopenharmony_ci    BYTECODE(CHECK_NOT_BACK_REF_BACKWARD) {
8151cb0ef41Sopenharmony_ci      int from = registers[LoadPacked24Unsigned(insn)];
8161cb0ef41Sopenharmony_ci      int len = registers[LoadPacked24Unsigned(insn) + 1] - from;
8171cb0ef41Sopenharmony_ci      if (from >= 0 && len > 0) {
8181cb0ef41Sopenharmony_ci        if (current - len < 0 ||
8191cb0ef41Sopenharmony_ci            !CompareCharsEqual(&subject[from], &subject[current - len], len)) {
8201cb0ef41Sopenharmony_ci          SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
8211cb0ef41Sopenharmony_ci          DISPATCH();
8221cb0ef41Sopenharmony_ci        }
8231cb0ef41Sopenharmony_ci        SET_CURRENT_POSITION(current - len);
8241cb0ef41Sopenharmony_ci      }
8251cb0ef41Sopenharmony_ci      ADVANCE(CHECK_NOT_BACK_REF_BACKWARD);
8261cb0ef41Sopenharmony_ci      DISPATCH();
8271cb0ef41Sopenharmony_ci    }
8281cb0ef41Sopenharmony_ci    BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE) {
8291cb0ef41Sopenharmony_ci      int from = registers[LoadPacked24Unsigned(insn)];
8301cb0ef41Sopenharmony_ci      int len = registers[LoadPacked24Unsigned(insn) + 1] - from;
8311cb0ef41Sopenharmony_ci      if (from >= 0 && len > 0) {
8321cb0ef41Sopenharmony_ci        if (current + len > subject.length() ||
8331cb0ef41Sopenharmony_ci            !BackRefMatchesNoCase(isolate, from, current, len, subject, true)) {
8341cb0ef41Sopenharmony_ci          SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
8351cb0ef41Sopenharmony_ci          DISPATCH();
8361cb0ef41Sopenharmony_ci        }
8371cb0ef41Sopenharmony_ci        ADVANCE_CURRENT_POSITION(len);
8381cb0ef41Sopenharmony_ci      }
8391cb0ef41Sopenharmony_ci      ADVANCE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE);
8401cb0ef41Sopenharmony_ci      DISPATCH();
8411cb0ef41Sopenharmony_ci    }
8421cb0ef41Sopenharmony_ci    BYTECODE(CHECK_NOT_BACK_REF_NO_CASE) {
8431cb0ef41Sopenharmony_ci      int from = registers[LoadPacked24Unsigned(insn)];
8441cb0ef41Sopenharmony_ci      int len = registers[LoadPacked24Unsigned(insn) + 1] - from;
8451cb0ef41Sopenharmony_ci      if (from >= 0 && len > 0) {
8461cb0ef41Sopenharmony_ci        if (current + len > subject.length() ||
8471cb0ef41Sopenharmony_ci            !BackRefMatchesNoCase(isolate, from, current, len, subject,
8481cb0ef41Sopenharmony_ci                                  false)) {
8491cb0ef41Sopenharmony_ci          SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
8501cb0ef41Sopenharmony_ci          DISPATCH();
8511cb0ef41Sopenharmony_ci        }
8521cb0ef41Sopenharmony_ci        ADVANCE_CURRENT_POSITION(len);
8531cb0ef41Sopenharmony_ci      }
8541cb0ef41Sopenharmony_ci      ADVANCE(CHECK_NOT_BACK_REF_NO_CASE);
8551cb0ef41Sopenharmony_ci      DISPATCH();
8561cb0ef41Sopenharmony_ci    }
8571cb0ef41Sopenharmony_ci    BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE_BACKWARD) {
8581cb0ef41Sopenharmony_ci      int from = registers[LoadPacked24Unsigned(insn)];
8591cb0ef41Sopenharmony_ci      int len = registers[LoadPacked24Unsigned(insn) + 1] - from;
8601cb0ef41Sopenharmony_ci      if (from >= 0 && len > 0) {
8611cb0ef41Sopenharmony_ci        if (current - len < 0 ||
8621cb0ef41Sopenharmony_ci            !BackRefMatchesNoCase(isolate, from, current - len, len, subject,
8631cb0ef41Sopenharmony_ci                                  true)) {
8641cb0ef41Sopenharmony_ci          SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
8651cb0ef41Sopenharmony_ci          DISPATCH();
8661cb0ef41Sopenharmony_ci        }
8671cb0ef41Sopenharmony_ci        SET_CURRENT_POSITION(current - len);
8681cb0ef41Sopenharmony_ci      }
8691cb0ef41Sopenharmony_ci      ADVANCE(CHECK_NOT_BACK_REF_NO_CASE_UNICODE_BACKWARD);
8701cb0ef41Sopenharmony_ci      DISPATCH();
8711cb0ef41Sopenharmony_ci    }
8721cb0ef41Sopenharmony_ci    BYTECODE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD) {
8731cb0ef41Sopenharmony_ci      int from = registers[LoadPacked24Unsigned(insn)];
8741cb0ef41Sopenharmony_ci      int len = registers[LoadPacked24Unsigned(insn) + 1] - from;
8751cb0ef41Sopenharmony_ci      if (from >= 0 && len > 0) {
8761cb0ef41Sopenharmony_ci        if (current - len < 0 ||
8771cb0ef41Sopenharmony_ci            !BackRefMatchesNoCase(isolate, from, current - len, len, subject,
8781cb0ef41Sopenharmony_ci                                  false)) {
8791cb0ef41Sopenharmony_ci          SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
8801cb0ef41Sopenharmony_ci          DISPATCH();
8811cb0ef41Sopenharmony_ci        }
8821cb0ef41Sopenharmony_ci        SET_CURRENT_POSITION(current - len);
8831cb0ef41Sopenharmony_ci      }
8841cb0ef41Sopenharmony_ci      ADVANCE(CHECK_NOT_BACK_REF_NO_CASE_BACKWARD);
8851cb0ef41Sopenharmony_ci      DISPATCH();
8861cb0ef41Sopenharmony_ci    }
8871cb0ef41Sopenharmony_ci    BYTECODE(CHECK_AT_START) {
8881cb0ef41Sopenharmony_ci      if (current + LoadPacked24Signed(insn) == 0) {
8891cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
8901cb0ef41Sopenharmony_ci      } else {
8911cb0ef41Sopenharmony_ci        ADVANCE(CHECK_AT_START);
8921cb0ef41Sopenharmony_ci      }
8931cb0ef41Sopenharmony_ci      DISPATCH();
8941cb0ef41Sopenharmony_ci    }
8951cb0ef41Sopenharmony_ci    BYTECODE(CHECK_NOT_AT_START) {
8961cb0ef41Sopenharmony_ci      if (current + LoadPacked24Signed(insn) == 0) {
8971cb0ef41Sopenharmony_ci        ADVANCE(CHECK_NOT_AT_START);
8981cb0ef41Sopenharmony_ci      } else {
8991cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
9001cb0ef41Sopenharmony_ci      }
9011cb0ef41Sopenharmony_ci      DISPATCH();
9021cb0ef41Sopenharmony_ci    }
9031cb0ef41Sopenharmony_ci    BYTECODE(SET_CURRENT_POSITION_FROM_END) {
9041cb0ef41Sopenharmony_ci      ADVANCE(SET_CURRENT_POSITION_FROM_END);
9051cb0ef41Sopenharmony_ci      int by = LoadPacked24Unsigned(insn);
9061cb0ef41Sopenharmony_ci      if (subject.length() - current > by) {
9071cb0ef41Sopenharmony_ci        SET_CURRENT_POSITION(subject.length() - by);
9081cb0ef41Sopenharmony_ci        current_char = subject[current - 1];
9091cb0ef41Sopenharmony_ci      }
9101cb0ef41Sopenharmony_ci      DISPATCH();
9111cb0ef41Sopenharmony_ci    }
9121cb0ef41Sopenharmony_ci    BYTECODE(CHECK_CURRENT_POSITION) {
9131cb0ef41Sopenharmony_ci      int pos = current + LoadPacked24Signed(insn);
9141cb0ef41Sopenharmony_ci      if (pos > subject.length() || pos < 0) {
9151cb0ef41Sopenharmony_ci        SET_PC_FROM_OFFSET(Load32Aligned(pc + 4));
9161cb0ef41Sopenharmony_ci      } else {
9171cb0ef41Sopenharmony_ci        ADVANCE(CHECK_CURRENT_POSITION);
9181cb0ef41Sopenharmony_ci      }
9191cb0ef41Sopenharmony_ci      DISPATCH();
9201cb0ef41Sopenharmony_ci    }
9211cb0ef41Sopenharmony_ci    BYTECODE(SKIP_UNTIL_CHAR) {
9221cb0ef41Sopenharmony_ci      int32_t load_offset = LoadPacked24Signed(insn);
9231cb0ef41Sopenharmony_ci      int32_t advance = Load16AlignedSigned(pc + 4);
9241cb0ef41Sopenharmony_ci      uint32_t c = Load16Aligned(pc + 6);
9251cb0ef41Sopenharmony_ci      while (IndexIsInBounds(current + load_offset, subject.length())) {
9261cb0ef41Sopenharmony_ci        current_char = subject[current + load_offset];
9271cb0ef41Sopenharmony_ci        if (c == current_char) {
9281cb0ef41Sopenharmony_ci          SET_PC_FROM_OFFSET(Load32Aligned(pc + 8));
9291cb0ef41Sopenharmony_ci          DISPATCH();
9301cb0ef41Sopenharmony_ci        }
9311cb0ef41Sopenharmony_ci        ADVANCE_CURRENT_POSITION(advance);
9321cb0ef41Sopenharmony_ci      }
9331cb0ef41Sopenharmony_ci      SET_PC_FROM_OFFSET(Load32Aligned(pc + 12));
9341cb0ef41Sopenharmony_ci      DISPATCH();
9351cb0ef41Sopenharmony_ci    }
9361cb0ef41Sopenharmony_ci    BYTECODE(SKIP_UNTIL_CHAR_AND) {
9371cb0ef41Sopenharmony_ci      int32_t load_offset = LoadPacked24Signed(insn);
9381cb0ef41Sopenharmony_ci      int32_t advance = Load16AlignedSigned(pc + 4);
9391cb0ef41Sopenharmony_ci      uint16_t c = Load16Aligned(pc + 6);
9401cb0ef41Sopenharmony_ci      uint32_t mask = Load32Aligned(pc + 8);
9411cb0ef41Sopenharmony_ci      int32_t maximum_offset = Load32Aligned(pc + 12);
9421cb0ef41Sopenharmony_ci      while (static_cast<uintptr_t>(current + maximum_offset) <=
9431cb0ef41Sopenharmony_ci             static_cast<uintptr_t>(subject.length())) {
9441cb0ef41Sopenharmony_ci        current_char = subject[current + load_offset];
9451cb0ef41Sopenharmony_ci        if (c == (current_char & mask)) {
9461cb0ef41Sopenharmony_ci          SET_PC_FROM_OFFSET(Load32Aligned(pc + 16));
9471cb0ef41Sopenharmony_ci          DISPATCH();
9481cb0ef41Sopenharmony_ci        }
9491cb0ef41Sopenharmony_ci        ADVANCE_CURRENT_POSITION(advance);
9501cb0ef41Sopenharmony_ci      }
9511cb0ef41Sopenharmony_ci      SET_PC_FROM_OFFSET(Load32Aligned(pc + 20));
9521cb0ef41Sopenharmony_ci      DISPATCH();
9531cb0ef41Sopenharmony_ci    }
9541cb0ef41Sopenharmony_ci    BYTECODE(SKIP_UNTIL_CHAR_POS_CHECKED) {
9551cb0ef41Sopenharmony_ci      int32_t load_offset = LoadPacked24Signed(insn);
9561cb0ef41Sopenharmony_ci      int32_t advance = Load16AlignedSigned(pc + 4);
9571cb0ef41Sopenharmony_ci      uint16_t c = Load16Aligned(pc + 6);
9581cb0ef41Sopenharmony_ci      int32_t maximum_offset = Load32Aligned(pc + 8);
9591cb0ef41Sopenharmony_ci      while (static_cast<uintptr_t>(current + maximum_offset) <=
9601cb0ef41Sopenharmony_ci             static_cast<uintptr_t>(subject.length())) {
9611cb0ef41Sopenharmony_ci        current_char = subject[current + load_offset];
9621cb0ef41Sopenharmony_ci        if (c == current_char) {
9631cb0ef41Sopenharmony_ci          SET_PC_FROM_OFFSET(Load32Aligned(pc + 12));
9641cb0ef41Sopenharmony_ci          DISPATCH();
9651cb0ef41Sopenharmony_ci        }
9661cb0ef41Sopenharmony_ci        ADVANCE_CURRENT_POSITION(advance);
9671cb0ef41Sopenharmony_ci      }
9681cb0ef41Sopenharmony_ci      SET_PC_FROM_OFFSET(Load32Aligned(pc + 16));
9691cb0ef41Sopenharmony_ci      DISPATCH();
9701cb0ef41Sopenharmony_ci    }
9711cb0ef41Sopenharmony_ci    BYTECODE(SKIP_UNTIL_BIT_IN_TABLE) {
9721cb0ef41Sopenharmony_ci      int32_t load_offset = LoadPacked24Signed(insn);
9731cb0ef41Sopenharmony_ci      int32_t advance = Load16AlignedSigned(pc + 4);
9741cb0ef41Sopenharmony_ci      const byte* table = pc + 8;
9751cb0ef41Sopenharmony_ci      while (IndexIsInBounds(current + load_offset, subject.length())) {
9761cb0ef41Sopenharmony_ci        current_char = subject[current + load_offset];
9771cb0ef41Sopenharmony_ci        if (CheckBitInTable(current_char, table)) {
9781cb0ef41Sopenharmony_ci          SET_PC_FROM_OFFSET(Load32Aligned(pc + 24));
9791cb0ef41Sopenharmony_ci          DISPATCH();
9801cb0ef41Sopenharmony_ci        }
9811cb0ef41Sopenharmony_ci        ADVANCE_CURRENT_POSITION(advance);
9821cb0ef41Sopenharmony_ci      }
9831cb0ef41Sopenharmony_ci      SET_PC_FROM_OFFSET(Load32Aligned(pc + 28));
9841cb0ef41Sopenharmony_ci      DISPATCH();
9851cb0ef41Sopenharmony_ci    }
9861cb0ef41Sopenharmony_ci    BYTECODE(SKIP_UNTIL_GT_OR_NOT_BIT_IN_TABLE) {
9871cb0ef41Sopenharmony_ci      int32_t load_offset = LoadPacked24Signed(insn);
9881cb0ef41Sopenharmony_ci      int32_t advance = Load16AlignedSigned(pc + 4);
9891cb0ef41Sopenharmony_ci      uint16_t limit = Load16Aligned(pc + 6);
9901cb0ef41Sopenharmony_ci      const byte* table = pc + 8;
9911cb0ef41Sopenharmony_ci      while (IndexIsInBounds(current + load_offset, subject.length())) {
9921cb0ef41Sopenharmony_ci        current_char = subject[current + load_offset];
9931cb0ef41Sopenharmony_ci        if (current_char > limit) {
9941cb0ef41Sopenharmony_ci          SET_PC_FROM_OFFSET(Load32Aligned(pc + 24));
9951cb0ef41Sopenharmony_ci          DISPATCH();
9961cb0ef41Sopenharmony_ci        }
9971cb0ef41Sopenharmony_ci        if (!CheckBitInTable(current_char, table)) {
9981cb0ef41Sopenharmony_ci          SET_PC_FROM_OFFSET(Load32Aligned(pc + 24));
9991cb0ef41Sopenharmony_ci          DISPATCH();
10001cb0ef41Sopenharmony_ci        }
10011cb0ef41Sopenharmony_ci        ADVANCE_CURRENT_POSITION(advance);
10021cb0ef41Sopenharmony_ci      }
10031cb0ef41Sopenharmony_ci      SET_PC_FROM_OFFSET(Load32Aligned(pc + 28));
10041cb0ef41Sopenharmony_ci      DISPATCH();
10051cb0ef41Sopenharmony_ci    }
10061cb0ef41Sopenharmony_ci    BYTECODE(SKIP_UNTIL_CHAR_OR_CHAR) {
10071cb0ef41Sopenharmony_ci      int32_t load_offset = LoadPacked24Signed(insn);
10081cb0ef41Sopenharmony_ci      int32_t advance = Load32Aligned(pc + 4);
10091cb0ef41Sopenharmony_ci      uint16_t c = Load16Aligned(pc + 8);
10101cb0ef41Sopenharmony_ci      uint16_t c2 = Load16Aligned(pc + 10);
10111cb0ef41Sopenharmony_ci      while (IndexIsInBounds(current + load_offset, subject.length())) {
10121cb0ef41Sopenharmony_ci        current_char = subject[current + load_offset];
10131cb0ef41Sopenharmony_ci        // The two if-statements below are split up intentionally, as combining
10141cb0ef41Sopenharmony_ci        // them seems to result in register allocation behaving quite
10151cb0ef41Sopenharmony_ci        // differently and slowing down the resulting code.
10161cb0ef41Sopenharmony_ci        if (c == current_char) {
10171cb0ef41Sopenharmony_ci          SET_PC_FROM_OFFSET(Load32Aligned(pc + 12));
10181cb0ef41Sopenharmony_ci          DISPATCH();
10191cb0ef41Sopenharmony_ci        }
10201cb0ef41Sopenharmony_ci        if (c2 == current_char) {
10211cb0ef41Sopenharmony_ci          SET_PC_FROM_OFFSET(Load32Aligned(pc + 12));
10221cb0ef41Sopenharmony_ci          DISPATCH();
10231cb0ef41Sopenharmony_ci        }
10241cb0ef41Sopenharmony_ci        ADVANCE_CURRENT_POSITION(advance);
10251cb0ef41Sopenharmony_ci      }
10261cb0ef41Sopenharmony_ci      SET_PC_FROM_OFFSET(Load32Aligned(pc + 16));
10271cb0ef41Sopenharmony_ci      DISPATCH();
10281cb0ef41Sopenharmony_ci    }
10291cb0ef41Sopenharmony_ci#if V8_USE_COMPUTED_GOTO
10301cb0ef41Sopenharmony_ci// Lint gets confused a lot if we just use !V8_USE_COMPUTED_GOTO or ifndef
10311cb0ef41Sopenharmony_ci// V8_USE_COMPUTED_GOTO here.
10321cb0ef41Sopenharmony_ci#else
10331cb0ef41Sopenharmony_ci      default:
10341cb0ef41Sopenharmony_ci        UNREACHABLE();
10351cb0ef41Sopenharmony_ci    }
10361cb0ef41Sopenharmony_ci  // Label we jump to in DISPATCH(). There must be no instructions between the
10371cb0ef41Sopenharmony_ci  // end of the switch, this label and the end of the loop.
10381cb0ef41Sopenharmony_ci  switch_dispatch_continuation : {}
10391cb0ef41Sopenharmony_ci#endif  // V8_USE_COMPUTED_GOTO
10401cb0ef41Sopenharmony_ci  }
10411cb0ef41Sopenharmony_ci}
10421cb0ef41Sopenharmony_ci
10431cb0ef41Sopenharmony_ci#undef BYTECODE
10441cb0ef41Sopenharmony_ci#undef ADVANCE_CURRENT_POSITION
10451cb0ef41Sopenharmony_ci#undef SET_CURRENT_POSITION
10461cb0ef41Sopenharmony_ci#undef DISPATCH
10471cb0ef41Sopenharmony_ci#undef DECODE
10481cb0ef41Sopenharmony_ci#undef SET_PC_FROM_OFFSET
10491cb0ef41Sopenharmony_ci#undef ADVANCE
10501cb0ef41Sopenharmony_ci#undef BC_LABEL
10511cb0ef41Sopenharmony_ci#undef V8_USE_COMPUTED_GOTO
10521cb0ef41Sopenharmony_ci
10531cb0ef41Sopenharmony_ci}  // namespace
10541cb0ef41Sopenharmony_ci
10551cb0ef41Sopenharmony_ci// static
10561cb0ef41Sopenharmony_ciIrregexpInterpreter::Result IrregexpInterpreter::Match(
10571cb0ef41Sopenharmony_ci    Isolate* isolate, JSRegExp regexp, String subject_string,
10581cb0ef41Sopenharmony_ci    int* output_registers, int output_register_count, int start_position,
10591cb0ef41Sopenharmony_ci    RegExp::CallOrigin call_origin) {
10601cb0ef41Sopenharmony_ci  if (FLAG_regexp_tier_up) regexp.TierUpTick();
10611cb0ef41Sopenharmony_ci
10621cb0ef41Sopenharmony_ci  bool is_one_byte = String::IsOneByteRepresentationUnderneath(subject_string);
10631cb0ef41Sopenharmony_ci  ByteArray code_array = ByteArray::cast(regexp.bytecode(is_one_byte));
10641cb0ef41Sopenharmony_ci  int total_register_count = regexp.max_register_count();
10651cb0ef41Sopenharmony_ci
10661cb0ef41Sopenharmony_ci  return MatchInternal(isolate, code_array, subject_string, output_registers,
10671cb0ef41Sopenharmony_ci                       output_register_count, total_register_count,
10681cb0ef41Sopenharmony_ci                       start_position, call_origin, regexp.backtrack_limit());
10691cb0ef41Sopenharmony_ci}
10701cb0ef41Sopenharmony_ci
10711cb0ef41Sopenharmony_ciIrregexpInterpreter::Result IrregexpInterpreter::MatchInternal(
10721cb0ef41Sopenharmony_ci    Isolate* isolate, ByteArray code_array, String subject_string,
10731cb0ef41Sopenharmony_ci    int* output_registers, int output_register_count, int total_register_count,
10741cb0ef41Sopenharmony_ci    int start_position, RegExp::CallOrigin call_origin,
10751cb0ef41Sopenharmony_ci    uint32_t backtrack_limit) {
10761cb0ef41Sopenharmony_ci  DCHECK(subject_string.IsFlat());
10771cb0ef41Sopenharmony_ci
10781cb0ef41Sopenharmony_ci  // TODO(chromium:1262676): Remove this CHECK once fixed.
10791cb0ef41Sopenharmony_ci  CHECK(code_array.IsByteArray());
10801cb0ef41Sopenharmony_ci
10811cb0ef41Sopenharmony_ci  // Note: Heap allocation *is* allowed in two situations if calling from
10821cb0ef41Sopenharmony_ci  // Runtime:
10831cb0ef41Sopenharmony_ci  // 1. When creating & throwing a stack overflow exception. The interpreter
10841cb0ef41Sopenharmony_ci  //    aborts afterwards, and thus possible-moved objects are never used.
10851cb0ef41Sopenharmony_ci  // 2. When handling interrupts. We manually relocate unhandlified references
10861cb0ef41Sopenharmony_ci  //    after interrupts have run.
10871cb0ef41Sopenharmony_ci  DisallowGarbageCollection no_gc;
10881cb0ef41Sopenharmony_ci
10891cb0ef41Sopenharmony_ci  base::uc16 previous_char = '\n';
10901cb0ef41Sopenharmony_ci  String::FlatContent subject_content = subject_string.GetFlatContent(no_gc);
10911cb0ef41Sopenharmony_ci  // Because interrupts can result in GC and string content relocation, the
10921cb0ef41Sopenharmony_ci  // checksum verification in FlatContent may fail even though this code is
10931cb0ef41Sopenharmony_ci  // safe. See (2) above.
10941cb0ef41Sopenharmony_ci  subject_content.UnsafeDisableChecksumVerification();
10951cb0ef41Sopenharmony_ci  if (subject_content.IsOneByte()) {
10961cb0ef41Sopenharmony_ci    base::Vector<const uint8_t> subject_vector =
10971cb0ef41Sopenharmony_ci        subject_content.ToOneByteVector();
10981cb0ef41Sopenharmony_ci    if (start_position != 0) previous_char = subject_vector[start_position - 1];
10991cb0ef41Sopenharmony_ci    return RawMatch(isolate, code_array, subject_string, subject_vector,
11001cb0ef41Sopenharmony_ci                    output_registers, output_register_count,
11011cb0ef41Sopenharmony_ci                    total_register_count, start_position, previous_char,
11021cb0ef41Sopenharmony_ci                    call_origin, backtrack_limit);
11031cb0ef41Sopenharmony_ci  } else {
11041cb0ef41Sopenharmony_ci    DCHECK(subject_content.IsTwoByte());
11051cb0ef41Sopenharmony_ci    base::Vector<const base::uc16> subject_vector =
11061cb0ef41Sopenharmony_ci        subject_content.ToUC16Vector();
11071cb0ef41Sopenharmony_ci    if (start_position != 0) previous_char = subject_vector[start_position - 1];
11081cb0ef41Sopenharmony_ci    return RawMatch(isolate, code_array, subject_string, subject_vector,
11091cb0ef41Sopenharmony_ci                    output_registers, output_register_count,
11101cb0ef41Sopenharmony_ci                    total_register_count, start_position, previous_char,
11111cb0ef41Sopenharmony_ci                    call_origin, backtrack_limit);
11121cb0ef41Sopenharmony_ci  }
11131cb0ef41Sopenharmony_ci}
11141cb0ef41Sopenharmony_ci
11151cb0ef41Sopenharmony_ci#ifndef COMPILING_IRREGEXP_FOR_EXTERNAL_EMBEDDER
11161cb0ef41Sopenharmony_ci
11171cb0ef41Sopenharmony_ci// This method is called through an external reference from RegExpExecInternal
11181cb0ef41Sopenharmony_ci// builtin.
11191cb0ef41Sopenharmony_ciIrregexpInterpreter::Result IrregexpInterpreter::MatchForCallFromJs(
11201cb0ef41Sopenharmony_ci    Address subject, int32_t start_position, Address, Address,
11211cb0ef41Sopenharmony_ci    int* output_registers, int32_t output_register_count,
11221cb0ef41Sopenharmony_ci    RegExp::CallOrigin call_origin, Isolate* isolate, Address regexp) {
11231cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(isolate);
11241cb0ef41Sopenharmony_ci  DCHECK_NOT_NULL(output_registers);
11251cb0ef41Sopenharmony_ci  DCHECK(call_origin == RegExp::CallOrigin::kFromJs);
11261cb0ef41Sopenharmony_ci
11271cb0ef41Sopenharmony_ci  DisallowGarbageCollection no_gc;
11281cb0ef41Sopenharmony_ci  DisallowJavascriptExecution no_js(isolate);
11291cb0ef41Sopenharmony_ci  DisallowHandleAllocation no_handles;
11301cb0ef41Sopenharmony_ci  DisallowHandleDereference no_deref;
11311cb0ef41Sopenharmony_ci
11321cb0ef41Sopenharmony_ci  String subject_string = String::cast(Object(subject));
11331cb0ef41Sopenharmony_ci  JSRegExp regexp_obj = JSRegExp::cast(Object(regexp));
11341cb0ef41Sopenharmony_ci
11351cb0ef41Sopenharmony_ci  if (regexp_obj.MarkedForTierUp()) {
11361cb0ef41Sopenharmony_ci    // Returning RETRY will re-enter through runtime, where actual recompilation
11371cb0ef41Sopenharmony_ci    // for tier-up takes place.
11381cb0ef41Sopenharmony_ci    return IrregexpInterpreter::RETRY;
11391cb0ef41Sopenharmony_ci  }
11401cb0ef41Sopenharmony_ci
11411cb0ef41Sopenharmony_ci  return Match(isolate, regexp_obj, subject_string, output_registers,
11421cb0ef41Sopenharmony_ci               output_register_count, start_position, call_origin);
11431cb0ef41Sopenharmony_ci}
11441cb0ef41Sopenharmony_ci
11451cb0ef41Sopenharmony_ci#endif  // !COMPILING_IRREGEXP_FOR_EXTERNAL_EMBEDDER
11461cb0ef41Sopenharmony_ci
11471cb0ef41Sopenharmony_ciIrregexpInterpreter::Result IrregexpInterpreter::MatchForCallFromRuntime(
11481cb0ef41Sopenharmony_ci    Isolate* isolate, Handle<JSRegExp> regexp, Handle<String> subject_string,
11491cb0ef41Sopenharmony_ci    int* output_registers, int output_register_count, int start_position) {
11501cb0ef41Sopenharmony_ci  return Match(isolate, *regexp, *subject_string, output_registers,
11511cb0ef41Sopenharmony_ci               output_register_count, start_position,
11521cb0ef41Sopenharmony_ci               RegExp::CallOrigin::kFromRuntime);
11531cb0ef41Sopenharmony_ci}
11541cb0ef41Sopenharmony_ci
11551cb0ef41Sopenharmony_ci}  // namespace internal
11561cb0ef41Sopenharmony_ci}  // namespace v8
1157