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