11cb0ef41Sopenharmony_ci// Copyright 2012 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#if V8_TARGET_ARCH_X64 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/regexp/x64/regexp-macro-assembler-x64.h" 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "src/codegen/code-desc.h" 101cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h" 111cb0ef41Sopenharmony_ci#include "src/heap/factory.h" 121cb0ef41Sopenharmony_ci#include "src/logging/log.h" 131cb0ef41Sopenharmony_ci#include "src/objects/code-inl.h" 141cb0ef41Sopenharmony_ci#include "src/regexp/regexp-macro-assembler.h" 151cb0ef41Sopenharmony_ci#include "src/regexp/regexp-stack.h" 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_cinamespace v8 { 181cb0ef41Sopenharmony_cinamespace internal { 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_ci/* 211cb0ef41Sopenharmony_ci * This assembler uses the following register assignment convention 221cb0ef41Sopenharmony_ci * - rdx : Currently loaded character(s) as Latin1 or UC16. Must be loaded 231cb0ef41Sopenharmony_ci * using LoadCurrentCharacter before using any of the dispatch methods. 241cb0ef41Sopenharmony_ci * Temporarily stores the index of capture start after a matching pass 251cb0ef41Sopenharmony_ci * for a global regexp. 261cb0ef41Sopenharmony_ci * - rdi : Current position in input, as negative offset from end of string. 271cb0ef41Sopenharmony_ci * Please notice that this is the byte offset, not the character 281cb0ef41Sopenharmony_ci * offset! Is always a 32-bit signed (negative) offset, but must be 291cb0ef41Sopenharmony_ci * maintained sign-extended to 64 bits, since it is used as index. 301cb0ef41Sopenharmony_ci * - rsi : End of input (points to byte after last character in input), 311cb0ef41Sopenharmony_ci * so that rsi+rdi points to the current character. 321cb0ef41Sopenharmony_ci * - rbp : Frame pointer. Used to access arguments, local variables and 331cb0ef41Sopenharmony_ci * RegExp registers. 341cb0ef41Sopenharmony_ci * - rsp : Points to tip of C stack. 351cb0ef41Sopenharmony_ci * - rcx : Points to tip of backtrack stack. The backtrack stack contains 361cb0ef41Sopenharmony_ci * only 32-bit values. Most are offsets from some base (e.g., character 371cb0ef41Sopenharmony_ci * positions from end of string or code location from Code pointer). 381cb0ef41Sopenharmony_ci * - r8 : Code object pointer. Used to convert between absolute and 391cb0ef41Sopenharmony_ci * code-object-relative addresses. 401cb0ef41Sopenharmony_ci * 411cb0ef41Sopenharmony_ci * The registers rax, rbx, r9 and r11 are free to use for computations. 421cb0ef41Sopenharmony_ci * If changed to use r12+, they should be saved as callee-save registers. 431cb0ef41Sopenharmony_ci * The macro assembler special register r13 (kRootRegister) isn't special 441cb0ef41Sopenharmony_ci * during execution of RegExp code (it doesn't hold the value assumed when 451cb0ef41Sopenharmony_ci * creating JS code), so Root related macro operations can be used. 461cb0ef41Sopenharmony_ci * 471cb0ef41Sopenharmony_ci * Each call to a C++ method should retain these registers. 481cb0ef41Sopenharmony_ci * 491cb0ef41Sopenharmony_ci * The stack will have the following content, in some order, indexable from the 501cb0ef41Sopenharmony_ci * frame pointer (see, e.g., kDirectCall): 511cb0ef41Sopenharmony_ci * - Address regexp (address of the JSRegExp object; unused in native 521cb0ef41Sopenharmony_ci * code, passed to match signature of interpreter) 531cb0ef41Sopenharmony_ci * - Isolate* isolate (address of the current isolate) 541cb0ef41Sopenharmony_ci * - direct_call (if 1, direct call from JavaScript code, if 0 call 551cb0ef41Sopenharmony_ci * through the runtime system) 561cb0ef41Sopenharmony_ci * - capture array size (may fit multiple sets of matches) 571cb0ef41Sopenharmony_ci * - int* capture_array (int[num_saved_registers_], for output). 581cb0ef41Sopenharmony_ci * - end of input (address of end of string) 591cb0ef41Sopenharmony_ci * - start of input (address of first character in string) 601cb0ef41Sopenharmony_ci * - start index (character index of start) 611cb0ef41Sopenharmony_ci * - String input_string (input string) 621cb0ef41Sopenharmony_ci * - return address 631cb0ef41Sopenharmony_ci * - backup of callee save registers (rbx, possibly rsi and rdi). 641cb0ef41Sopenharmony_ci * - success counter (only useful for global regexp to count matches) 651cb0ef41Sopenharmony_ci * - Offset of location before start of input (effectively character 661cb0ef41Sopenharmony_ci * string start - 1). Used to initialize capture registers to a 671cb0ef41Sopenharmony_ci * non-position. 681cb0ef41Sopenharmony_ci * - At start of string (if 1, we are starting at the start of the 691cb0ef41Sopenharmony_ci * string, otherwise 0) 701cb0ef41Sopenharmony_ci * - register 0 rbp[-n] (Only positions must be stored in the first 711cb0ef41Sopenharmony_ci * - register 1 rbp[-n-8] num_saved_registers_ registers) 721cb0ef41Sopenharmony_ci * - ... 731cb0ef41Sopenharmony_ci * 741cb0ef41Sopenharmony_ci * The first num_saved_registers_ registers are initialized to point to 751cb0ef41Sopenharmony_ci * "character -1" in the string (i.e., char_size() bytes before the first 761cb0ef41Sopenharmony_ci * character of the string). The remaining registers starts out uninitialized. 771cb0ef41Sopenharmony_ci * 781cb0ef41Sopenharmony_ci * The argument values must be provided by the calling code by calling the 791cb0ef41Sopenharmony_ci * code's entry address cast to a function pointer with the following signature: 801cb0ef41Sopenharmony_ci * int (*match)(String input_string, 811cb0ef41Sopenharmony_ci * int start_index, 821cb0ef41Sopenharmony_ci * Address start, 831cb0ef41Sopenharmony_ci * Address end, 841cb0ef41Sopenharmony_ci * int* capture_output_array, 851cb0ef41Sopenharmony_ci * int num_capture_registers, 861cb0ef41Sopenharmony_ci * bool direct_call = false, 871cb0ef41Sopenharmony_ci * Isolate* isolate, 881cb0ef41Sopenharmony_ci * Address regexp); 891cb0ef41Sopenharmony_ci */ 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci#define __ ACCESS_MASM((&masm_)) 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ciconst int RegExpMacroAssemblerX64::kRegExpCodeSize; 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ciRegExpMacroAssemblerX64::RegExpMacroAssemblerX64(Isolate* isolate, Zone* zone, 961cb0ef41Sopenharmony_ci Mode mode, 971cb0ef41Sopenharmony_ci int registers_to_save) 981cb0ef41Sopenharmony_ci : NativeRegExpMacroAssembler(isolate, zone), 991cb0ef41Sopenharmony_ci masm_(isolate, CodeObjectRequired::kYes, 1001cb0ef41Sopenharmony_ci NewAssemblerBuffer(kRegExpCodeSize)), 1011cb0ef41Sopenharmony_ci no_root_array_scope_(&masm_), 1021cb0ef41Sopenharmony_ci code_relative_fixup_positions_(zone), 1031cb0ef41Sopenharmony_ci mode_(mode), 1041cb0ef41Sopenharmony_ci num_registers_(registers_to_save), 1051cb0ef41Sopenharmony_ci num_saved_registers_(registers_to_save), 1061cb0ef41Sopenharmony_ci entry_label_(), 1071cb0ef41Sopenharmony_ci start_label_(), 1081cb0ef41Sopenharmony_ci success_label_(), 1091cb0ef41Sopenharmony_ci backtrack_label_(), 1101cb0ef41Sopenharmony_ci exit_label_() { 1111cb0ef41Sopenharmony_ci DCHECK_EQ(0, registers_to_save % 2); 1121cb0ef41Sopenharmony_ci __ jmp(&entry_label_); // We'll write the entry code when we know more. 1131cb0ef41Sopenharmony_ci __ bind(&start_label_); // And then continue from here. 1141cb0ef41Sopenharmony_ci} 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ciRegExpMacroAssemblerX64::~RegExpMacroAssemblerX64() { 1171cb0ef41Sopenharmony_ci // Unuse labels in case we throw away the assembler without calling GetCode. 1181cb0ef41Sopenharmony_ci entry_label_.Unuse(); 1191cb0ef41Sopenharmony_ci start_label_.Unuse(); 1201cb0ef41Sopenharmony_ci success_label_.Unuse(); 1211cb0ef41Sopenharmony_ci backtrack_label_.Unuse(); 1221cb0ef41Sopenharmony_ci exit_label_.Unuse(); 1231cb0ef41Sopenharmony_ci check_preempt_label_.Unuse(); 1241cb0ef41Sopenharmony_ci stack_overflow_label_.Unuse(); 1251cb0ef41Sopenharmony_ci fallback_label_.Unuse(); 1261cb0ef41Sopenharmony_ci} 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ciint RegExpMacroAssemblerX64::stack_limit_slack() { 1301cb0ef41Sopenharmony_ci return RegExpStack::kStackLimitSlack; 1311cb0ef41Sopenharmony_ci} 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::AdvanceCurrentPosition(int by) { 1351cb0ef41Sopenharmony_ci if (by != 0) { 1361cb0ef41Sopenharmony_ci __ addq(rdi, Immediate(by * char_size())); 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci} 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::AdvanceRegister(int reg, int by) { 1421cb0ef41Sopenharmony_ci DCHECK_LE(0, reg); 1431cb0ef41Sopenharmony_ci DCHECK_GT(num_registers_, reg); 1441cb0ef41Sopenharmony_ci if (by != 0) { 1451cb0ef41Sopenharmony_ci __ addq(register_location(reg), Immediate(by)); 1461cb0ef41Sopenharmony_ci } 1471cb0ef41Sopenharmony_ci} 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::Backtrack() { 1511cb0ef41Sopenharmony_ci CheckPreemption(); 1521cb0ef41Sopenharmony_ci if (has_backtrack_limit()) { 1531cb0ef41Sopenharmony_ci Label next; 1541cb0ef41Sopenharmony_ci __ incq(Operand(rbp, kBacktrackCount)); 1551cb0ef41Sopenharmony_ci __ cmpq(Operand(rbp, kBacktrackCount), Immediate(backtrack_limit())); 1561cb0ef41Sopenharmony_ci __ j(not_equal, &next); 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci // Backtrack limit exceeded. 1591cb0ef41Sopenharmony_ci if (can_fallback()) { 1601cb0ef41Sopenharmony_ci __ jmp(&fallback_label_); 1611cb0ef41Sopenharmony_ci } else { 1621cb0ef41Sopenharmony_ci // Can't fallback, so we treat it as a failed match. 1631cb0ef41Sopenharmony_ci Fail(); 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci __ bind(&next); 1671cb0ef41Sopenharmony_ci } 1681cb0ef41Sopenharmony_ci // Pop Code offset from backtrack stack, add Code and jump to location. 1691cb0ef41Sopenharmony_ci Pop(rbx); 1701cb0ef41Sopenharmony_ci __ addq(rbx, code_object_pointer()); 1711cb0ef41Sopenharmony_ci __ jmp(rbx); 1721cb0ef41Sopenharmony_ci} 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::Bind(Label* label) { 1761cb0ef41Sopenharmony_ci __ bind(label); 1771cb0ef41Sopenharmony_ci} 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckCharacter(uint32_t c, Label* on_equal) { 1811cb0ef41Sopenharmony_ci __ cmpl(current_character(), Immediate(c)); 1821cb0ef41Sopenharmony_ci BranchOrBacktrack(equal, on_equal); 1831cb0ef41Sopenharmony_ci} 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckCharacterGT(base::uc16 limit, 1861cb0ef41Sopenharmony_ci Label* on_greater) { 1871cb0ef41Sopenharmony_ci __ cmpl(current_character(), Immediate(limit)); 1881cb0ef41Sopenharmony_ci BranchOrBacktrack(greater, on_greater); 1891cb0ef41Sopenharmony_ci} 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckAtStart(int cp_offset, Label* on_at_start) { 1921cb0ef41Sopenharmony_ci __ leaq(rax, Operand(rdi, -char_size() + cp_offset * char_size())); 1931cb0ef41Sopenharmony_ci __ cmpq(rax, Operand(rbp, kStringStartMinusOne)); 1941cb0ef41Sopenharmony_ci BranchOrBacktrack(equal, on_at_start); 1951cb0ef41Sopenharmony_ci} 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckNotAtStart(int cp_offset, 1981cb0ef41Sopenharmony_ci Label* on_not_at_start) { 1991cb0ef41Sopenharmony_ci __ leaq(rax, Operand(rdi, -char_size() + cp_offset * char_size())); 2001cb0ef41Sopenharmony_ci __ cmpq(rax, Operand(rbp, kStringStartMinusOne)); 2011cb0ef41Sopenharmony_ci BranchOrBacktrack(not_equal, on_not_at_start); 2021cb0ef41Sopenharmony_ci} 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckCharacterLT(base::uc16 limit, 2051cb0ef41Sopenharmony_ci Label* on_less) { 2061cb0ef41Sopenharmony_ci __ cmpl(current_character(), Immediate(limit)); 2071cb0ef41Sopenharmony_ci BranchOrBacktrack(less, on_less); 2081cb0ef41Sopenharmony_ci} 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckGreedyLoop(Label* on_equal) { 2111cb0ef41Sopenharmony_ci Label fallthrough; 2121cb0ef41Sopenharmony_ci __ cmpl(rdi, Operand(backtrack_stackpointer(), 0)); 2131cb0ef41Sopenharmony_ci __ j(not_equal, &fallthrough); 2141cb0ef41Sopenharmony_ci Drop(); 2151cb0ef41Sopenharmony_ci BranchOrBacktrack(no_condition, on_equal); 2161cb0ef41Sopenharmony_ci __ bind(&fallthrough); 2171cb0ef41Sopenharmony_ci} 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci// Push (pop) caller-saved registers used by irregexp. 2201cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::PushCallerSavedRegisters() { 2211cb0ef41Sopenharmony_ci#ifndef V8_TARGET_OS_WIN 2221cb0ef41Sopenharmony_ci // Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI. 2231cb0ef41Sopenharmony_ci __ pushq(rsi); 2241cb0ef41Sopenharmony_ci __ pushq(rdi); 2251cb0ef41Sopenharmony_ci#endif 2261cb0ef41Sopenharmony_ci __ pushq(rcx); 2271cb0ef41Sopenharmony_ci} 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::PopCallerSavedRegisters() { 2301cb0ef41Sopenharmony_ci __ popq(rcx); 2311cb0ef41Sopenharmony_ci#ifndef V8_TARGET_OS_WIN 2321cb0ef41Sopenharmony_ci __ popq(rdi); 2331cb0ef41Sopenharmony_ci __ popq(rsi); 2341cb0ef41Sopenharmony_ci#endif 2351cb0ef41Sopenharmony_ci} 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase( 2381cb0ef41Sopenharmony_ci int start_reg, bool read_backward, bool unicode, Label* on_no_match) { 2391cb0ef41Sopenharmony_ci Label fallthrough; 2401cb0ef41Sopenharmony_ci ReadPositionFromRegister(rdx, start_reg); // Offset of start of capture 2411cb0ef41Sopenharmony_ci ReadPositionFromRegister(rbx, start_reg + 1); // Offset of end of capture 2421cb0ef41Sopenharmony_ci __ subq(rbx, rdx); // Length of capture. 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_ci // ----------------------- 2451cb0ef41Sopenharmony_ci // rdx = Start offset of capture. 2461cb0ef41Sopenharmony_ci // rbx = Length of capture 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci // At this point, the capture registers are either both set or both cleared. 2491cb0ef41Sopenharmony_ci // If the capture length is zero, then the capture is either empty or cleared. 2501cb0ef41Sopenharmony_ci // Fall through in both cases. 2511cb0ef41Sopenharmony_ci __ j(equal, &fallthrough); 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci // ----------------------- 2541cb0ef41Sopenharmony_ci // rdx - Start of capture 2551cb0ef41Sopenharmony_ci // rbx - length of capture 2561cb0ef41Sopenharmony_ci // Check that there are sufficient characters left in the input. 2571cb0ef41Sopenharmony_ci if (read_backward) { 2581cb0ef41Sopenharmony_ci __ movl(rax, Operand(rbp, kStringStartMinusOne)); 2591cb0ef41Sopenharmony_ci __ addl(rax, rbx); 2601cb0ef41Sopenharmony_ci __ cmpl(rdi, rax); 2611cb0ef41Sopenharmony_ci BranchOrBacktrack(less_equal, on_no_match); 2621cb0ef41Sopenharmony_ci } else { 2631cb0ef41Sopenharmony_ci __ movl(rax, rdi); 2641cb0ef41Sopenharmony_ci __ addl(rax, rbx); 2651cb0ef41Sopenharmony_ci BranchOrBacktrack(greater, on_no_match); 2661cb0ef41Sopenharmony_ci } 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci if (mode_ == LATIN1) { 2691cb0ef41Sopenharmony_ci Label loop_increment; 2701cb0ef41Sopenharmony_ci if (on_no_match == nullptr) { 2711cb0ef41Sopenharmony_ci on_no_match = &backtrack_label_; 2721cb0ef41Sopenharmony_ci } 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ci __ leaq(r9, Operand(rsi, rdx, times_1, 0)); 2751cb0ef41Sopenharmony_ci __ leaq(r11, Operand(rsi, rdi, times_1, 0)); 2761cb0ef41Sopenharmony_ci if (read_backward) { 2771cb0ef41Sopenharmony_ci __ subq(r11, rbx); // Offset by length when matching backwards. 2781cb0ef41Sopenharmony_ci } 2791cb0ef41Sopenharmony_ci __ addq(rbx, r9); // End of capture 2801cb0ef41Sopenharmony_ci // --------------------- 2811cb0ef41Sopenharmony_ci // r11 - current input character address 2821cb0ef41Sopenharmony_ci // r9 - current capture character address 2831cb0ef41Sopenharmony_ci // rbx - end of capture 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci Label loop; 2861cb0ef41Sopenharmony_ci __ bind(&loop); 2871cb0ef41Sopenharmony_ci __ movzxbl(rdx, Operand(r9, 0)); 2881cb0ef41Sopenharmony_ci __ movzxbl(rax, Operand(r11, 0)); 2891cb0ef41Sopenharmony_ci // al - input character 2901cb0ef41Sopenharmony_ci // dl - capture character 2911cb0ef41Sopenharmony_ci __ cmpb(rax, rdx); 2921cb0ef41Sopenharmony_ci __ j(equal, &loop_increment); 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_ci // Mismatch, try case-insensitive match (converting letters to lower-case). 2951cb0ef41Sopenharmony_ci // I.e., if or-ing with 0x20 makes values equal and in range 'a'-'z', it's 2961cb0ef41Sopenharmony_ci // a match. 2971cb0ef41Sopenharmony_ci __ orq(rax, Immediate(0x20)); // Convert match character to lower-case. 2981cb0ef41Sopenharmony_ci __ orq(rdx, Immediate(0x20)); // Convert capture character to lower-case. 2991cb0ef41Sopenharmony_ci __ cmpb(rax, rdx); 3001cb0ef41Sopenharmony_ci __ j(not_equal, on_no_match); // Definitely not equal. 3011cb0ef41Sopenharmony_ci __ subb(rax, Immediate('a')); 3021cb0ef41Sopenharmony_ci __ cmpb(rax, Immediate('z' - 'a')); 3031cb0ef41Sopenharmony_ci __ j(below_equal, &loop_increment); // In range 'a'-'z'. 3041cb0ef41Sopenharmony_ci // Latin-1: Check for values in range [224,254] but not 247. 3051cb0ef41Sopenharmony_ci __ subb(rax, Immediate(224 - 'a')); 3061cb0ef41Sopenharmony_ci __ cmpb(rax, Immediate(254 - 224)); 3071cb0ef41Sopenharmony_ci __ j(above, on_no_match); // Weren't Latin-1 letters. 3081cb0ef41Sopenharmony_ci __ cmpb(rax, Immediate(247 - 224)); // Check for 247. 3091cb0ef41Sopenharmony_ci __ j(equal, on_no_match); 3101cb0ef41Sopenharmony_ci __ bind(&loop_increment); 3111cb0ef41Sopenharmony_ci // Increment pointers into match and capture strings. 3121cb0ef41Sopenharmony_ci __ addq(r11, Immediate(1)); 3131cb0ef41Sopenharmony_ci __ addq(r9, Immediate(1)); 3141cb0ef41Sopenharmony_ci // Compare to end of capture, and loop if not done. 3151cb0ef41Sopenharmony_ci __ cmpq(r9, rbx); 3161cb0ef41Sopenharmony_ci __ j(below, &loop); 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci // Compute new value of character position after the matched part. 3191cb0ef41Sopenharmony_ci __ movq(rdi, r11); 3201cb0ef41Sopenharmony_ci __ subq(rdi, rsi); 3211cb0ef41Sopenharmony_ci if (read_backward) { 3221cb0ef41Sopenharmony_ci // Subtract match length if we matched backward. 3231cb0ef41Sopenharmony_ci __ addq(rdi, register_location(start_reg)); 3241cb0ef41Sopenharmony_ci __ subq(rdi, register_location(start_reg + 1)); 3251cb0ef41Sopenharmony_ci } 3261cb0ef41Sopenharmony_ci } else { 3271cb0ef41Sopenharmony_ci DCHECK(mode_ == UC16); 3281cb0ef41Sopenharmony_ci PushCallerSavedRegisters(); 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_ci static const int num_arguments = 4; 3311cb0ef41Sopenharmony_ci __ PrepareCallCFunction(num_arguments); 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ci // Put arguments into parameter registers. Parameters are 3341cb0ef41Sopenharmony_ci // Address byte_offset1 - Address captured substring's start. 3351cb0ef41Sopenharmony_ci // Address byte_offset2 - Address of current character position. 3361cb0ef41Sopenharmony_ci // size_t byte_length - length of capture in bytes(!) 3371cb0ef41Sopenharmony_ci // Isolate* isolate. 3381cb0ef41Sopenharmony_ci#ifdef V8_TARGET_OS_WIN 3391cb0ef41Sopenharmony_ci DCHECK(rcx == arg_reg_1); 3401cb0ef41Sopenharmony_ci DCHECK(rdx == arg_reg_2); 3411cb0ef41Sopenharmony_ci // Compute and set byte_offset1 (start of capture). 3421cb0ef41Sopenharmony_ci __ leaq(rcx, Operand(rsi, rdx, times_1, 0)); 3431cb0ef41Sopenharmony_ci // Set byte_offset2. 3441cb0ef41Sopenharmony_ci __ leaq(rdx, Operand(rsi, rdi, times_1, 0)); 3451cb0ef41Sopenharmony_ci if (read_backward) { 3461cb0ef41Sopenharmony_ci __ subq(rdx, rbx); 3471cb0ef41Sopenharmony_ci } 3481cb0ef41Sopenharmony_ci#else // AMD64 calling convention 3491cb0ef41Sopenharmony_ci DCHECK(rdi == arg_reg_1); 3501cb0ef41Sopenharmony_ci DCHECK(rsi == arg_reg_2); 3511cb0ef41Sopenharmony_ci // Compute byte_offset2 (current position = rsi+rdi). 3521cb0ef41Sopenharmony_ci __ leaq(rax, Operand(rsi, rdi, times_1, 0)); 3531cb0ef41Sopenharmony_ci // Compute and set byte_offset1 (start of capture). 3541cb0ef41Sopenharmony_ci __ leaq(rdi, Operand(rsi, rdx, times_1, 0)); 3551cb0ef41Sopenharmony_ci // Set byte_offset2. 3561cb0ef41Sopenharmony_ci __ movq(rsi, rax); 3571cb0ef41Sopenharmony_ci if (read_backward) { 3581cb0ef41Sopenharmony_ci __ subq(rsi, rbx); 3591cb0ef41Sopenharmony_ci } 3601cb0ef41Sopenharmony_ci#endif // V8_TARGET_OS_WIN 3611cb0ef41Sopenharmony_ci 3621cb0ef41Sopenharmony_ci // Set byte_length. 3631cb0ef41Sopenharmony_ci __ movq(arg_reg_3, rbx); 3641cb0ef41Sopenharmony_ci // Isolate. 3651cb0ef41Sopenharmony_ci __ LoadAddress(arg_reg_4, ExternalReference::isolate_address(isolate())); 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ci { 3681cb0ef41Sopenharmony_ci AllowExternalCallThatCantCauseGC scope(&masm_); 3691cb0ef41Sopenharmony_ci ExternalReference compare = 3701cb0ef41Sopenharmony_ci unicode 3711cb0ef41Sopenharmony_ci ? ExternalReference::re_case_insensitive_compare_unicode() 3721cb0ef41Sopenharmony_ci : ExternalReference::re_case_insensitive_compare_non_unicode(); 3731cb0ef41Sopenharmony_ci __ CallCFunction(compare, num_arguments); 3741cb0ef41Sopenharmony_ci } 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci // Restore original values before reacting on result value. 3771cb0ef41Sopenharmony_ci __ Move(code_object_pointer(), masm_.CodeObject()); 3781cb0ef41Sopenharmony_ci PopCallerSavedRegisters(); 3791cb0ef41Sopenharmony_ci 3801cb0ef41Sopenharmony_ci // Check if function returned non-zero for success or zero for failure. 3811cb0ef41Sopenharmony_ci __ testq(rax, rax); 3821cb0ef41Sopenharmony_ci BranchOrBacktrack(zero, on_no_match); 3831cb0ef41Sopenharmony_ci // On success, advance position by length of capture. 3841cb0ef41Sopenharmony_ci // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs). 3851cb0ef41Sopenharmony_ci if (read_backward) { 3861cb0ef41Sopenharmony_ci __ subq(rdi, rbx); 3871cb0ef41Sopenharmony_ci } else { 3881cb0ef41Sopenharmony_ci __ addq(rdi, rbx); 3891cb0ef41Sopenharmony_ci } 3901cb0ef41Sopenharmony_ci } 3911cb0ef41Sopenharmony_ci __ bind(&fallthrough); 3921cb0ef41Sopenharmony_ci} 3931cb0ef41Sopenharmony_ci 3941cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckNotBackReference(int start_reg, 3951cb0ef41Sopenharmony_ci bool read_backward, 3961cb0ef41Sopenharmony_ci Label* on_no_match) { 3971cb0ef41Sopenharmony_ci Label fallthrough; 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ci // Find length of back-referenced capture. 4001cb0ef41Sopenharmony_ci ReadPositionFromRegister(rdx, start_reg); // Offset of start of capture 4011cb0ef41Sopenharmony_ci ReadPositionFromRegister(rax, start_reg + 1); // Offset of end of capture 4021cb0ef41Sopenharmony_ci __ subq(rax, rdx); // Length to check. 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_ci // At this point, the capture registers are either both set or both cleared. 4051cb0ef41Sopenharmony_ci // If the capture length is zero, then the capture is either empty or cleared. 4061cb0ef41Sopenharmony_ci // Fall through in both cases. 4071cb0ef41Sopenharmony_ci __ j(equal, &fallthrough); 4081cb0ef41Sopenharmony_ci 4091cb0ef41Sopenharmony_ci // ----------------------- 4101cb0ef41Sopenharmony_ci // rdx - Start of capture 4111cb0ef41Sopenharmony_ci // rax - length of capture 4121cb0ef41Sopenharmony_ci // Check that there are sufficient characters left in the input. 4131cb0ef41Sopenharmony_ci if (read_backward) { 4141cb0ef41Sopenharmony_ci __ movl(rbx, Operand(rbp, kStringStartMinusOne)); 4151cb0ef41Sopenharmony_ci __ addl(rbx, rax); 4161cb0ef41Sopenharmony_ci __ cmpl(rdi, rbx); 4171cb0ef41Sopenharmony_ci BranchOrBacktrack(less_equal, on_no_match); 4181cb0ef41Sopenharmony_ci } else { 4191cb0ef41Sopenharmony_ci __ movl(rbx, rdi); 4201cb0ef41Sopenharmony_ci __ addl(rbx, rax); 4211cb0ef41Sopenharmony_ci BranchOrBacktrack(greater, on_no_match); 4221cb0ef41Sopenharmony_ci } 4231cb0ef41Sopenharmony_ci 4241cb0ef41Sopenharmony_ci // Compute pointers to match string and capture string 4251cb0ef41Sopenharmony_ci __ leaq(rbx, Operand(rsi, rdi, times_1, 0)); // Start of match. 4261cb0ef41Sopenharmony_ci if (read_backward) { 4271cb0ef41Sopenharmony_ci __ subq(rbx, rax); // Offset by length when matching backwards. 4281cb0ef41Sopenharmony_ci } 4291cb0ef41Sopenharmony_ci __ addq(rdx, rsi); // Start of capture. 4301cb0ef41Sopenharmony_ci __ leaq(r9, Operand(rdx, rax, times_1, 0)); // End of capture 4311cb0ef41Sopenharmony_ci 4321cb0ef41Sopenharmony_ci // ----------------------- 4331cb0ef41Sopenharmony_ci // rbx - current capture character address. 4341cb0ef41Sopenharmony_ci // rbx - current input character address . 4351cb0ef41Sopenharmony_ci // r9 - end of input to match (capture length after rbx). 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_ci Label loop; 4381cb0ef41Sopenharmony_ci __ bind(&loop); 4391cb0ef41Sopenharmony_ci if (mode_ == LATIN1) { 4401cb0ef41Sopenharmony_ci __ movzxbl(rax, Operand(rdx, 0)); 4411cb0ef41Sopenharmony_ci __ cmpb(rax, Operand(rbx, 0)); 4421cb0ef41Sopenharmony_ci } else { 4431cb0ef41Sopenharmony_ci DCHECK(mode_ == UC16); 4441cb0ef41Sopenharmony_ci __ movzxwl(rax, Operand(rdx, 0)); 4451cb0ef41Sopenharmony_ci __ cmpw(rax, Operand(rbx, 0)); 4461cb0ef41Sopenharmony_ci } 4471cb0ef41Sopenharmony_ci BranchOrBacktrack(not_equal, on_no_match); 4481cb0ef41Sopenharmony_ci // Increment pointers into capture and match string. 4491cb0ef41Sopenharmony_ci __ addq(rbx, Immediate(char_size())); 4501cb0ef41Sopenharmony_ci __ addq(rdx, Immediate(char_size())); 4511cb0ef41Sopenharmony_ci // Check if we have reached end of match area. 4521cb0ef41Sopenharmony_ci __ cmpq(rdx, r9); 4531cb0ef41Sopenharmony_ci __ j(below, &loop); 4541cb0ef41Sopenharmony_ci 4551cb0ef41Sopenharmony_ci // Success. 4561cb0ef41Sopenharmony_ci // Set current character position to position after match. 4571cb0ef41Sopenharmony_ci __ movq(rdi, rbx); 4581cb0ef41Sopenharmony_ci __ subq(rdi, rsi); 4591cb0ef41Sopenharmony_ci if (read_backward) { 4601cb0ef41Sopenharmony_ci // Subtract match length if we matched backward. 4611cb0ef41Sopenharmony_ci __ addq(rdi, register_location(start_reg)); 4621cb0ef41Sopenharmony_ci __ subq(rdi, register_location(start_reg + 1)); 4631cb0ef41Sopenharmony_ci } 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci __ bind(&fallthrough); 4661cb0ef41Sopenharmony_ci} 4671cb0ef41Sopenharmony_ci 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckNotCharacter(uint32_t c, 4701cb0ef41Sopenharmony_ci Label* on_not_equal) { 4711cb0ef41Sopenharmony_ci __ cmpl(current_character(), Immediate(c)); 4721cb0ef41Sopenharmony_ci BranchOrBacktrack(not_equal, on_not_equal); 4731cb0ef41Sopenharmony_ci} 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_ci 4761cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckCharacterAfterAnd(uint32_t c, 4771cb0ef41Sopenharmony_ci uint32_t mask, 4781cb0ef41Sopenharmony_ci Label* on_equal) { 4791cb0ef41Sopenharmony_ci if (c == 0) { 4801cb0ef41Sopenharmony_ci __ testl(current_character(), Immediate(mask)); 4811cb0ef41Sopenharmony_ci } else { 4821cb0ef41Sopenharmony_ci __ Move(rax, mask); 4831cb0ef41Sopenharmony_ci __ andq(rax, current_character()); 4841cb0ef41Sopenharmony_ci __ cmpl(rax, Immediate(c)); 4851cb0ef41Sopenharmony_ci } 4861cb0ef41Sopenharmony_ci BranchOrBacktrack(equal, on_equal); 4871cb0ef41Sopenharmony_ci} 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_ci 4901cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckNotCharacterAfterAnd(uint32_t c, 4911cb0ef41Sopenharmony_ci uint32_t mask, 4921cb0ef41Sopenharmony_ci Label* on_not_equal) { 4931cb0ef41Sopenharmony_ci if (c == 0) { 4941cb0ef41Sopenharmony_ci __ testl(current_character(), Immediate(mask)); 4951cb0ef41Sopenharmony_ci } else { 4961cb0ef41Sopenharmony_ci __ Move(rax, mask); 4971cb0ef41Sopenharmony_ci __ andq(rax, current_character()); 4981cb0ef41Sopenharmony_ci __ cmpl(rax, Immediate(c)); 4991cb0ef41Sopenharmony_ci } 5001cb0ef41Sopenharmony_ci BranchOrBacktrack(not_equal, on_not_equal); 5011cb0ef41Sopenharmony_ci} 5021cb0ef41Sopenharmony_ci 5031cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckNotCharacterAfterMinusAnd( 5041cb0ef41Sopenharmony_ci base::uc16 c, base::uc16 minus, base::uc16 mask, Label* on_not_equal) { 5051cb0ef41Sopenharmony_ci DCHECK_GT(String::kMaxUtf16CodeUnit, minus); 5061cb0ef41Sopenharmony_ci __ leal(rax, Operand(current_character(), -minus)); 5071cb0ef41Sopenharmony_ci __ andl(rax, Immediate(mask)); 5081cb0ef41Sopenharmony_ci __ cmpl(rax, Immediate(c)); 5091cb0ef41Sopenharmony_ci BranchOrBacktrack(not_equal, on_not_equal); 5101cb0ef41Sopenharmony_ci} 5111cb0ef41Sopenharmony_ci 5121cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckCharacterInRange(base::uc16 from, 5131cb0ef41Sopenharmony_ci base::uc16 to, 5141cb0ef41Sopenharmony_ci Label* on_in_range) { 5151cb0ef41Sopenharmony_ci __ leal(rax, Operand(current_character(), -from)); 5161cb0ef41Sopenharmony_ci __ cmpl(rax, Immediate(to - from)); 5171cb0ef41Sopenharmony_ci BranchOrBacktrack(below_equal, on_in_range); 5181cb0ef41Sopenharmony_ci} 5191cb0ef41Sopenharmony_ci 5201cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckCharacterNotInRange(base::uc16 from, 5211cb0ef41Sopenharmony_ci base::uc16 to, 5221cb0ef41Sopenharmony_ci Label* on_not_in_range) { 5231cb0ef41Sopenharmony_ci __ leal(rax, Operand(current_character(), -from)); 5241cb0ef41Sopenharmony_ci __ cmpl(rax, Immediate(to - from)); 5251cb0ef41Sopenharmony_ci BranchOrBacktrack(above, on_not_in_range); 5261cb0ef41Sopenharmony_ci} 5271cb0ef41Sopenharmony_ci 5281cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CallIsCharacterInRangeArray( 5291cb0ef41Sopenharmony_ci const ZoneList<CharacterRange>* ranges) { 5301cb0ef41Sopenharmony_ci PushCallerSavedRegisters(); 5311cb0ef41Sopenharmony_ci 5321cb0ef41Sopenharmony_ci static const int kNumArguments = 3; 5331cb0ef41Sopenharmony_ci __ PrepareCallCFunction(kNumArguments); 5341cb0ef41Sopenharmony_ci 5351cb0ef41Sopenharmony_ci __ Move(arg_reg_1, current_character()); 5361cb0ef41Sopenharmony_ci __ Move(arg_reg_2, GetOrAddRangeArray(ranges)); 5371cb0ef41Sopenharmony_ci __ LoadAddress(arg_reg_3, ExternalReference::isolate_address(isolate())); 5381cb0ef41Sopenharmony_ci 5391cb0ef41Sopenharmony_ci { 5401cb0ef41Sopenharmony_ci // We have a frame (set up in GetCode), but the assembler doesn't know. 5411cb0ef41Sopenharmony_ci FrameScope scope(&masm_, StackFrame::MANUAL); 5421cb0ef41Sopenharmony_ci __ CallCFunction(ExternalReference::re_is_character_in_range_array(), 5431cb0ef41Sopenharmony_ci kNumArguments); 5441cb0ef41Sopenharmony_ci } 5451cb0ef41Sopenharmony_ci 5461cb0ef41Sopenharmony_ci PopCallerSavedRegisters(); 5471cb0ef41Sopenharmony_ci __ Move(code_object_pointer(), masm_.CodeObject()); 5481cb0ef41Sopenharmony_ci} 5491cb0ef41Sopenharmony_ci 5501cb0ef41Sopenharmony_cibool RegExpMacroAssemblerX64::CheckCharacterInRangeArray( 5511cb0ef41Sopenharmony_ci const ZoneList<CharacterRange>* ranges, Label* on_in_range) { 5521cb0ef41Sopenharmony_ci CallIsCharacterInRangeArray(ranges); 5531cb0ef41Sopenharmony_ci __ testq(rax, rax); 5541cb0ef41Sopenharmony_ci BranchOrBacktrack(not_zero, on_in_range); 5551cb0ef41Sopenharmony_ci return true; 5561cb0ef41Sopenharmony_ci} 5571cb0ef41Sopenharmony_ci 5581cb0ef41Sopenharmony_cibool RegExpMacroAssemblerX64::CheckCharacterNotInRangeArray( 5591cb0ef41Sopenharmony_ci const ZoneList<CharacterRange>* ranges, Label* on_not_in_range) { 5601cb0ef41Sopenharmony_ci CallIsCharacterInRangeArray(ranges); 5611cb0ef41Sopenharmony_ci __ testq(rax, rax); 5621cb0ef41Sopenharmony_ci BranchOrBacktrack(zero, on_not_in_range); 5631cb0ef41Sopenharmony_ci return true; 5641cb0ef41Sopenharmony_ci} 5651cb0ef41Sopenharmony_ci 5661cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckBitInTable( 5671cb0ef41Sopenharmony_ci Handle<ByteArray> table, 5681cb0ef41Sopenharmony_ci Label* on_bit_set) { 5691cb0ef41Sopenharmony_ci __ Move(rax, table); 5701cb0ef41Sopenharmony_ci Register index = current_character(); 5711cb0ef41Sopenharmony_ci if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) { 5721cb0ef41Sopenharmony_ci __ movq(rbx, current_character()); 5731cb0ef41Sopenharmony_ci __ andq(rbx, Immediate(kTableMask)); 5741cb0ef41Sopenharmony_ci index = rbx; 5751cb0ef41Sopenharmony_ci } 5761cb0ef41Sopenharmony_ci __ cmpb(FieldOperand(rax, index, times_1, ByteArray::kHeaderSize), 5771cb0ef41Sopenharmony_ci Immediate(0)); 5781cb0ef41Sopenharmony_ci BranchOrBacktrack(not_equal, on_bit_set); 5791cb0ef41Sopenharmony_ci} 5801cb0ef41Sopenharmony_ci 5811cb0ef41Sopenharmony_cibool RegExpMacroAssemblerX64::CheckSpecialCharacterClass( 5821cb0ef41Sopenharmony_ci StandardCharacterSet type, Label* on_no_match) { 5831cb0ef41Sopenharmony_ci // Range checks (c in min..max) are generally implemented by an unsigned 5841cb0ef41Sopenharmony_ci // (c - min) <= (max - min) check, using the sequence: 5851cb0ef41Sopenharmony_ci // leal(rax, Operand(current_character(), -min)) or sub(rax, Immediate(min)) 5861cb0ef41Sopenharmony_ci // cmpl(rax, Immediate(max - min)) 5871cb0ef41Sopenharmony_ci // TODO(jgruber): No custom implementation (yet): s(UC16), S(UC16). 5881cb0ef41Sopenharmony_ci switch (type) { 5891cb0ef41Sopenharmony_ci case StandardCharacterSet::kWhitespace: 5901cb0ef41Sopenharmony_ci // Match space-characters. 5911cb0ef41Sopenharmony_ci if (mode_ == LATIN1) { 5921cb0ef41Sopenharmony_ci // One byte space characters are '\t'..'\r', ' ' and \u00a0. 5931cb0ef41Sopenharmony_ci Label success; 5941cb0ef41Sopenharmony_ci __ cmpl(current_character(), Immediate(' ')); 5951cb0ef41Sopenharmony_ci __ j(equal, &success, Label::kNear); 5961cb0ef41Sopenharmony_ci // Check range 0x09..0x0D. 5971cb0ef41Sopenharmony_ci __ leal(rax, Operand(current_character(), -'\t')); 5981cb0ef41Sopenharmony_ci __ cmpl(rax, Immediate('\r' - '\t')); 5991cb0ef41Sopenharmony_ci __ j(below_equal, &success, Label::kNear); 6001cb0ef41Sopenharmony_ci // \u00a0 (NBSP). 6011cb0ef41Sopenharmony_ci __ cmpl(rax, Immediate(0x00A0 - '\t')); 6021cb0ef41Sopenharmony_ci BranchOrBacktrack(not_equal, on_no_match); 6031cb0ef41Sopenharmony_ci __ bind(&success); 6041cb0ef41Sopenharmony_ci return true; 6051cb0ef41Sopenharmony_ci } 6061cb0ef41Sopenharmony_ci return false; 6071cb0ef41Sopenharmony_ci case StandardCharacterSet::kNotWhitespace: 6081cb0ef41Sopenharmony_ci // The emitted code for generic character classes is good enough. 6091cb0ef41Sopenharmony_ci return false; 6101cb0ef41Sopenharmony_ci case StandardCharacterSet::kDigit: 6111cb0ef41Sopenharmony_ci // Match ASCII digits ('0'..'9'). 6121cb0ef41Sopenharmony_ci __ leal(rax, Operand(current_character(), -'0')); 6131cb0ef41Sopenharmony_ci __ cmpl(rax, Immediate('9' - '0')); 6141cb0ef41Sopenharmony_ci BranchOrBacktrack(above, on_no_match); 6151cb0ef41Sopenharmony_ci return true; 6161cb0ef41Sopenharmony_ci case StandardCharacterSet::kNotDigit: 6171cb0ef41Sopenharmony_ci // Match non ASCII-digits. 6181cb0ef41Sopenharmony_ci __ leal(rax, Operand(current_character(), -'0')); 6191cb0ef41Sopenharmony_ci __ cmpl(rax, Immediate('9' - '0')); 6201cb0ef41Sopenharmony_ci BranchOrBacktrack(below_equal, on_no_match); 6211cb0ef41Sopenharmony_ci return true; 6221cb0ef41Sopenharmony_ci case StandardCharacterSet::kNotLineTerminator: { 6231cb0ef41Sopenharmony_ci // Match non-newlines (not 0x0A('\n'), 0x0D('\r'), 0x2028 and 0x2029). 6241cb0ef41Sopenharmony_ci __ movl(rax, current_character()); 6251cb0ef41Sopenharmony_ci __ xorl(rax, Immediate(0x01)); 6261cb0ef41Sopenharmony_ci // See if current character is '\n'^1 or '\r'^1, i.e., 0x0B or 0x0C. 6271cb0ef41Sopenharmony_ci __ subl(rax, Immediate(0x0B)); 6281cb0ef41Sopenharmony_ci __ cmpl(rax, Immediate(0x0C - 0x0B)); 6291cb0ef41Sopenharmony_ci BranchOrBacktrack(below_equal, on_no_match); 6301cb0ef41Sopenharmony_ci if (mode_ == UC16) { 6311cb0ef41Sopenharmony_ci // Compare original value to 0x2028 and 0x2029, using the already 6321cb0ef41Sopenharmony_ci // computed (current_char ^ 0x01 - 0x0B). I.e., check for 6331cb0ef41Sopenharmony_ci // 0x201D (0x2028 - 0x0B) or 0x201E. 6341cb0ef41Sopenharmony_ci __ subl(rax, Immediate(0x2028 - 0x0B)); 6351cb0ef41Sopenharmony_ci __ cmpl(rax, Immediate(0x2029 - 0x2028)); 6361cb0ef41Sopenharmony_ci BranchOrBacktrack(below_equal, on_no_match); 6371cb0ef41Sopenharmony_ci } 6381cb0ef41Sopenharmony_ci return true; 6391cb0ef41Sopenharmony_ci } 6401cb0ef41Sopenharmony_ci case StandardCharacterSet::kLineTerminator: { 6411cb0ef41Sopenharmony_ci // Match newlines (0x0A('\n'), 0x0D('\r'), 0x2028 and 0x2029). 6421cb0ef41Sopenharmony_ci __ movl(rax, current_character()); 6431cb0ef41Sopenharmony_ci __ xorl(rax, Immediate(0x01)); 6441cb0ef41Sopenharmony_ci // See if current character is '\n'^1 or '\r'^1, i.e., 0x0B or 0x0C. 6451cb0ef41Sopenharmony_ci __ subl(rax, Immediate(0x0B)); 6461cb0ef41Sopenharmony_ci __ cmpl(rax, Immediate(0x0C - 0x0B)); 6471cb0ef41Sopenharmony_ci if (mode_ == LATIN1) { 6481cb0ef41Sopenharmony_ci BranchOrBacktrack(above, on_no_match); 6491cb0ef41Sopenharmony_ci } else { 6501cb0ef41Sopenharmony_ci Label done; 6511cb0ef41Sopenharmony_ci BranchOrBacktrack(below_equal, &done); 6521cb0ef41Sopenharmony_ci // Compare original value to 0x2028 and 0x2029, using the already 6531cb0ef41Sopenharmony_ci // computed (current_char ^ 0x01 - 0x0B). I.e., check for 6541cb0ef41Sopenharmony_ci // 0x201D (0x2028 - 0x0B) or 0x201E. 6551cb0ef41Sopenharmony_ci __ subl(rax, Immediate(0x2028 - 0x0B)); 6561cb0ef41Sopenharmony_ci __ cmpl(rax, Immediate(0x2029 - 0x2028)); 6571cb0ef41Sopenharmony_ci BranchOrBacktrack(above, on_no_match); 6581cb0ef41Sopenharmony_ci __ bind(&done); 6591cb0ef41Sopenharmony_ci } 6601cb0ef41Sopenharmony_ci return true; 6611cb0ef41Sopenharmony_ci } 6621cb0ef41Sopenharmony_ci case StandardCharacterSet::kWord: { 6631cb0ef41Sopenharmony_ci if (mode_ != LATIN1) { 6641cb0ef41Sopenharmony_ci // Table is 256 entries, so all Latin1 characters can be tested. 6651cb0ef41Sopenharmony_ci __ cmpl(current_character(), Immediate('z')); 6661cb0ef41Sopenharmony_ci BranchOrBacktrack(above, on_no_match); 6671cb0ef41Sopenharmony_ci } 6681cb0ef41Sopenharmony_ci __ Move(rbx, ExternalReference::re_word_character_map()); 6691cb0ef41Sopenharmony_ci DCHECK_EQ(0, 6701cb0ef41Sopenharmony_ci word_character_map[0]); // Character '\0' is not a word char. 6711cb0ef41Sopenharmony_ci __ testb(Operand(rbx, current_character(), times_1, 0), 6721cb0ef41Sopenharmony_ci current_character()); 6731cb0ef41Sopenharmony_ci BranchOrBacktrack(zero, on_no_match); 6741cb0ef41Sopenharmony_ci return true; 6751cb0ef41Sopenharmony_ci } 6761cb0ef41Sopenharmony_ci case StandardCharacterSet::kNotWord: { 6771cb0ef41Sopenharmony_ci Label done; 6781cb0ef41Sopenharmony_ci if (mode_ != LATIN1) { 6791cb0ef41Sopenharmony_ci // Table is 256 entries, so all Latin1 characters can be tested. 6801cb0ef41Sopenharmony_ci __ cmpl(current_character(), Immediate('z')); 6811cb0ef41Sopenharmony_ci __ j(above, &done); 6821cb0ef41Sopenharmony_ci } 6831cb0ef41Sopenharmony_ci __ Move(rbx, ExternalReference::re_word_character_map()); 6841cb0ef41Sopenharmony_ci DCHECK_EQ(0, 6851cb0ef41Sopenharmony_ci word_character_map[0]); // Character '\0' is not a word char. 6861cb0ef41Sopenharmony_ci __ testb(Operand(rbx, current_character(), times_1, 0), 6871cb0ef41Sopenharmony_ci current_character()); 6881cb0ef41Sopenharmony_ci BranchOrBacktrack(not_zero, on_no_match); 6891cb0ef41Sopenharmony_ci if (mode_ != LATIN1) { 6901cb0ef41Sopenharmony_ci __ bind(&done); 6911cb0ef41Sopenharmony_ci } 6921cb0ef41Sopenharmony_ci return true; 6931cb0ef41Sopenharmony_ci } 6941cb0ef41Sopenharmony_ci 6951cb0ef41Sopenharmony_ci case StandardCharacterSet::kEverything: 6961cb0ef41Sopenharmony_ci // Match any character. 6971cb0ef41Sopenharmony_ci return true; 6981cb0ef41Sopenharmony_ci } 6991cb0ef41Sopenharmony_ci} 7001cb0ef41Sopenharmony_ci 7011cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::Fail() { 7021cb0ef41Sopenharmony_ci STATIC_ASSERT(FAILURE == 0); // Return value for failure is zero. 7031cb0ef41Sopenharmony_ci if (!global()) { 7041cb0ef41Sopenharmony_ci __ Move(rax, FAILURE); 7051cb0ef41Sopenharmony_ci } 7061cb0ef41Sopenharmony_ci __ jmp(&exit_label_); 7071cb0ef41Sopenharmony_ci} 7081cb0ef41Sopenharmony_ci 7091cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::LoadRegExpStackPointerFromMemory(Register dst) { 7101cb0ef41Sopenharmony_ci ExternalReference ref = 7111cb0ef41Sopenharmony_ci ExternalReference::address_of_regexp_stack_stack_pointer(isolate()); 7121cb0ef41Sopenharmony_ci __ movq(dst, __ ExternalReferenceAsOperand(ref, dst)); 7131cb0ef41Sopenharmony_ci} 7141cb0ef41Sopenharmony_ci 7151cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::StoreRegExpStackPointerToMemory( 7161cb0ef41Sopenharmony_ci Register src, Register scratch) { 7171cb0ef41Sopenharmony_ci ExternalReference ref = 7181cb0ef41Sopenharmony_ci ExternalReference::address_of_regexp_stack_stack_pointer(isolate()); 7191cb0ef41Sopenharmony_ci __ movq(__ ExternalReferenceAsOperand(ref, scratch), src); 7201cb0ef41Sopenharmony_ci} 7211cb0ef41Sopenharmony_ci 7221cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::PushRegExpBasePointer(Register stack_pointer, 7231cb0ef41Sopenharmony_ci Register scratch) { 7241cb0ef41Sopenharmony_ci ExternalReference ref = 7251cb0ef41Sopenharmony_ci ExternalReference::address_of_regexp_stack_memory_top_address(isolate()); 7261cb0ef41Sopenharmony_ci __ movq(scratch, __ ExternalReferenceAsOperand(ref, scratch)); 7271cb0ef41Sopenharmony_ci __ subq(scratch, stack_pointer); 7281cb0ef41Sopenharmony_ci __ movq(Operand(rbp, kRegExpStackBasePointer), scratch); 7291cb0ef41Sopenharmony_ci} 7301cb0ef41Sopenharmony_ci 7311cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::PopRegExpBasePointer(Register stack_pointer_out, 7321cb0ef41Sopenharmony_ci Register scratch) { 7331cb0ef41Sopenharmony_ci ExternalReference ref = 7341cb0ef41Sopenharmony_ci ExternalReference::address_of_regexp_stack_memory_top_address(isolate()); 7351cb0ef41Sopenharmony_ci __ movq(scratch, Operand(rbp, kRegExpStackBasePointer)); 7361cb0ef41Sopenharmony_ci __ movq(stack_pointer_out, 7371cb0ef41Sopenharmony_ci __ ExternalReferenceAsOperand(ref, stack_pointer_out)); 7381cb0ef41Sopenharmony_ci __ subq(stack_pointer_out, scratch); 7391cb0ef41Sopenharmony_ci StoreRegExpStackPointerToMemory(stack_pointer_out, scratch); 7401cb0ef41Sopenharmony_ci} 7411cb0ef41Sopenharmony_ci 7421cb0ef41Sopenharmony_ciHandle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) { 7431cb0ef41Sopenharmony_ci Label return_rax; 7441cb0ef41Sopenharmony_ci // Finalize code - write the entry point code now we know how many registers 7451cb0ef41Sopenharmony_ci // we need. 7461cb0ef41Sopenharmony_ci __ bind(&entry_label_); 7471cb0ef41Sopenharmony_ci 7481cb0ef41Sopenharmony_ci // Tell the system that we have a stack frame. Because the type is MANUAL, no 7491cb0ef41Sopenharmony_ci // physical frame is generated. 7501cb0ef41Sopenharmony_ci FrameScope scope(&masm_, StackFrame::MANUAL); 7511cb0ef41Sopenharmony_ci 7521cb0ef41Sopenharmony_ci // Actually emit code to start a new stack frame. 7531cb0ef41Sopenharmony_ci __ pushq(rbp); 7541cb0ef41Sopenharmony_ci __ movq(rbp, rsp); 7551cb0ef41Sopenharmony_ci 7561cb0ef41Sopenharmony_ci // Save parameters and callee-save registers. Order here should correspond 7571cb0ef41Sopenharmony_ci // to order of kBackup_ebx etc. 7581cb0ef41Sopenharmony_ci#ifdef V8_TARGET_OS_WIN 7591cb0ef41Sopenharmony_ci // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots. 7601cb0ef41Sopenharmony_ci // Store register parameters in pre-allocated stack slots. 7611cb0ef41Sopenharmony_ci __ movq(Operand(rbp, kInputString), arg_reg_1); 7621cb0ef41Sopenharmony_ci __ movq(Operand(rbp, kStartIndex), arg_reg_2); // Passed as int32 in edx. 7631cb0ef41Sopenharmony_ci __ movq(Operand(rbp, kInputStart), arg_reg_3); 7641cb0ef41Sopenharmony_ci __ movq(Operand(rbp, kInputEnd), arg_reg_4); 7651cb0ef41Sopenharmony_ci 7661cb0ef41Sopenharmony_ci STATIC_ASSERT(kNumCalleeSaveRegisters == 3); 7671cb0ef41Sopenharmony_ci __ pushq(rsi); 7681cb0ef41Sopenharmony_ci __ pushq(rdi); 7691cb0ef41Sopenharmony_ci __ pushq(rbx); 7701cb0ef41Sopenharmony_ci#else 7711cb0ef41Sopenharmony_ci // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9 (and then on stack). 7721cb0ef41Sopenharmony_ci // Push register parameters on stack for reference. 7731cb0ef41Sopenharmony_ci DCHECK_EQ(kInputString, -1 * kSystemPointerSize); 7741cb0ef41Sopenharmony_ci DCHECK_EQ(kStartIndex, -2 * kSystemPointerSize); 7751cb0ef41Sopenharmony_ci DCHECK_EQ(kInputStart, -3 * kSystemPointerSize); 7761cb0ef41Sopenharmony_ci DCHECK_EQ(kInputEnd, -4 * kSystemPointerSize); 7771cb0ef41Sopenharmony_ci DCHECK_EQ(kRegisterOutput, -5 * kSystemPointerSize); 7781cb0ef41Sopenharmony_ci DCHECK_EQ(kNumOutputRegisters, -6 * kSystemPointerSize); 7791cb0ef41Sopenharmony_ci __ pushq(arg_reg_1); 7801cb0ef41Sopenharmony_ci __ pushq(arg_reg_2); 7811cb0ef41Sopenharmony_ci __ pushq(arg_reg_3); 7821cb0ef41Sopenharmony_ci __ pushq(arg_reg_4); 7831cb0ef41Sopenharmony_ci __ pushq(r8); 7841cb0ef41Sopenharmony_ci __ pushq(r9); 7851cb0ef41Sopenharmony_ci 7861cb0ef41Sopenharmony_ci STATIC_ASSERT(kNumCalleeSaveRegisters == 1); 7871cb0ef41Sopenharmony_ci __ pushq(rbx); 7881cb0ef41Sopenharmony_ci#endif 7891cb0ef41Sopenharmony_ci 7901cb0ef41Sopenharmony_ci STATIC_ASSERT(kSuccessfulCaptures == 7911cb0ef41Sopenharmony_ci kLastCalleeSaveRegister - kSystemPointerSize); 7921cb0ef41Sopenharmony_ci __ Push(Immediate(0)); // Number of successful matches in a global regexp. 7931cb0ef41Sopenharmony_ci STATIC_ASSERT(kStringStartMinusOne == 7941cb0ef41Sopenharmony_ci kSuccessfulCaptures - kSystemPointerSize); 7951cb0ef41Sopenharmony_ci __ Push(Immediate(0)); // Make room for "string start - 1" constant. 7961cb0ef41Sopenharmony_ci STATIC_ASSERT(kBacktrackCount == kStringStartMinusOne - kSystemPointerSize); 7971cb0ef41Sopenharmony_ci __ Push(Immediate(0)); // The backtrack counter. 7981cb0ef41Sopenharmony_ci STATIC_ASSERT(kRegExpStackBasePointer == 7991cb0ef41Sopenharmony_ci kBacktrackCount - kSystemPointerSize); 8001cb0ef41Sopenharmony_ci __ Push(Immediate(0)); // The regexp stack base ptr. 8011cb0ef41Sopenharmony_ci 8021cb0ef41Sopenharmony_ci // Initialize backtrack stack pointer. It must not be clobbered from here on. 8031cb0ef41Sopenharmony_ci // Note the backtrack_stackpointer is *not* callee-saved. 8041cb0ef41Sopenharmony_ci STATIC_ASSERT(backtrack_stackpointer() == rcx); 8051cb0ef41Sopenharmony_ci LoadRegExpStackPointerFromMemory(backtrack_stackpointer()); 8061cb0ef41Sopenharmony_ci 8071cb0ef41Sopenharmony_ci // Store the regexp base pointer - we'll later restore it / write it to 8081cb0ef41Sopenharmony_ci // memory when returning from this irregexp code object. 8091cb0ef41Sopenharmony_ci PushRegExpBasePointer(backtrack_stackpointer(), kScratchRegister); 8101cb0ef41Sopenharmony_ci 8111cb0ef41Sopenharmony_ci { 8121cb0ef41Sopenharmony_ci // Check if we have space on the stack for registers. 8131cb0ef41Sopenharmony_ci Label stack_limit_hit, stack_ok; 8141cb0ef41Sopenharmony_ci 8151cb0ef41Sopenharmony_ci ExternalReference stack_limit = 8161cb0ef41Sopenharmony_ci ExternalReference::address_of_jslimit(isolate()); 8171cb0ef41Sopenharmony_ci __ movq(r9, rsp); 8181cb0ef41Sopenharmony_ci __ Move(kScratchRegister, stack_limit); 8191cb0ef41Sopenharmony_ci __ subq(r9, Operand(kScratchRegister, 0)); 8201cb0ef41Sopenharmony_ci // Handle it if the stack pointer is already below the stack limit. 8211cb0ef41Sopenharmony_ci __ j(below_equal, &stack_limit_hit); 8221cb0ef41Sopenharmony_ci // Check if there is room for the variable number of registers above 8231cb0ef41Sopenharmony_ci // the stack limit. 8241cb0ef41Sopenharmony_ci __ cmpq(r9, Immediate(num_registers_ * kSystemPointerSize)); 8251cb0ef41Sopenharmony_ci __ j(above_equal, &stack_ok); 8261cb0ef41Sopenharmony_ci // Exit with OutOfMemory exception. There is not enough space on the stack 8271cb0ef41Sopenharmony_ci // for our working registers. 8281cb0ef41Sopenharmony_ci __ Move(rax, EXCEPTION); 8291cb0ef41Sopenharmony_ci __ jmp(&return_rax); 8301cb0ef41Sopenharmony_ci 8311cb0ef41Sopenharmony_ci __ bind(&stack_limit_hit); 8321cb0ef41Sopenharmony_ci __ Move(code_object_pointer(), masm_.CodeObject()); 8331cb0ef41Sopenharmony_ci __ pushq(backtrack_stackpointer()); 8341cb0ef41Sopenharmony_ci CallCheckStackGuardState(); // Preserves no registers beside rbp and rsp. 8351cb0ef41Sopenharmony_ci __ popq(backtrack_stackpointer()); 8361cb0ef41Sopenharmony_ci __ testq(rax, rax); 8371cb0ef41Sopenharmony_ci // If returned value is non-zero, we exit with the returned value as result. 8381cb0ef41Sopenharmony_ci __ j(not_zero, &return_rax); 8391cb0ef41Sopenharmony_ci 8401cb0ef41Sopenharmony_ci __ bind(&stack_ok); 8411cb0ef41Sopenharmony_ci } 8421cb0ef41Sopenharmony_ci 8431cb0ef41Sopenharmony_ci // Allocate space on stack for registers. 8441cb0ef41Sopenharmony_ci __ AllocateStackSpace(num_registers_ * kSystemPointerSize); 8451cb0ef41Sopenharmony_ci // Load string length. 8461cb0ef41Sopenharmony_ci __ movq(rsi, Operand(rbp, kInputEnd)); 8471cb0ef41Sopenharmony_ci // Load input position. 8481cb0ef41Sopenharmony_ci __ movq(rdi, Operand(rbp, kInputStart)); 8491cb0ef41Sopenharmony_ci // Set up rdi to be negative offset from string end. 8501cb0ef41Sopenharmony_ci __ subq(rdi, rsi); 8511cb0ef41Sopenharmony_ci // Set rax to address of char before start of the string 8521cb0ef41Sopenharmony_ci // (effectively string position -1). 8531cb0ef41Sopenharmony_ci __ movq(rbx, Operand(rbp, kStartIndex)); 8541cb0ef41Sopenharmony_ci __ negq(rbx); 8551cb0ef41Sopenharmony_ci if (mode_ == UC16) { 8561cb0ef41Sopenharmony_ci __ leaq(rax, Operand(rdi, rbx, times_2, -char_size())); 8571cb0ef41Sopenharmony_ci } else { 8581cb0ef41Sopenharmony_ci __ leaq(rax, Operand(rdi, rbx, times_1, -char_size())); 8591cb0ef41Sopenharmony_ci } 8601cb0ef41Sopenharmony_ci // Store this value in a local variable, for use when clearing 8611cb0ef41Sopenharmony_ci // position registers. 8621cb0ef41Sopenharmony_ci __ movq(Operand(rbp, kStringStartMinusOne), rax); 8631cb0ef41Sopenharmony_ci 8641cb0ef41Sopenharmony_ci // Initialize code object pointer. 8651cb0ef41Sopenharmony_ci __ Move(code_object_pointer(), masm_.CodeObject()); 8661cb0ef41Sopenharmony_ci 8671cb0ef41Sopenharmony_ci Label load_char_start_regexp; // Execution restarts here for global regexps. 8681cb0ef41Sopenharmony_ci { 8691cb0ef41Sopenharmony_ci Label start_regexp; 8701cb0ef41Sopenharmony_ci 8711cb0ef41Sopenharmony_ci // Load newline if index is at start, previous character otherwise. 8721cb0ef41Sopenharmony_ci __ cmpl(Operand(rbp, kStartIndex), Immediate(0)); 8731cb0ef41Sopenharmony_ci __ j(not_equal, &load_char_start_regexp, Label::kNear); 8741cb0ef41Sopenharmony_ci __ Move(current_character(), '\n'); 8751cb0ef41Sopenharmony_ci __ jmp(&start_regexp, Label::kNear); 8761cb0ef41Sopenharmony_ci 8771cb0ef41Sopenharmony_ci // Global regexp restarts matching here. 8781cb0ef41Sopenharmony_ci __ bind(&load_char_start_regexp); 8791cb0ef41Sopenharmony_ci // Load previous char as initial value of current character register. 8801cb0ef41Sopenharmony_ci LoadCurrentCharacterUnchecked(-1, 1); 8811cb0ef41Sopenharmony_ci 8821cb0ef41Sopenharmony_ci __ bind(&start_regexp); 8831cb0ef41Sopenharmony_ci } 8841cb0ef41Sopenharmony_ci 8851cb0ef41Sopenharmony_ci // Initialize on-stack registers. 8861cb0ef41Sopenharmony_ci if (num_saved_registers_ > 0) { 8871cb0ef41Sopenharmony_ci // Fill saved registers with initial value = start offset - 1 8881cb0ef41Sopenharmony_ci // Fill in stack push order, to avoid accessing across an unwritten 8891cb0ef41Sopenharmony_ci // page (a problem on Windows). 8901cb0ef41Sopenharmony_ci if (num_saved_registers_ > 8) { 8911cb0ef41Sopenharmony_ci __ Move(r9, kRegisterZero); 8921cb0ef41Sopenharmony_ci Label init_loop; 8931cb0ef41Sopenharmony_ci __ bind(&init_loop); 8941cb0ef41Sopenharmony_ci __ movq(Operand(rbp, r9, times_1, 0), rax); 8951cb0ef41Sopenharmony_ci __ subq(r9, Immediate(kSystemPointerSize)); 8961cb0ef41Sopenharmony_ci __ cmpq(r9, Immediate(kRegisterZero - 8971cb0ef41Sopenharmony_ci num_saved_registers_ * kSystemPointerSize)); 8981cb0ef41Sopenharmony_ci __ j(greater, &init_loop); 8991cb0ef41Sopenharmony_ci } else { // Unroll the loop. 9001cb0ef41Sopenharmony_ci for (int i = 0; i < num_saved_registers_; i++) { 9011cb0ef41Sopenharmony_ci __ movq(register_location(i), rax); 9021cb0ef41Sopenharmony_ci } 9031cb0ef41Sopenharmony_ci } 9041cb0ef41Sopenharmony_ci } 9051cb0ef41Sopenharmony_ci 9061cb0ef41Sopenharmony_ci __ jmp(&start_label_); 9071cb0ef41Sopenharmony_ci 9081cb0ef41Sopenharmony_ci // Exit code: 9091cb0ef41Sopenharmony_ci if (success_label_.is_linked()) { 9101cb0ef41Sopenharmony_ci // Save captures when successful. 9111cb0ef41Sopenharmony_ci __ bind(&success_label_); 9121cb0ef41Sopenharmony_ci if (num_saved_registers_ > 0) { 9131cb0ef41Sopenharmony_ci // copy captures to output 9141cb0ef41Sopenharmony_ci __ movq(rdx, Operand(rbp, kStartIndex)); 9151cb0ef41Sopenharmony_ci __ movq(rbx, Operand(rbp, kRegisterOutput)); 9161cb0ef41Sopenharmony_ci __ movq(rcx, Operand(rbp, kInputEnd)); 9171cb0ef41Sopenharmony_ci __ subq(rcx, Operand(rbp, kInputStart)); 9181cb0ef41Sopenharmony_ci if (mode_ == UC16) { 9191cb0ef41Sopenharmony_ci __ leaq(rcx, Operand(rcx, rdx, times_2, 0)); 9201cb0ef41Sopenharmony_ci } else { 9211cb0ef41Sopenharmony_ci __ addq(rcx, rdx); 9221cb0ef41Sopenharmony_ci } 9231cb0ef41Sopenharmony_ci for (int i = 0; i < num_saved_registers_; i++) { 9241cb0ef41Sopenharmony_ci __ movq(rax, register_location(i)); 9251cb0ef41Sopenharmony_ci if (i == 0 && global_with_zero_length_check()) { 9261cb0ef41Sopenharmony_ci // Keep capture start in rdx for the zero-length check later. 9271cb0ef41Sopenharmony_ci __ movq(rdx, rax); 9281cb0ef41Sopenharmony_ci } 9291cb0ef41Sopenharmony_ci __ addq(rax, rcx); // Convert to index from start, not end. 9301cb0ef41Sopenharmony_ci if (mode_ == UC16) { 9311cb0ef41Sopenharmony_ci __ sarq(rax, Immediate(1)); // Convert byte index to character index. 9321cb0ef41Sopenharmony_ci } 9331cb0ef41Sopenharmony_ci __ movl(Operand(rbx, i * kIntSize), rax); 9341cb0ef41Sopenharmony_ci } 9351cb0ef41Sopenharmony_ci } 9361cb0ef41Sopenharmony_ci 9371cb0ef41Sopenharmony_ci if (global()) { 9381cb0ef41Sopenharmony_ci // Restart matching if the regular expression is flagged as global. 9391cb0ef41Sopenharmony_ci // Increment success counter. 9401cb0ef41Sopenharmony_ci __ incq(Operand(rbp, kSuccessfulCaptures)); 9411cb0ef41Sopenharmony_ci // Capture results have been stored, so the number of remaining global 9421cb0ef41Sopenharmony_ci // output registers is reduced by the number of stored captures. 9431cb0ef41Sopenharmony_ci __ movsxlq(rcx, Operand(rbp, kNumOutputRegisters)); 9441cb0ef41Sopenharmony_ci __ subq(rcx, Immediate(num_saved_registers_)); 9451cb0ef41Sopenharmony_ci // Check whether we have enough room for another set of capture results. 9461cb0ef41Sopenharmony_ci __ cmpq(rcx, Immediate(num_saved_registers_)); 9471cb0ef41Sopenharmony_ci __ j(less, &exit_label_); 9481cb0ef41Sopenharmony_ci 9491cb0ef41Sopenharmony_ci __ movq(Operand(rbp, kNumOutputRegisters), rcx); 9501cb0ef41Sopenharmony_ci // Advance the location for output. 9511cb0ef41Sopenharmony_ci __ addq(Operand(rbp, kRegisterOutput), 9521cb0ef41Sopenharmony_ci Immediate(num_saved_registers_ * kIntSize)); 9531cb0ef41Sopenharmony_ci 9541cb0ef41Sopenharmony_ci // Prepare rax to initialize registers with its value in the next run. 9551cb0ef41Sopenharmony_ci __ movq(rax, Operand(rbp, kStringStartMinusOne)); 9561cb0ef41Sopenharmony_ci 9571cb0ef41Sopenharmony_ci // Restore the original regexp stack pointer value (effectively, pop the 9581cb0ef41Sopenharmony_ci // stored base pointer). 9591cb0ef41Sopenharmony_ci PopRegExpBasePointer(backtrack_stackpointer(), kScratchRegister); 9601cb0ef41Sopenharmony_ci 9611cb0ef41Sopenharmony_ci if (global_with_zero_length_check()) { 9621cb0ef41Sopenharmony_ci // Special case for zero-length matches. 9631cb0ef41Sopenharmony_ci // rdx: capture start index 9641cb0ef41Sopenharmony_ci __ cmpq(rdi, rdx); 9651cb0ef41Sopenharmony_ci // Not a zero-length match, restart. 9661cb0ef41Sopenharmony_ci __ j(not_equal, &load_char_start_regexp); 9671cb0ef41Sopenharmony_ci // rdi (offset from the end) is zero if we already reached the end. 9681cb0ef41Sopenharmony_ci __ testq(rdi, rdi); 9691cb0ef41Sopenharmony_ci __ j(zero, &exit_label_, Label::kNear); 9701cb0ef41Sopenharmony_ci // Advance current position after a zero-length match. 9711cb0ef41Sopenharmony_ci Label advance; 9721cb0ef41Sopenharmony_ci __ bind(&advance); 9731cb0ef41Sopenharmony_ci if (mode_ == UC16) { 9741cb0ef41Sopenharmony_ci __ addq(rdi, Immediate(2)); 9751cb0ef41Sopenharmony_ci } else { 9761cb0ef41Sopenharmony_ci __ incq(rdi); 9771cb0ef41Sopenharmony_ci } 9781cb0ef41Sopenharmony_ci if (global_unicode()) CheckNotInSurrogatePair(0, &advance); 9791cb0ef41Sopenharmony_ci } 9801cb0ef41Sopenharmony_ci 9811cb0ef41Sopenharmony_ci __ jmp(&load_char_start_regexp); 9821cb0ef41Sopenharmony_ci } else { 9831cb0ef41Sopenharmony_ci __ Move(rax, SUCCESS); 9841cb0ef41Sopenharmony_ci } 9851cb0ef41Sopenharmony_ci } 9861cb0ef41Sopenharmony_ci 9871cb0ef41Sopenharmony_ci __ bind(&exit_label_); 9881cb0ef41Sopenharmony_ci if (global()) { 9891cb0ef41Sopenharmony_ci // Return the number of successful captures. 9901cb0ef41Sopenharmony_ci __ movq(rax, Operand(rbp, kSuccessfulCaptures)); 9911cb0ef41Sopenharmony_ci } 9921cb0ef41Sopenharmony_ci 9931cb0ef41Sopenharmony_ci __ bind(&return_rax); 9941cb0ef41Sopenharmony_ci // Restore the original regexp stack pointer value (effectively, pop the 9951cb0ef41Sopenharmony_ci // stored base pointer). 9961cb0ef41Sopenharmony_ci PopRegExpBasePointer(backtrack_stackpointer(), kScratchRegister); 9971cb0ef41Sopenharmony_ci 9981cb0ef41Sopenharmony_ci#ifdef V8_TARGET_OS_WIN 9991cb0ef41Sopenharmony_ci // Restore callee save registers. 10001cb0ef41Sopenharmony_ci __ leaq(rsp, Operand(rbp, kLastCalleeSaveRegister)); 10011cb0ef41Sopenharmony_ci STATIC_ASSERT(kNumCalleeSaveRegisters == 3); 10021cb0ef41Sopenharmony_ci __ popq(rbx); 10031cb0ef41Sopenharmony_ci __ popq(rdi); 10041cb0ef41Sopenharmony_ci __ popq(rsi); 10051cb0ef41Sopenharmony_ci // Stack now at rbp. 10061cb0ef41Sopenharmony_ci#else 10071cb0ef41Sopenharmony_ci // Restore callee save register. 10081cb0ef41Sopenharmony_ci STATIC_ASSERT(kNumCalleeSaveRegisters == 1); 10091cb0ef41Sopenharmony_ci __ movq(rbx, Operand(rbp, kBackup_rbx)); 10101cb0ef41Sopenharmony_ci // Skip rsp to rbp. 10111cb0ef41Sopenharmony_ci __ movq(rsp, rbp); 10121cb0ef41Sopenharmony_ci#endif 10131cb0ef41Sopenharmony_ci 10141cb0ef41Sopenharmony_ci // Exit function frame, restore previous one. 10151cb0ef41Sopenharmony_ci __ popq(rbp); 10161cb0ef41Sopenharmony_ci __ ret(0); 10171cb0ef41Sopenharmony_ci 10181cb0ef41Sopenharmony_ci // Backtrack code (branch target for conditional backtracks). 10191cb0ef41Sopenharmony_ci if (backtrack_label_.is_linked()) { 10201cb0ef41Sopenharmony_ci __ bind(&backtrack_label_); 10211cb0ef41Sopenharmony_ci Backtrack(); 10221cb0ef41Sopenharmony_ci } 10231cb0ef41Sopenharmony_ci 10241cb0ef41Sopenharmony_ci Label exit_with_exception; 10251cb0ef41Sopenharmony_ci 10261cb0ef41Sopenharmony_ci // Preempt-code 10271cb0ef41Sopenharmony_ci if (check_preempt_label_.is_linked()) { 10281cb0ef41Sopenharmony_ci SafeCallTarget(&check_preempt_label_); 10291cb0ef41Sopenharmony_ci 10301cb0ef41Sopenharmony_ci __ pushq(rdi); 10311cb0ef41Sopenharmony_ci 10321cb0ef41Sopenharmony_ci StoreRegExpStackPointerToMemory(backtrack_stackpointer(), kScratchRegister); 10331cb0ef41Sopenharmony_ci 10341cb0ef41Sopenharmony_ci CallCheckStackGuardState(); 10351cb0ef41Sopenharmony_ci __ testq(rax, rax); 10361cb0ef41Sopenharmony_ci // If returning non-zero, we should end execution with the given 10371cb0ef41Sopenharmony_ci // result as return value. 10381cb0ef41Sopenharmony_ci __ j(not_zero, &return_rax); 10391cb0ef41Sopenharmony_ci 10401cb0ef41Sopenharmony_ci // Restore registers. 10411cb0ef41Sopenharmony_ci __ Move(code_object_pointer(), masm_.CodeObject()); 10421cb0ef41Sopenharmony_ci __ popq(rdi); 10431cb0ef41Sopenharmony_ci 10441cb0ef41Sopenharmony_ci LoadRegExpStackPointerFromMemory(backtrack_stackpointer()); 10451cb0ef41Sopenharmony_ci 10461cb0ef41Sopenharmony_ci // String might have moved: Reload esi from frame. 10471cb0ef41Sopenharmony_ci __ movq(rsi, Operand(rbp, kInputEnd)); 10481cb0ef41Sopenharmony_ci SafeReturn(); 10491cb0ef41Sopenharmony_ci } 10501cb0ef41Sopenharmony_ci 10511cb0ef41Sopenharmony_ci // Backtrack stack overflow code. 10521cb0ef41Sopenharmony_ci if (stack_overflow_label_.is_linked()) { 10531cb0ef41Sopenharmony_ci SafeCallTarget(&stack_overflow_label_); 10541cb0ef41Sopenharmony_ci // Reached if the backtrack-stack limit has been hit. 10551cb0ef41Sopenharmony_ci 10561cb0ef41Sopenharmony_ci PushCallerSavedRegisters(); 10571cb0ef41Sopenharmony_ci 10581cb0ef41Sopenharmony_ci // Call GrowStack(isolate). 10591cb0ef41Sopenharmony_ci 10601cb0ef41Sopenharmony_ci StoreRegExpStackPointerToMemory(backtrack_stackpointer(), kScratchRegister); 10611cb0ef41Sopenharmony_ci 10621cb0ef41Sopenharmony_ci static constexpr int kNumArguments = 1; 10631cb0ef41Sopenharmony_ci __ PrepareCallCFunction(kNumArguments); 10641cb0ef41Sopenharmony_ci __ LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate())); 10651cb0ef41Sopenharmony_ci 10661cb0ef41Sopenharmony_ci ExternalReference grow_stack = ExternalReference::re_grow_stack(); 10671cb0ef41Sopenharmony_ci __ CallCFunction(grow_stack, kNumArguments); 10681cb0ef41Sopenharmony_ci // If nullptr is returned, we have failed to grow the stack, and must exit 10691cb0ef41Sopenharmony_ci // with a stack-overflow exception. 10701cb0ef41Sopenharmony_ci __ testq(rax, rax); 10711cb0ef41Sopenharmony_ci __ j(equal, &exit_with_exception); 10721cb0ef41Sopenharmony_ci PopCallerSavedRegisters(); 10731cb0ef41Sopenharmony_ci // Otherwise use return value as new stack pointer. 10741cb0ef41Sopenharmony_ci __ movq(backtrack_stackpointer(), rax); 10751cb0ef41Sopenharmony_ci // Restore saved registers and continue. 10761cb0ef41Sopenharmony_ci __ Move(code_object_pointer(), masm_.CodeObject()); 10771cb0ef41Sopenharmony_ci SafeReturn(); 10781cb0ef41Sopenharmony_ci } 10791cb0ef41Sopenharmony_ci 10801cb0ef41Sopenharmony_ci if (exit_with_exception.is_linked()) { 10811cb0ef41Sopenharmony_ci // If any of the code above needed to exit with an exception. 10821cb0ef41Sopenharmony_ci __ bind(&exit_with_exception); 10831cb0ef41Sopenharmony_ci // Exit with Result EXCEPTION(-1) to signal thrown exception. 10841cb0ef41Sopenharmony_ci __ Move(rax, EXCEPTION); 10851cb0ef41Sopenharmony_ci __ jmp(&return_rax); 10861cb0ef41Sopenharmony_ci } 10871cb0ef41Sopenharmony_ci 10881cb0ef41Sopenharmony_ci if (fallback_label_.is_linked()) { 10891cb0ef41Sopenharmony_ci __ bind(&fallback_label_); 10901cb0ef41Sopenharmony_ci __ Move(rax, FALLBACK_TO_EXPERIMENTAL); 10911cb0ef41Sopenharmony_ci __ jmp(&return_rax); 10921cb0ef41Sopenharmony_ci } 10931cb0ef41Sopenharmony_ci 10941cb0ef41Sopenharmony_ci FixupCodeRelativePositions(); 10951cb0ef41Sopenharmony_ci 10961cb0ef41Sopenharmony_ci CodeDesc code_desc; 10971cb0ef41Sopenharmony_ci Isolate* isolate = this->isolate(); 10981cb0ef41Sopenharmony_ci masm_.GetCode(isolate, &code_desc); 10991cb0ef41Sopenharmony_ci Handle<Code> code = Factory::CodeBuilder(isolate, code_desc, CodeKind::REGEXP) 11001cb0ef41Sopenharmony_ci .set_self_reference(masm_.CodeObject()) 11011cb0ef41Sopenharmony_ci .Build(); 11021cb0ef41Sopenharmony_ci PROFILE(isolate, 11031cb0ef41Sopenharmony_ci RegExpCodeCreateEvent(Handle<AbstractCode>::cast(code), source)); 11041cb0ef41Sopenharmony_ci return Handle<HeapObject>::cast(code); 11051cb0ef41Sopenharmony_ci} 11061cb0ef41Sopenharmony_ci 11071cb0ef41Sopenharmony_ci 11081cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::GoTo(Label* to) { 11091cb0ef41Sopenharmony_ci BranchOrBacktrack(no_condition, to); 11101cb0ef41Sopenharmony_ci} 11111cb0ef41Sopenharmony_ci 11121cb0ef41Sopenharmony_ci 11131cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::IfRegisterGE(int reg, 11141cb0ef41Sopenharmony_ci int comparand, 11151cb0ef41Sopenharmony_ci Label* if_ge) { 11161cb0ef41Sopenharmony_ci __ cmpq(register_location(reg), Immediate(comparand)); 11171cb0ef41Sopenharmony_ci BranchOrBacktrack(greater_equal, if_ge); 11181cb0ef41Sopenharmony_ci} 11191cb0ef41Sopenharmony_ci 11201cb0ef41Sopenharmony_ci 11211cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::IfRegisterLT(int reg, 11221cb0ef41Sopenharmony_ci int comparand, 11231cb0ef41Sopenharmony_ci Label* if_lt) { 11241cb0ef41Sopenharmony_ci __ cmpq(register_location(reg), Immediate(comparand)); 11251cb0ef41Sopenharmony_ci BranchOrBacktrack(less, if_lt); 11261cb0ef41Sopenharmony_ci} 11271cb0ef41Sopenharmony_ci 11281cb0ef41Sopenharmony_ci 11291cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::IfRegisterEqPos(int reg, 11301cb0ef41Sopenharmony_ci Label* if_eq) { 11311cb0ef41Sopenharmony_ci __ cmpq(rdi, register_location(reg)); 11321cb0ef41Sopenharmony_ci BranchOrBacktrack(equal, if_eq); 11331cb0ef41Sopenharmony_ci} 11341cb0ef41Sopenharmony_ci 11351cb0ef41Sopenharmony_ci 11361cb0ef41Sopenharmony_ciRegExpMacroAssembler::IrregexpImplementation 11371cb0ef41Sopenharmony_ci RegExpMacroAssemblerX64::Implementation() { 11381cb0ef41Sopenharmony_ci return kX64Implementation; 11391cb0ef41Sopenharmony_ci} 11401cb0ef41Sopenharmony_ci 11411cb0ef41Sopenharmony_ci 11421cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::PopCurrentPosition() { 11431cb0ef41Sopenharmony_ci Pop(rdi); 11441cb0ef41Sopenharmony_ci} 11451cb0ef41Sopenharmony_ci 11461cb0ef41Sopenharmony_ci 11471cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::PopRegister(int register_index) { 11481cb0ef41Sopenharmony_ci Pop(rax); 11491cb0ef41Sopenharmony_ci __ movq(register_location(register_index), rax); 11501cb0ef41Sopenharmony_ci} 11511cb0ef41Sopenharmony_ci 11521cb0ef41Sopenharmony_ci 11531cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::PushBacktrack(Label* label) { 11541cb0ef41Sopenharmony_ci Push(label); 11551cb0ef41Sopenharmony_ci CheckStackLimit(); 11561cb0ef41Sopenharmony_ci} 11571cb0ef41Sopenharmony_ci 11581cb0ef41Sopenharmony_ci 11591cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::PushCurrentPosition() { 11601cb0ef41Sopenharmony_ci Push(rdi); 11611cb0ef41Sopenharmony_ci} 11621cb0ef41Sopenharmony_ci 11631cb0ef41Sopenharmony_ci 11641cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::PushRegister(int register_index, 11651cb0ef41Sopenharmony_ci StackCheckFlag check_stack_limit) { 11661cb0ef41Sopenharmony_ci __ movq(rax, register_location(register_index)); 11671cb0ef41Sopenharmony_ci Push(rax); 11681cb0ef41Sopenharmony_ci if (check_stack_limit) CheckStackLimit(); 11691cb0ef41Sopenharmony_ci} 11701cb0ef41Sopenharmony_ci 11711cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::ReadCurrentPositionFromRegister(int reg) { 11721cb0ef41Sopenharmony_ci __ movq(rdi, register_location(reg)); 11731cb0ef41Sopenharmony_ci} 11741cb0ef41Sopenharmony_ci 11751cb0ef41Sopenharmony_ci 11761cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::ReadPositionFromRegister(Register dst, int reg) { 11771cb0ef41Sopenharmony_ci __ movq(dst, register_location(reg)); 11781cb0ef41Sopenharmony_ci} 11791cb0ef41Sopenharmony_ci 11801cb0ef41Sopenharmony_ci// Preserves a position-independent representation of the stack pointer in reg: 11811cb0ef41Sopenharmony_ci// reg = top - sp. 11821cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::WriteStackPointerToRegister(int reg) { 11831cb0ef41Sopenharmony_ci ExternalReference stack_top_address = 11841cb0ef41Sopenharmony_ci ExternalReference::address_of_regexp_stack_memory_top_address(isolate()); 11851cb0ef41Sopenharmony_ci __ movq(rax, __ ExternalReferenceAsOperand(stack_top_address, rax)); 11861cb0ef41Sopenharmony_ci __ subq(rax, backtrack_stackpointer()); 11871cb0ef41Sopenharmony_ci __ movq(register_location(reg), rax); 11881cb0ef41Sopenharmony_ci} 11891cb0ef41Sopenharmony_ci 11901cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::ReadStackPointerFromRegister(int reg) { 11911cb0ef41Sopenharmony_ci ExternalReference stack_top_address = 11921cb0ef41Sopenharmony_ci ExternalReference::address_of_regexp_stack_memory_top_address(isolate()); 11931cb0ef41Sopenharmony_ci __ movq(backtrack_stackpointer(), 11941cb0ef41Sopenharmony_ci __ ExternalReferenceAsOperand(stack_top_address, 11951cb0ef41Sopenharmony_ci backtrack_stackpointer())); 11961cb0ef41Sopenharmony_ci __ subq(backtrack_stackpointer(), register_location(reg)); 11971cb0ef41Sopenharmony_ci} 11981cb0ef41Sopenharmony_ci 11991cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::SetCurrentPositionFromEnd(int by) { 12001cb0ef41Sopenharmony_ci Label after_position; 12011cb0ef41Sopenharmony_ci __ cmpq(rdi, Immediate(-by * char_size())); 12021cb0ef41Sopenharmony_ci __ j(greater_equal, &after_position, Label::kNear); 12031cb0ef41Sopenharmony_ci __ Move(rdi, -by * char_size()); 12041cb0ef41Sopenharmony_ci // On RegExp code entry (where this operation is used), the character before 12051cb0ef41Sopenharmony_ci // the current position is expected to be already loaded. 12061cb0ef41Sopenharmony_ci // We have advanced the position, so it's safe to read backwards. 12071cb0ef41Sopenharmony_ci LoadCurrentCharacterUnchecked(-1, 1); 12081cb0ef41Sopenharmony_ci __ bind(&after_position); 12091cb0ef41Sopenharmony_ci} 12101cb0ef41Sopenharmony_ci 12111cb0ef41Sopenharmony_ci 12121cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::SetRegister(int register_index, int to) { 12131cb0ef41Sopenharmony_ci DCHECK(register_index >= num_saved_registers_); // Reserved for positions! 12141cb0ef41Sopenharmony_ci __ movq(register_location(register_index), Immediate(to)); 12151cb0ef41Sopenharmony_ci} 12161cb0ef41Sopenharmony_ci 12171cb0ef41Sopenharmony_ci 12181cb0ef41Sopenharmony_cibool RegExpMacroAssemblerX64::Succeed() { 12191cb0ef41Sopenharmony_ci __ jmp(&success_label_); 12201cb0ef41Sopenharmony_ci return global(); 12211cb0ef41Sopenharmony_ci} 12221cb0ef41Sopenharmony_ci 12231cb0ef41Sopenharmony_ci 12241cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::WriteCurrentPositionToRegister(int reg, 12251cb0ef41Sopenharmony_ci int cp_offset) { 12261cb0ef41Sopenharmony_ci if (cp_offset == 0) { 12271cb0ef41Sopenharmony_ci __ movq(register_location(reg), rdi); 12281cb0ef41Sopenharmony_ci } else { 12291cb0ef41Sopenharmony_ci __ leaq(rax, Operand(rdi, cp_offset * char_size())); 12301cb0ef41Sopenharmony_ci __ movq(register_location(reg), rax); 12311cb0ef41Sopenharmony_ci } 12321cb0ef41Sopenharmony_ci} 12331cb0ef41Sopenharmony_ci 12341cb0ef41Sopenharmony_ci 12351cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::ClearRegisters(int reg_from, int reg_to) { 12361cb0ef41Sopenharmony_ci DCHECK(reg_from <= reg_to); 12371cb0ef41Sopenharmony_ci __ movq(rax, Operand(rbp, kStringStartMinusOne)); 12381cb0ef41Sopenharmony_ci for (int reg = reg_from; reg <= reg_to; reg++) { 12391cb0ef41Sopenharmony_ci __ movq(register_location(reg), rax); 12401cb0ef41Sopenharmony_ci } 12411cb0ef41Sopenharmony_ci} 12421cb0ef41Sopenharmony_ci 12431cb0ef41Sopenharmony_ci// Private methods: 12441cb0ef41Sopenharmony_ci 12451cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CallCheckStackGuardState() { 12461cb0ef41Sopenharmony_ci // This function call preserves no register values. Caller should 12471cb0ef41Sopenharmony_ci // store anything volatile in a C call or overwritten by this function. 12481cb0ef41Sopenharmony_ci static const int num_arguments = 3; 12491cb0ef41Sopenharmony_ci __ PrepareCallCFunction(num_arguments); 12501cb0ef41Sopenharmony_ci#ifdef V8_TARGET_OS_WIN 12511cb0ef41Sopenharmony_ci // Second argument: Code of self. (Do this before overwriting r8). 12521cb0ef41Sopenharmony_ci __ movq(rdx, code_object_pointer()); 12531cb0ef41Sopenharmony_ci // Third argument: RegExp code frame pointer. 12541cb0ef41Sopenharmony_ci __ movq(r8, rbp); 12551cb0ef41Sopenharmony_ci // First argument: Next address on the stack (will be address of 12561cb0ef41Sopenharmony_ci // return address). 12571cb0ef41Sopenharmony_ci __ leaq(rcx, Operand(rsp, -kSystemPointerSize)); 12581cb0ef41Sopenharmony_ci#else 12591cb0ef41Sopenharmony_ci // Third argument: RegExp code frame pointer. 12601cb0ef41Sopenharmony_ci __ movq(rdx, rbp); 12611cb0ef41Sopenharmony_ci // Second argument: Code of self. 12621cb0ef41Sopenharmony_ci __ movq(rsi, code_object_pointer()); 12631cb0ef41Sopenharmony_ci // First argument: Next address on the stack (will be address of 12641cb0ef41Sopenharmony_ci // return address). 12651cb0ef41Sopenharmony_ci __ leaq(rdi, Operand(rsp, -kSystemPointerSize)); 12661cb0ef41Sopenharmony_ci#endif 12671cb0ef41Sopenharmony_ci ExternalReference stack_check = 12681cb0ef41Sopenharmony_ci ExternalReference::re_check_stack_guard_state(); 12691cb0ef41Sopenharmony_ci __ CallCFunction(stack_check, num_arguments); 12701cb0ef41Sopenharmony_ci} 12711cb0ef41Sopenharmony_ci 12721cb0ef41Sopenharmony_ci 12731cb0ef41Sopenharmony_ci// Helper function for reading a value out of a stack frame. 12741cb0ef41Sopenharmony_citemplate <typename T> 12751cb0ef41Sopenharmony_cistatic T& frame_entry(Address re_frame, int frame_offset) { 12761cb0ef41Sopenharmony_ci return reinterpret_cast<T&>(Memory<int32_t>(re_frame + frame_offset)); 12771cb0ef41Sopenharmony_ci} 12781cb0ef41Sopenharmony_ci 12791cb0ef41Sopenharmony_ci 12801cb0ef41Sopenharmony_citemplate <typename T> 12811cb0ef41Sopenharmony_cistatic T* frame_entry_address(Address re_frame, int frame_offset) { 12821cb0ef41Sopenharmony_ci return reinterpret_cast<T*>(re_frame + frame_offset); 12831cb0ef41Sopenharmony_ci} 12841cb0ef41Sopenharmony_ci 12851cb0ef41Sopenharmony_ciint RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address, 12861cb0ef41Sopenharmony_ci Address raw_code, 12871cb0ef41Sopenharmony_ci Address re_frame) { 12881cb0ef41Sopenharmony_ci Code re_code = Code::cast(Object(raw_code)); 12891cb0ef41Sopenharmony_ci return NativeRegExpMacroAssembler::CheckStackGuardState( 12901cb0ef41Sopenharmony_ci frame_entry<Isolate*>(re_frame, kIsolate), 12911cb0ef41Sopenharmony_ci frame_entry<int>(re_frame, kStartIndex), 12921cb0ef41Sopenharmony_ci static_cast<RegExp::CallOrigin>(frame_entry<int>(re_frame, kDirectCall)), 12931cb0ef41Sopenharmony_ci return_address, re_code, 12941cb0ef41Sopenharmony_ci frame_entry_address<Address>(re_frame, kInputString), 12951cb0ef41Sopenharmony_ci frame_entry_address<const byte*>(re_frame, kInputStart), 12961cb0ef41Sopenharmony_ci frame_entry_address<const byte*>(re_frame, kInputEnd)); 12971cb0ef41Sopenharmony_ci} 12981cb0ef41Sopenharmony_ci 12991cb0ef41Sopenharmony_ci 13001cb0ef41Sopenharmony_ciOperand RegExpMacroAssemblerX64::register_location(int register_index) { 13011cb0ef41Sopenharmony_ci DCHECK(register_index < (1<<30)); 13021cb0ef41Sopenharmony_ci if (num_registers_ <= register_index) { 13031cb0ef41Sopenharmony_ci num_registers_ = register_index + 1; 13041cb0ef41Sopenharmony_ci } 13051cb0ef41Sopenharmony_ci return Operand(rbp, kRegisterZero - register_index * kSystemPointerSize); 13061cb0ef41Sopenharmony_ci} 13071cb0ef41Sopenharmony_ci 13081cb0ef41Sopenharmony_ci 13091cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckPosition(int cp_offset, 13101cb0ef41Sopenharmony_ci Label* on_outside_input) { 13111cb0ef41Sopenharmony_ci if (cp_offset >= 0) { 13121cb0ef41Sopenharmony_ci __ cmpl(rdi, Immediate(-cp_offset * char_size())); 13131cb0ef41Sopenharmony_ci BranchOrBacktrack(greater_equal, on_outside_input); 13141cb0ef41Sopenharmony_ci } else { 13151cb0ef41Sopenharmony_ci __ leaq(rax, Operand(rdi, cp_offset * char_size())); 13161cb0ef41Sopenharmony_ci __ cmpq(rax, Operand(rbp, kStringStartMinusOne)); 13171cb0ef41Sopenharmony_ci BranchOrBacktrack(less_equal, on_outside_input); 13181cb0ef41Sopenharmony_ci } 13191cb0ef41Sopenharmony_ci} 13201cb0ef41Sopenharmony_ci 13211cb0ef41Sopenharmony_ci 13221cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::BranchOrBacktrack(Condition condition, 13231cb0ef41Sopenharmony_ci Label* to) { 13241cb0ef41Sopenharmony_ci if (condition < 0) { // No condition 13251cb0ef41Sopenharmony_ci if (to == nullptr) { 13261cb0ef41Sopenharmony_ci Backtrack(); 13271cb0ef41Sopenharmony_ci return; 13281cb0ef41Sopenharmony_ci } 13291cb0ef41Sopenharmony_ci __ jmp(to); 13301cb0ef41Sopenharmony_ci return; 13311cb0ef41Sopenharmony_ci } 13321cb0ef41Sopenharmony_ci if (to == nullptr) { 13331cb0ef41Sopenharmony_ci __ j(condition, &backtrack_label_); 13341cb0ef41Sopenharmony_ci return; 13351cb0ef41Sopenharmony_ci } 13361cb0ef41Sopenharmony_ci __ j(condition, to); 13371cb0ef41Sopenharmony_ci} 13381cb0ef41Sopenharmony_ci 13391cb0ef41Sopenharmony_ci 13401cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::SafeCall(Label* to) { 13411cb0ef41Sopenharmony_ci __ call(to); 13421cb0ef41Sopenharmony_ci} 13431cb0ef41Sopenharmony_ci 13441cb0ef41Sopenharmony_ci 13451cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::SafeCallTarget(Label* label) { 13461cb0ef41Sopenharmony_ci __ bind(label); 13471cb0ef41Sopenharmony_ci __ subq(Operand(rsp, 0), code_object_pointer()); 13481cb0ef41Sopenharmony_ci} 13491cb0ef41Sopenharmony_ci 13501cb0ef41Sopenharmony_ci 13511cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::SafeReturn() { 13521cb0ef41Sopenharmony_ci __ addq(Operand(rsp, 0), code_object_pointer()); 13531cb0ef41Sopenharmony_ci __ ret(0); 13541cb0ef41Sopenharmony_ci} 13551cb0ef41Sopenharmony_ci 13561cb0ef41Sopenharmony_ci 13571cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::Push(Register source) { 13581cb0ef41Sopenharmony_ci DCHECK(source != backtrack_stackpointer()); 13591cb0ef41Sopenharmony_ci // Notice: This updates flags, unlike normal Push. 13601cb0ef41Sopenharmony_ci __ subq(backtrack_stackpointer(), Immediate(kIntSize)); 13611cb0ef41Sopenharmony_ci __ movl(Operand(backtrack_stackpointer(), 0), source); 13621cb0ef41Sopenharmony_ci} 13631cb0ef41Sopenharmony_ci 13641cb0ef41Sopenharmony_ci 13651cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::Push(Immediate value) { 13661cb0ef41Sopenharmony_ci // Notice: This updates flags, unlike normal Push. 13671cb0ef41Sopenharmony_ci __ subq(backtrack_stackpointer(), Immediate(kIntSize)); 13681cb0ef41Sopenharmony_ci __ movl(Operand(backtrack_stackpointer(), 0), value); 13691cb0ef41Sopenharmony_ci} 13701cb0ef41Sopenharmony_ci 13711cb0ef41Sopenharmony_ci 13721cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::FixupCodeRelativePositions() { 13731cb0ef41Sopenharmony_ci for (int position : code_relative_fixup_positions_) { 13741cb0ef41Sopenharmony_ci // The position succeeds a relative label offset from position. 13751cb0ef41Sopenharmony_ci // Patch the relative offset to be relative to the Code object pointer 13761cb0ef41Sopenharmony_ci // instead. 13771cb0ef41Sopenharmony_ci int patch_position = position - kIntSize; 13781cb0ef41Sopenharmony_ci int offset = masm_.long_at(patch_position); 13791cb0ef41Sopenharmony_ci masm_.long_at_put(patch_position, 13801cb0ef41Sopenharmony_ci offset 13811cb0ef41Sopenharmony_ci + position 13821cb0ef41Sopenharmony_ci + Code::kHeaderSize 13831cb0ef41Sopenharmony_ci - kHeapObjectTag); 13841cb0ef41Sopenharmony_ci } 13851cb0ef41Sopenharmony_ci code_relative_fixup_positions_.Rewind(0); 13861cb0ef41Sopenharmony_ci} 13871cb0ef41Sopenharmony_ci 13881cb0ef41Sopenharmony_ci 13891cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::Push(Label* backtrack_target) { 13901cb0ef41Sopenharmony_ci __ subq(backtrack_stackpointer(), Immediate(kIntSize)); 13911cb0ef41Sopenharmony_ci __ movl(Operand(backtrack_stackpointer(), 0), backtrack_target); 13921cb0ef41Sopenharmony_ci MarkPositionForCodeRelativeFixup(); 13931cb0ef41Sopenharmony_ci} 13941cb0ef41Sopenharmony_ci 13951cb0ef41Sopenharmony_ci 13961cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::Pop(Register target) { 13971cb0ef41Sopenharmony_ci DCHECK(target != backtrack_stackpointer()); 13981cb0ef41Sopenharmony_ci __ movsxlq(target, Operand(backtrack_stackpointer(), 0)); 13991cb0ef41Sopenharmony_ci // Notice: This updates flags, unlike normal Pop. 14001cb0ef41Sopenharmony_ci __ addq(backtrack_stackpointer(), Immediate(kIntSize)); 14011cb0ef41Sopenharmony_ci} 14021cb0ef41Sopenharmony_ci 14031cb0ef41Sopenharmony_ci 14041cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::Drop() { 14051cb0ef41Sopenharmony_ci __ addq(backtrack_stackpointer(), Immediate(kIntSize)); 14061cb0ef41Sopenharmony_ci} 14071cb0ef41Sopenharmony_ci 14081cb0ef41Sopenharmony_ci 14091cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckPreemption() { 14101cb0ef41Sopenharmony_ci // Check for preemption. 14111cb0ef41Sopenharmony_ci Label no_preempt; 14121cb0ef41Sopenharmony_ci ExternalReference stack_limit = 14131cb0ef41Sopenharmony_ci ExternalReference::address_of_jslimit(isolate()); 14141cb0ef41Sopenharmony_ci __ load_rax(stack_limit); 14151cb0ef41Sopenharmony_ci __ cmpq(rsp, rax); 14161cb0ef41Sopenharmony_ci __ j(above, &no_preempt); 14171cb0ef41Sopenharmony_ci 14181cb0ef41Sopenharmony_ci SafeCall(&check_preempt_label_); 14191cb0ef41Sopenharmony_ci 14201cb0ef41Sopenharmony_ci __ bind(&no_preempt); 14211cb0ef41Sopenharmony_ci} 14221cb0ef41Sopenharmony_ci 14231cb0ef41Sopenharmony_ci 14241cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::CheckStackLimit() { 14251cb0ef41Sopenharmony_ci Label no_stack_overflow; 14261cb0ef41Sopenharmony_ci ExternalReference stack_limit = 14271cb0ef41Sopenharmony_ci ExternalReference::address_of_regexp_stack_limit_address(isolate()); 14281cb0ef41Sopenharmony_ci __ load_rax(stack_limit); 14291cb0ef41Sopenharmony_ci __ cmpq(backtrack_stackpointer(), rax); 14301cb0ef41Sopenharmony_ci __ j(above, &no_stack_overflow); 14311cb0ef41Sopenharmony_ci 14321cb0ef41Sopenharmony_ci SafeCall(&stack_overflow_label_); 14331cb0ef41Sopenharmony_ci 14341cb0ef41Sopenharmony_ci __ bind(&no_stack_overflow); 14351cb0ef41Sopenharmony_ci} 14361cb0ef41Sopenharmony_ci 14371cb0ef41Sopenharmony_ci 14381cb0ef41Sopenharmony_civoid RegExpMacroAssemblerX64::LoadCurrentCharacterUnchecked(int cp_offset, 14391cb0ef41Sopenharmony_ci int characters) { 14401cb0ef41Sopenharmony_ci if (mode_ == LATIN1) { 14411cb0ef41Sopenharmony_ci if (characters == 4) { 14421cb0ef41Sopenharmony_ci __ movl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); 14431cb0ef41Sopenharmony_ci } else if (characters == 2) { 14441cb0ef41Sopenharmony_ci __ movzxwl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); 14451cb0ef41Sopenharmony_ci } else { 14461cb0ef41Sopenharmony_ci DCHECK_EQ(1, characters); 14471cb0ef41Sopenharmony_ci __ movzxbl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); 14481cb0ef41Sopenharmony_ci } 14491cb0ef41Sopenharmony_ci } else { 14501cb0ef41Sopenharmony_ci DCHECK(mode_ == UC16); 14511cb0ef41Sopenharmony_ci if (characters == 2) { 14521cb0ef41Sopenharmony_ci __ movl(current_character(), 14531cb0ef41Sopenharmony_ci Operand(rsi, rdi, times_1, cp_offset * sizeof(base::uc16))); 14541cb0ef41Sopenharmony_ci } else { 14551cb0ef41Sopenharmony_ci DCHECK_EQ(1, characters); 14561cb0ef41Sopenharmony_ci __ movzxwl(current_character(), 14571cb0ef41Sopenharmony_ci Operand(rsi, rdi, times_1, cp_offset * sizeof(base::uc16))); 14581cb0ef41Sopenharmony_ci } 14591cb0ef41Sopenharmony_ci } 14601cb0ef41Sopenharmony_ci} 14611cb0ef41Sopenharmony_ci 14621cb0ef41Sopenharmony_ci#undef __ 14631cb0ef41Sopenharmony_ci 14641cb0ef41Sopenharmony_ci} // namespace internal 14651cb0ef41Sopenharmony_ci} // namespace v8 14661cb0ef41Sopenharmony_ci 14671cb0ef41Sopenharmony_ci#endif // V8_TARGET_ARCH_X64 1468