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