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