1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_ARM) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "unicode.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "log.h" 34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "code-stubs.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "regexp-stack.h" 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "macro-assembler.h" 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "regexp-macro-assembler.h" 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "arm/regexp-macro-assembler-arm.h" 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifndef V8_INTERPRETED_REGEXP 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * This assembler uses the following register assignment convention 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r5 : Pointer to current code object (Code*) including heap object tag. 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r6 : Current position in input, as negative offset from end of string. 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Please notice that this is the byte offset, not the character offset! 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r7 : Currently loaded character. Must be loaded using 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * LoadCurrentCharacter before using any of the dispatch methods. 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r8 : points to tip of backtrack stack 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r9 : Unused, might be used by C code and expected unchanged. 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r10 : End of input (points to byte after last character in input). 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r11 : Frame pointer. Used to access arguments, local variables and 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * RegExp registers. 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r12 : IP register, used by assembler. Very volatile. 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r13/sp : points to tip of C stack. 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The remaining registers are free for computations. 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Each call to a public method should retain this convention. 61e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The stack will have the following structure: 6344f0eee88ff00398ff7f715fab053374d808c90dSteve Block * - fp[52] Isolate* isolate (Address of the current isolate) 64e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - fp[48] direct_call (if 1, direct call from JavaScript code, 65e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * if 0, call through the runtime system). 66e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - fp[44] stack_area_base (High end of the memory area to use as 67e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * backtracking stack). 68e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - fp[40] int* capture_array (int[num_saved_registers_], for output). 69e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - fp[36] secondary link/return address used by native call. 70e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * --- sp when called --- 71e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - fp[32] return address (lr). 72e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - fp[28] old frame pointer (r11). 73e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - fp[0..24] backup of registers r4..r10. 74e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * --- frame pointer ---- 75e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - fp[-4] end of input (Address of end of string). 76e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - fp[-8] start of input (Address of first character in string). 77e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - fp[-12] start index (character index of start). 78e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - fp[-16] void* input_string (location of a handle containing the string). 79e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - fp[-20] Offset of location before start of input (effectively character 80e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * position -1). Used to initialize capture registers to a 81e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * non-position. 82e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - fp[-24] At start (if 1, we are starting at the start of the 83e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * string, otherwise 0) 84e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - fp[-28] register 0 (Only positions must be stored in the first 85e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - register 1 num_saved_registers_ registers) 86e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - ... 87e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * - register num_registers-1 88e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * --- sp --- 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The first num_saved_registers_ registers are initialized to point to 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * "character -1" in the string (i.e., char_size() bytes before the first 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * character of the string). The remaining registers start out as garbage. 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The data up to the return address must be placed there by the calling 95e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * code and the remaining arguments are passed in registers, e.g. by calling the 96e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * code entry as cast to a function with the signature: 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * int (*match)(String* input_string, 98e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * int start_index, 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Address start, 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Address end, 101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * Address secondary_return_address, // Only used by native call. 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * int* capture_output_array, 103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * byte* stack_area_base, 104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * bool direct_call = false) 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The call is performed by NativeRegExpMacroAssembler::Execute() 106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro 107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * in arm/simulator-arm.h. 108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * When calling as a non-direct call (i.e., from C++ code), the return address 109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * area is overwritten with the LR register by the RegExp code. When doing a 110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * direct call from generated code, the return address is placed there by 111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch * the calling code, as in a normal exit frame. 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */ 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm_) 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssemblerARM::RegExpMacroAssemblerARM( 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Mode mode, 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int registers_to_save) 1198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : masm_(new MacroAssembler(Isolate::Current(), NULL, kRegExpCodeSize)), 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mode_(mode), 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_registers_(registers_to_save), 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_saved_registers_(registers_to_save), 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block entry_label_(), 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block start_label_(), 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block success_label_(), 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_label_(), 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block exit_label_() { 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, registers_to_save % 2); 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&entry_label_); // We'll write the entry code later. 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EmitBacktrackConstantPool(); 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&start_label_); // And then continue from here. 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssemblerARM::~RegExpMacroAssemblerARM() { 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete masm_; 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Unuse labels in case we throw away the assembler without calling GetCode. 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block entry_label_.Unuse(); 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block start_label_.Unuse(); 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block success_label_.Unuse(); 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_label_.Unuse(); 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block exit_label_.Unuse(); 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block check_preempt_label_.Unuse(); 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_overflow_label_.Unuse(); 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerARM::stack_limit_slack() { 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RegExpStack::kStackLimitSlack; 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::AdvanceCurrentPosition(int by) { 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (by != 0) { 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(current_input_offset(), 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current_input_offset(), Operand(by * char_size())); 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::AdvanceRegister(int reg, int by) { 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg >= 0); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg < num_registers_); 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (by != 0) { 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, register_location(reg)); 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(by)); 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, register_location(reg)); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::Backtrack() { 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPreemption(); 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop Code* offset from backtrack stack, add Code* and jump to location. 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(r0); 1766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(pc, r0, Operand(code_pointer())); 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::Bind(Label* label) { 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(label); 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckCharacter(uint32_t c, Label* on_equal) { 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), Operand(c)); 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(eq, on_equal); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckCharacterGT(uc16 limit, Label* on_greater) { 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), Operand(limit)); 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(gt, on_greater); 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckAtStart(Label* on_at_start) { 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label not_at_start; 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Did we start the match at the start of the string at all? 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(frame_pointer(), kAtStart)); 2019ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ cmp(r0, Operand(0, RelocInfo::NONE)); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(eq, ¬_at_start); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we did, are we still at the start of the input? 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(frame_pointer(), kInputStart)); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, end_of_input_address(), Operand(current_input_offset())); 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r1); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(eq, on_at_start); 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(¬_at_start); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckNotAtStart(Label* on_not_at_start) { 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Did we start the match at the start of the string at all? 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(frame_pointer(), kAtStart)); 2169ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ cmp(r0, Operand(0, RelocInfo::NONE)); 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(eq, on_not_at_start); 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we did, are we still at the start of the input? 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(frame_pointer(), kInputStart)); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, end_of_input_address(), Operand(current_input_offset())); 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r1); 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(ne, on_not_at_start); 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckCharacterLT(uc16 limit, Label* on_less) { 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), Operand(limit)); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(lt, on_less); 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckCharacters(Vector<const uc16> str, 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int cp_offset, 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_failure, 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool check_end_of_string) { 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (on_failure == NULL) { 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instead of inlining a backtrack for each test, (re)use the global 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // backtrack target. 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block on_failure = &backtrack_label_; 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_end_of_string) { 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Is last character of required match inside string. 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPosition(cp_offset + str.length() - 1, on_failure); 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, end_of_input_address(), Operand(current_input_offset())); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (cp_offset != 0) { 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int byte_offset = cp_offset * char_size(); 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(byte_offset)); 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0 : Address of characters to match against str. 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int stored_high_byte = 0; 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < str.length(); i++) { 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(r1, MemOperand(r0, char_size(), PostIndex)); 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(str[i] <= String::kMaxAsciiCharCode); 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r1, Operand(str[i])); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrh(r1, MemOperand(r0, char_size(), PostIndex)); 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 match_char = str[i]; 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int match_high_byte = (match_char >> 8); 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (match_high_byte == 0) { 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r1, Operand(str[i])); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (match_high_byte != stored_high_byte) { 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(match_high_byte)); 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stored_high_byte = match_high_byte; 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r3, r2, Operand(match_char & 0xff)); 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r1, r3); 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(ne, on_failure); 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckGreedyLoop(Label* on_equal) { 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(backtrack_stackpointer(), 0)); 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_input_offset(), r0); 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(backtrack_stackpointer(), 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_stackpointer(), Operand(kPointerSize), LeaveCC, eq); 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(eq, on_equal); 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckNotBackReferenceIgnoreCase( 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_reg, 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, register_location(start_reg)); // Index of start of capture 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, register_location(start_reg + 1)); // Index of end of capture 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r1, r1, r0, SetCC); // Length of capture. 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If length is zero, either the capture is empty or it is not participating. 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // In either case succeed immediately. 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &fallthrough); 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that there are enough characters left in the input. 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmn(r1, Operand(current_input_offset())); 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(gt, on_no_match); 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label success; 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fail; 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop_check; 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0 - offset of start of capture 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1 - length of capture 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(end_of_input_address())); 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, end_of_input_address(), Operand(current_input_offset())); 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r1, r0, Operand(r1)); 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0 - Address of start of capture. 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1 - Address of end of capture 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2 - Address of current input position. 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop; 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(r3, MemOperand(r0, char_size(), PostIndex)); 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(r4, MemOperand(r2, char_size(), PostIndex)); 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r4, r3); 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &loop_check); 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mismatch, try case-insensitive match (converting letters to lower-case). 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ orr(r3, r3, Operand(0x20)); // Convert capture character to lower-case. 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ orr(r4, r4, Operand(0x20)); // Also convert input character. 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r4, r3); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &fail); 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r3, r3, Operand('a')); 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r3, Operand('z' - 'a')); // Is r3 a lowercase letter? 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(hi, &fail); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop_check); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r1); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &loop); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&success); 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fail); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(al, on_no_match); 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success); 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute new value of character position after the matched part. 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(current_input_offset(), r2, end_of_input_address()); 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 3508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int argument_count = 4; 3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ PrepareCallCFunction(argument_count, r2); 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0 - offset of start of capture 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1 - length of capture 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Put arguments into arguments registers. 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Parameters are 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0: Address byte_offset1 - Address captured substring's start. 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1: Address byte_offset2 - Address of current character position. 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r2: size_t byte_length - length of capture in bytes(!) 3618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // r3: Isolate* isolate 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Address of start of capture. 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(end_of_input_address())); 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Length of capture. 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(r1)); 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save length in callee-save register for use on return. 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r4, Operand(r1)); 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Address of current input position. 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r1, current_input_offset(), Operand(end_of_input_address())); 3718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Isolate. 3728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ mov(r3, Operand(ExternalReference::isolate_address())); 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm_); 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference function = 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate()); 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(function, argument_count); 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if function returned non-zero for success or zero for failure. 3829ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ cmp(r0, Operand(0, RelocInfo::NONE)); 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(eq, on_no_match); 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // On success, increment position by length of capture. 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(current_input_offset(), current_input_offset(), Operand(r4)); 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckNotBackReference( 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_reg, 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label success; 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find length of back-referenced capture. 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, register_location(start_reg)); 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, register_location(start_reg + 1)); 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r1, r1, r0, SetCC); // Length to check. 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Succeed on empty capture (including no capture). 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &fallthrough); 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that there are enough characters left in the input. 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmn(r1, Operand(current_input_offset())); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(gt, on_no_match); 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute pointers to match string and capture string 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, r0, Operand(end_of_input_address())); 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, end_of_input_address(), Operand(current_input_offset())); 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r1, r1, Operand(r0)); 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop; 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(r3, MemOperand(r0, char_size(), PostIndex)); 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrb(r4, MemOperand(r2, char_size(), PostIndex)); 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrh(r3, MemOperand(r0, char_size(), PostIndex)); 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldrh(r4, MemOperand(r2, char_size(), PostIndex)); 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r3, r4); 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(ne, on_no_match); 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r1); 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(lt, &loop); 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move current character position to position after match. 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(current_input_offset(), r2, end_of_input_address()); 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckNotRegistersEqual(int reg1, 436b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int reg2, 437b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* on_not_equal) { 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, register_location(reg1)); 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, register_location(reg2)); 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, r1); 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(ne, on_not_equal); 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 445b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid RegExpMacroAssemblerARM::CheckNotCharacter(unsigned c, 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), Operand(c)); 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(ne, on_not_equal); 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckCharacterAfterAnd(uint32_t c, 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t mask, 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_equal) { 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(r0, current_character(), Operand(mask)); 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(c)); 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(eq, on_equal); 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 461b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid RegExpMacroAssemblerARM::CheckNotCharacterAfterAnd(unsigned c, 462b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch unsigned mask, 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(r0, current_character(), Operand(mask)); 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(c)); 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(ne, on_not_equal); 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckNotCharacterAfterMinusAnd( 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 c, 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 minus, 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 mask, 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(minus < String::kMaxUtf16CodeUnit); 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, current_character(), Operand(minus)); 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(r0, r0, Operand(mask)); 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(c)); 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(ne, on_not_equal); 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpMacroAssemblerARM::CheckSpecialCharacterClass(uc16 type, 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Range checks (c in min..max) are generally implemented by an unsigned 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (c - min) <= (max - min) check 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (type) { 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 's': 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match space-characters 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ASCII space characters are '\t'..'\r' and ' '. 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label success; 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), Operand(' ')); 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &success); 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check range 0x09..0x0d 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, current_character(), Operand('\t')); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand('\r' - '\t')); 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(hi, on_no_match); 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success); 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'S': 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non-space characters. 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ASCII space characters are '\t'..'\r' and ' '. 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), Operand(' ')); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(eq, on_no_match); 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, current_character(), Operand('\t')); 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand('\r' - '\t')); 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(ls, on_no_match); 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'd': 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match ASCII digits ('0'..'9') 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, current_character(), Operand('0')); 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), Operand('9' - '0')); 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(hi, on_no_match); 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'D': 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non ASCII-digits 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, current_character(), Operand('0')); 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand('9' - '0')); 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(ls, on_no_match); 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case '.': { 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ eor(r0, current_character(), Operand(0x01)); 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, r0, Operand(0x0b)); 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(0x0c - 0x0b)); 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(ls, on_no_match); 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == UC16) { 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare original value to 0x2028 and 0x2029, using the already 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // computed (current_char ^ 0x01 - 0x0b). I.e., check for 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 0x201d (0x2028 - 0x0b) or 0x201e. 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, r0, Operand(0x2028 - 0x0b)); 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(1)); 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(ls, on_no_match); 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 544e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'n': { 545e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) 546e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ eor(r0, current_character(), Operand(0x01)); 547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 548e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ sub(r0, r0, Operand(0x0b)); 549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(r0, Operand(0x0c - 0x0b)); 550e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ == ASCII) { 551e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(hi, on_no_match); 552e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(ls, &done); 555e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Compare original value to 0x2028 and 0x2029, using the already 556e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // computed (current_char ^ 0x01 - 0x0b). I.e., check for 557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // 0x201d (0x2028 - 0x0b) or 0x201e. 558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ sub(r0, r0, Operand(0x2028 - 0x0b)); 559e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(r0, Operand(1)); 560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(hi, on_no_match); 561e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&done); 562e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 564e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'w': { 566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ != ASCII) { 567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Table is 128 entries, so all ASCII characters can be tested. 568e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(current_character(), Operand('z')); 569e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(hi, on_no_match); 570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 571e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference map = ExternalReference::re_word_character_map(); 572e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r0, Operand(map)); 573e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldrb(r0, MemOperand(r0, current_character())); 5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(0)); 575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(eq, on_no_match); 576e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'W': { 579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ != ASCII) { 581e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Table is 128 entries, so all ASCII characters can be tested. 582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(current_character(), Operand('z')); 583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ b(hi, &done); 584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference map = ExternalReference::re_word_character_map(); 586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ mov(r0, Operand(map)); 587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ ldrb(r0, MemOperand(r0, current_character())); 5883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r0, Operand(0)); 589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(ne, on_no_match); 590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ != ASCII) { 591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&done); 592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case '*': 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match any character. 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // No custom implementation (yet): s(UC16), S(UC16). 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::Fail() { 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(FAILURE)); 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 611053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve BlockHandle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) { 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Finalize code - write the entry point code now we know how many 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // registers we need. 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Entry code: 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry_label_); 6173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Tell the system that we have a stack frame. Because the type is MANUAL, no 6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // is generated. 6203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm_, StackFrame::MANUAL); 6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Actually emit code to start a new stack frame. 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push arguments 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save callee-save registers. 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Start new stack frame. 626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Store link register in existing stack-cell. 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Order here should correspond to order of offset constants in header file. 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegList registers_to_retain = r4.bit() | r5.bit() | r6.bit() | 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block r7.bit() | r8.bit() | r9.bit() | r10.bit() | fp.bit(); 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegList argument_registers = r0.bit() | r1.bit() | r2.bit() | r3.bit(); 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ stm(db_w, sp, argument_registers | registers_to_retain | lr.bit()); 632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Set frame pointer in space for it if this is not a direct call 633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // from generated code. 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(frame_pointer(), sp, Operand(4 * kPointerSize)); 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r0); // Make room for "position - 1" constant (value is irrelevant). 636d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(r0); // Make room for "at start" constant (value is irrelevant). 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if we have space on the stack for registers. 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label stack_limit_hit; 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label stack_ok; 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 641d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 64244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::address_of_stack_limit(masm_->isolate()); 643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r0, Operand(stack_limit)); 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(r0)); 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, sp, r0, SetCC); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle it if the stack pointer is already below the stack limit. 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ls, &stack_limit_hit); 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if there is room for the variable number of registers above 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the stack limit. 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(num_registers_ * kPointerSize)); 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(hs, &stack_ok); 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit with OutOfMemory exception. There is not enough space on the stack 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for our working registers. 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(EXCEPTION)); 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&stack_limit_hit); 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCheckStackGuardState(r0); 6599ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ cmp(r0, Operand(0, RelocInfo::NONE)); 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If returned value is non-zero, we exit with the returned value as result. 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &exit_label_); 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&stack_ok); 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate space on stack for registers. 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(sp, sp, Operand(num_registers_ * kPointerSize)); 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load string end. 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load input start. 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(frame_pointer(), kInputStart)); 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find negative length (offset of start relative to end). 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(current_input_offset(), r0, end_of_input_address()); 6736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Set r0 to address of char before start of the input string 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (effectively string position -1). 6756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r1, MemOperand(frame_pointer(), kStartIndex)); 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, current_input_offset(), Operand(char_size())); 6776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ sub(r0, r0, Operand(r1, LSL, (mode_ == UC16) ? 1 : 0)); 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store this value in a local variable, for use when clearing 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // position registers. 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, MemOperand(frame_pointer(), kInputStartMinusOne)); 681d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 682d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Determine whether the start index is zero, that is at the start of the 683d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // string, and store that value in a local variable. 6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(r1, Operand(0)); 685d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ mov(r1, Operand(1), LeaveCC, eq); 6869ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ mov(r1, Operand(0, RelocInfo::NONE), LeaveCC, ne); 687d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ str(r1, MemOperand(frame_pointer(), kAtStart)); 688d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill saved registers with initial value = start offset - 1 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Address of register 0. 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r1, frame_pointer(), Operand(kRegisterZero)); 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, Operand(num_saved_registers_)); 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label init_loop; 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&init_loop); 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, MemOperand(r1, kPointerSize, NegPostIndex)); 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r2, r2, Operand(1), SetCC); 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &init_loop); 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize backtrack stack pointer. 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd)); 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize code pointer register 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(code_pointer(), Operand(masm_->CodeObject())); 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load previous char as initial value of current character register. 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label at_start; 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(frame_pointer(), kAtStart)); 7099ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ cmp(r0, Operand(0, RelocInfo::NONE)); 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &at_start); 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(-1, 1); // Load previous char. 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&start_label_); 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&at_start); 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(current_character(), Operand('\n')); 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&start_label_); 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit code: 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (success_label_.is_linked()) { 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save captures when successful. 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success_label_); 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_saved_registers_ > 0) { 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // copy captures to output 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(frame_pointer(), kInputStart)); 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(frame_pointer(), kRegisterOutput)); 7266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ ldr(r2, MemOperand(frame_pointer(), kStartIndex)); 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r1, end_of_input_address(), r1); 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1 is length of input in bytes. 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == UC16) { 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r1, Operand(r1, LSR, 1)); 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r1 is length of input in characters. 7336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ add(r1, r1, Operand(r2)); 7346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // r1 is length of string in characters. 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, num_saved_registers_ % 2); 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Always an even number of capture registers. This allows us to 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // unroll the loop once to add an operation between a load of a register 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and the following use of that register. 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < num_saved_registers_; i += 2) { 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r2, register_location(i)); 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r3, register_location(i + 1)); 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == UC16) { 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, r1, Operand(r2, ASR, 1)); 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r3, r1, Operand(r3, ASR, 1)); 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r2, r1, Operand(r2)); 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r3, r1, Operand(r3)); 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r2, MemOperand(r0, kPointerSize, PostIndex)); 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r3, MemOperand(r0, kPointerSize, PostIndex)); 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(SUCCESS)); 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit and return r0 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit_label_); 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip sp past regexp registers and local variables.. 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(sp, frame_pointer()); 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore registers r4..r11 and return (restoring lr to pc). 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldm(ia_w, sp, registers_to_retain | pc.bit()); 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Backtrack code (branch target for conditional backtracks). 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (backtrack_label_.is_linked()) { 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&backtrack_label_); 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Backtrack(); 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label exit_with_exception; 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preempt-code 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_preempt_label_.is_linked()) { 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCallTarget(&check_preempt_label_); 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCheckStackGuardState(r0); 7769ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ cmp(r0, Operand(0, RelocInfo::NONE)); 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If returning non-zero, we should end execution with the given 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result as return value. 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(ne, &exit_label_); 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // String might have moved: Reload end of string from frame. 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeReturn(); 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Backtrack stack overflow code. 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (stack_overflow_label_.is_linked()) { 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCallTarget(&stack_overflow_label_); 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reached if the backtrack-stack limit has been hit. 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label grow_failed; 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 792e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Call GrowStack(backtrack_stackpointer(), &stack_base) 7938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static const int num_arguments = 3; 7946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ PrepareCallCFunction(num_arguments, r0); 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, backtrack_stackpointer()); 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r1, frame_pointer(), Operand(kStackHighEnd)); 7978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ mov(r2, Operand(ExternalReference::isolate_address())); 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference grow_stack = 79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::re_grow_stack(masm_->isolate()); 8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallCFunction(grow_stack, num_arguments); 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If return NULL, we have failed to grow the stack, and 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // must exit with a stack-overflow exception. 8039ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick __ cmp(r0, Operand(0, RelocInfo::NONE)); 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(eq, &exit_with_exception); 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Otherwise use return value as new stack pointer. 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(backtrack_stackpointer(), r0); 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore saved registers and continue. 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeReturn(); 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (exit_with_exception.is_linked()) { 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If any of the code above needed to exit with an exception. 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit_with_exception); 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit with Result EXCEPTION(-1) to signal thrown exception. 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(EXCEPTION)); 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CodeDesc code_desc; 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm_->GetCode(&code_desc); 82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> code = FACTORY->NewCode(code_desc, 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::ComputeFlags(Code::REGEXP), 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm_->CodeObject()); 82444f0eee88ff00398ff7f715fab053374d808c90dSteve Block PROFILE(Isolate::Current(), RegExpCodeCreateEvent(*code, *source)); 825053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block return Handle<HeapObject>::cast(code); 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::GoTo(Label* to) { 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(al, to); 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::IfRegisterGE(int reg, 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int comparand, 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_ge) { 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, register_location(reg)); 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(comparand)); 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(ge, if_ge); 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::IfRegisterLT(int reg, 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int comparand, 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_lt) { 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, register_location(reg)); 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(comparand)); 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(lt, if_lt); 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::IfRegisterEqPos(int reg, 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_eq) { 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, register_location(reg)); 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(r0, Operand(current_input_offset())); 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(eq, if_eq); 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssembler::IrregexpImplementation 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegExpMacroAssemblerARM::Implementation() { 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return kARMImplementation; 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::LoadCurrentCharacter(int cp_offset, 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_end_of_input, 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool check_bounds, 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int characters) { 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_bounds) { 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPosition(cp_offset + characters - 1, on_end_of_input); 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(cp_offset, characters); 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::PopCurrentPosition() { 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(current_input_offset()); 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::PopRegister(int register_index) { 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(r0); 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, register_location(register_index)); 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool is_valid_memory_offset(int value) { 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (value < 0) value = -value; 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return value < (1<<12); 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::PushBacktrack(Label* label) { 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (label->is_bound()) { 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int target = label->pos(); 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(target + Code::kHeaderSize - kHeapObjectTag)); 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int constant_offset = GetBacktrackConstantPoolEntry(); 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm_->label_at_put(label, constant_offset); 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reading pc-relative is based on the address 8 bytes ahead of 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the current opcode. 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned int offset_of_pc_register_read = 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm_->pc_offset() + Assembler::kPcLoadDelta; 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int pc_offset_of_constant = 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block constant_offset - offset_of_pc_register_read; 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(pc_offset_of_constant < 0); 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (is_valid_memory_offset(pc_offset_of_constant)) { 9113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(pc, pc_offset_of_constant)); 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Not a 12-bit offset, so it needs to be loaded from the constant 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // pool. 9163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(pc_offset_of_constant + Assembler::kInstrSize)); 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(pc, r0)); 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(r0); 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckStackLimit(); 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::PushCurrentPosition() { 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(current_input_offset()); 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::PushRegister(int register_index, 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackCheckFlag check_stack_limit) { 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, register_location(register_index)); 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(r0); 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_stack_limit) CheckStackLimit(); 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::ReadCurrentPositionFromRegister(int reg) { 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(current_input_offset(), register_location(reg)); 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::ReadStackPointerFromRegister(int reg) { 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(backtrack_stackpointer(), register_location(reg)); 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(frame_pointer(), kStackHighEnd)); 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(backtrack_stackpointer(), backtrack_stackpointer(), Operand(r0)); 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 951f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid RegExpMacroAssemblerARM::SetCurrentPositionFromEnd(int by) { 952f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Label after_position; 953f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ cmp(current_input_offset(), Operand(-by * char_size())); 954f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ b(ge, &after_position); 955f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(current_input_offset(), Operand(-by * char_size())); 956f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // On RegExp code entry (where this operation is used), the character before 957f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // the current position is expected to be already loaded. 958f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // We have advanced the position, so it's safe to read backwards. 959f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch LoadCurrentCharacterUnchecked(-1, 1); 960f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&after_position); 961f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 962f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 963f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::SetRegister(int register_index, int to) { 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(register_index >= num_saved_registers_); // Reserved for positions! 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, Operand(to)); 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, register_location(register_index)); 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::Succeed() { 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&success_label_); 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::WriteCurrentPositionToRegister(int reg, 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int cp_offset) { 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (cp_offset == 0) { 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(current_input_offset(), register_location(reg)); 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, current_input_offset(), Operand(cp_offset * char_size())); 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, register_location(reg)); 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::ClearRegisters(int reg_from, int reg_to) { 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg_from <= reg_to); 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(frame_pointer(), kInputStartMinusOne)); 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int reg = reg_from; reg <= reg_to; reg++) { 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, register_location(reg)); 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::WriteStackPointerToRegister(int reg) { 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r1, MemOperand(frame_pointer(), kStackHighEnd)); 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(r0, backtrack_stackpointer(), r1); 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(r0, register_location(reg)); 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Private methods: 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CallCheckStackGuardState(Register scratch) { 10066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int num_arguments = 3; 10076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ PrepareCallCFunction(num_arguments, scratch); 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // RegExp code frame pointer. 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r2, frame_pointer()); 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Code* of self. 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r1, Operand(masm_->CodeObject())); 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r0 becomes return address pointer. 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference stack_guard_check = 101444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::re_check_stack_guard_state(masm_->isolate()); 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCFunctionUsingStub(stack_guard_check, num_arguments); 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper function for reading a value out of a stack frame. 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate <typename T> 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic T& frame_entry(Address re_frame, int frame_offset) { 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset)); 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address, 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* re_code, 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address re_frame) { 102944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate); 103044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(isolate == Isolate::Current()); 103144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (isolate->stack_guard()->IsStackOverflow()) { 103244f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate->StackOverflow(); 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return EXCEPTION; 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If not real stack overflow the stack guard was used to interrupt 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // execution for another purpose. 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // If this is a direct call from JavaScript retry the RegExp forcing the call 10406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // through the runtime system. Currently the direct call cannot handle a GC. 10416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (frame_entry<int>(re_frame, kDirectCall) == 1) { 10426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return RETRY; 10436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 10446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Prepare for possible GC. 104669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HandleScope handles(isolate); 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code_handle(re_code); 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); 105069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Current string. 105269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch bool is_ascii = subject->IsAsciiRepresentationUnderneath(); 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(re_code->instruction_start() <= *return_address); 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(*return_address <= 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block re_code->instruction_start() + re_code->instruction_size()); 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate); 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*code_handle != re_code) { // Return address no longer valid 106169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int delta = code_handle->address() - re_code->address(); 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Overwrite the return address on the stack. 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *return_address += delta; 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result->IsException()) { 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return EXCEPTION; 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 107069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Handle<String> subject_tmp = subject; 107169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int slice_offset = 0; 107269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 107369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Extract the underlying string and the slice offset. 107469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (StringShape(*subject_tmp).IsCons()) { 107569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); 107669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (StringShape(*subject_tmp).IsSliced()) { 107769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch SlicedString* slice = SlicedString::cast(*subject_tmp); 107869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch subject_tmp = Handle<String>(slice->parent()); 107969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch slice_offset = slice->offset(); 108069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 108169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // String might have changed. 108369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (subject_tmp->IsAsciiRepresentation() != is_ascii) { 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we changed between an ASCII and an UC16 string, the specialized 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code cannot be used, and we need to restart regexp matching from 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch (including, potentially, compiling a new version of the code). 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RETRY; 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Otherwise, the content of the string might have moved. It must still 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // be a sequential or external string with the same content. 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the start and end pointers in the stack frame to the current 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // location (whether it has actually moved or not). 109469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ASSERT(StringShape(*subject_tmp).IsSequential() || 109569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch StringShape(*subject_tmp).IsExternal()); 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The original start address of the characters to match. 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart); 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find the current start address of the same character at the current string 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // position. 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_index = frame_entry<int>(re_frame, kStartIndex); 110369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch const byte* new_address = StringCharacterPosition(*subject_tmp, 110469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch start_index + slice_offset); 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (start_address != new_address) { 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If there is a difference, update the object pointer and start and end 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // addresses in the RegExp stack frame to match the new value. 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd); 111069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int byte_length = static_cast<int>(end_address - start_address); 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const String*>(re_frame, kInputString) = *subject; 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const byte*>(re_frame, kInputStart) = new_address; 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length; 11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (frame_entry<const String*>(re_frame, kInputString) != *subject) { 11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Subject string might have been a ConsString that underwent 11163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // short-circuiting during GC. That will not change start_address but 11173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // will change pointer inside the subject handle. 11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_entry<const String*>(re_frame, kInputString) = *subject; 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 0; 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMemOperand RegExpMacroAssemblerARM::register_location(int register_index) { 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(register_index < (1<<30)); 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_registers_ <= register_index) { 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_registers_ = register_index + 1; 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return MemOperand(frame_pointer(), 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block kRegisterZero - register_index * kPointerSize); 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckPosition(int cp_offset, 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_outside_input) { 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_input_offset(), Operand(-cp_offset * char_size())); 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(ge, on_outside_input); 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::BranchOrBacktrack(Condition condition, 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* to) { 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (condition == al) { // Unconditional. 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (to == NULL) { 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Backtrack(); 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(to); 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (to == NULL) { 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(condition, &backtrack_label_); 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ b(condition, to); 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::SafeCall(Label* to, Condition cond) { 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bl(to, cond); 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::SafeReturn() { 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(lr); 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(pc, lr, Operand(masm_->CodeObject())); 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::SafeCallTarget(Label* name) { 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(name); 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(lr, lr, Operand(masm_->CodeObject())); 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(lr); 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::Push(Register source) { 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!source.is(backtrack_stackpointer())); 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(source, 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MemOperand(backtrack_stackpointer(), kPointerSize, NegPreIndex)); 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::Pop(Register target) { 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!target.is(backtrack_stackpointer())); 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(target, 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MemOperand(backtrack_stackpointer(), kPointerSize, PostIndex)); 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckPreemption() { 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for preemption. 1194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 119544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::address_of_stack_limit(masm_->isolate()); 1196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r0, Operand(stack_limit)); 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(r0, MemOperand(r0)); 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(sp, r0); 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCall(&check_preempt_label_, ls); 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CheckStackLimit() { 1204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 120544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::address_of_regexp_stack_limit(masm_->isolate()); 1206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ mov(r0, Operand(stack_limit)); 1207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ ldr(r0, MemOperand(r0)); 1208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(backtrack_stackpointer(), Operand(r0)); 1209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SafeCall(&stack_overflow_label_, ls); 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::EmitBacktrackConstantPool() { 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CheckConstPool(false, false); 12153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Assembler::BlockConstPoolScope block_const_pool(masm_); 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_constant_pool_offset_ = masm_->pc_offset(); 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < kBacktrackConstantPoolSize; i++) { 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ emit(0); 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_constant_pool_capacity_ = kBacktrackConstantPoolSize; 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerARM::GetBacktrackConstantPoolEntry() { 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (backtrack_constant_pool_capacity_ > 0) { 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = backtrack_constant_pool_offset_; 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_constant_pool_offset_ += kPointerSize; 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_constant_pool_capacity_--; 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (masm_->pc_offset() - offset < 2 * KB) { 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return offset; 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label new_pool_skip; 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&new_pool_skip); 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EmitBacktrackConstantPool(); 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&new_pool_skip); 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = backtrack_constant_pool_offset_; 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_constant_pool_offset_ += kPointerSize; 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_constant_pool_capacity_--; 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return offset; 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::CallCFunctionUsingStub( 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference function, 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_arguments) { 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Must pass all arguments in registers. The stub pushes on the stack. 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(num_arguments <= 4); 12506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(code_pointer(), Operand(function)); 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegExpCEntryStub stub; 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CallStub(&stub); 1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (OS::ActivationFrameAlignment() != 0) { 1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(sp, MemOperand(sp, 0)); 1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(code_pointer(), Operand(masm_->CodeObject())); 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerARM::LoadCurrentCharacterUnchecked(int cp_offset, 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int characters) { 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register offset = current_input_offset(); 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (cp_offset != 0) { 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(r0, current_input_offset(), Operand(cp_offset * char_size())); 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block offset = r0; 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 126725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU 126825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // and the operating system running on the target allow it. 126925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // If unaligned load/stores are not supported then this function must only 127025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // be used to load a single character at a time. 127125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen#if !V8_TARGET_CAN_READ_UNALIGNED 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(characters == 1); 127325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen#endif 127425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 127625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (characters == 4) { 127725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ ldr(current_character(), MemOperand(end_of_input_address(), offset)); 127825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else if (characters == 2) { 127925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ ldrh(current_character(), MemOperand(end_of_input_address(), offset)); 128025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 128125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen ASSERT(characters == 1); 128225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ ldrb(current_character(), MemOperand(end_of_input_address(), offset)); 128325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 128625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (characters == 2) { 128725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ ldr(current_character(), MemOperand(end_of_input_address(), offset)); 128825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 128925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen ASSERT(characters == 1); 129025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ ldrh(current_character(), MemOperand(end_of_input_address(), offset)); 129125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpCEntryStub::Generate(MacroAssembler* masm_) { 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int stack_alignment = OS::ActivationFrameAlignment(); 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (stack_alignment < kPointerSize) stack_alignment = kPointerSize; 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stack is already aligned for call, so decrement by alignment 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to make room for storing the link register. 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ str(lr, MemOperand(sp, stack_alignment, NegPreIndex)); 1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(r0, sp); 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Call(r5); 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ldr(pc, MemOperand(sp, stack_alignment, PostIndex)); 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif // V8_INTERPRETED_REGEXP 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}} // namespace v8::internal 1312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_ARM 1314