regexp-macro-assembler-ia32.cc revision a7e24c173cf37484693b9abb38e494fa7bd7baeb
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2008-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" 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "unicode.h" 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "log.h" 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ast.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "regexp-stack.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "macro-assembler.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "regexp-macro-assembler.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ia32/macro-assembler-ia32.h" 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ia32/regexp-macro-assembler-ia32.h" 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef V8_NATIVE_REGEXP 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * This assembler uses the following register assignment convention 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - edx : current character. Must be loaded using LoadCurrentCharacter 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * before using any of the dispatch methods. 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - edi : current position in input, as negative offset from end of string. 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Please notice that this is the byte offset, not the character offset! 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - esi : end of input (points to byte after last character in input). 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - ebp : frame pointer. Used to access arguments, local variables and 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * RegExp registers. 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - esp : points to tip of C stack. 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - ecx : points to tip of backtrack stack 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The registers eax, ebx and ecx are free to use for computations. 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Each call to a public method should retain this convention. 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The stack will have the following structure: 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - stack_area_base (High end of the memory area to use as 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * backtracking stack) 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - at_start (if 1, start at start of string, if 0, don't) 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - int* capture_array (int[num_saved_registers_], for output). 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - end of input (Address of end of string) 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - start of input (Address of first character in string) 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - void* input_string (location of a handle containing the string) 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * --- frame alignment (if applicable) --- 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - return address 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * ebp-> - old ebp 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - backup of caller esi 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - backup of caller edi 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - backup of caller ebx 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - Offset of location before start of input (effectively character 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * position -1). Used to initialize capture registers to a non-position. 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - register 0 ebp[-4] (Only positions must be stored in the first 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - register 1 ebp[-8] num_saved_registers_ registers) 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - ... 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The first num_saved_registers_ registers are initialized to point to 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * "character -1" in the string (i.e., char_size() bytes before the first 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * character of the string). The remaining registers starts out as garbage. 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The data up to the return address must be placed there by the calling 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * code, by calling the code entry as cast to a function with the signature: 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * int (*match)(String* input_string, 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Address start, 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Address end, 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * int* capture_output_array, 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * bool at_start, 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * byte* stack_area_base) 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */ 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm_) 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32( 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Mode mode, 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int registers_to_save) 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : masm_(new MacroAssembler(NULL, kRegExpCodeSize)), 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mode_(mode), 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_registers_(registers_to_save), 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_saved_registers_(registers_to_save), 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block entry_label_(), 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block start_label_(), 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block success_label_(), 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_label_(), 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block exit_label_() { 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, registers_to_save % 2); 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&entry_label_); // We'll write the entry code later. 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&start_label_); // And then continue from here. 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() { 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete masm_; 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Unuse labels in case we throw away the assembler without calling GetCode. 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block entry_label_.Unuse(); 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block start_label_.Unuse(); 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block success_label_.Unuse(); 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_label_.Unuse(); 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block exit_label_.Unuse(); 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block check_preempt_label_.Unuse(); 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_overflow_label_.Unuse(); 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerIA32::stack_limit_slack() { 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RegExpStack::kStackLimitSlack; 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (by != 0) { 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label inside_string; 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(edi), Immediate(by * char_size())); 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg >= 0); 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg < num_registers_); 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (by != 0) { 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(register_location(reg), Immediate(by)); 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Backtrack() { 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPreemption(); 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop Code* offset from backtrack stack, add Code* and jump to location. 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(ebx); 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(ebx), Immediate(masm_->CodeObject())); 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(Operand(ebx)); 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Bind(Label* label) { 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(label); 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) { 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), c); 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_equal); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) { 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), limit); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater, on_greater); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckAtStart(Label* on_at_start) { 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label not_at_start; 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Did we start the match at the start of the string at all? 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(Operand(ebp, kAtStart), Immediate(0)); 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, ¬_at_start); 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we did, are we still at the start of the input? 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(esi, edi, times_1, 0)); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, Operand(ebp, kInputStart)); 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_at_start); 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(¬_at_start); 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotAtStart(Label* on_not_at_start) { 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Did we start the match at the start of the string at all? 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(Operand(ebp, kAtStart), Immediate(0)); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_not_at_start); 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we did, are we still at the start of the input? 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(esi, edi, times_1, 0)); 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, Operand(ebp, kInputStart)); 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_at_start); 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) { 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), limit); 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(less, on_less); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str, 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int cp_offset, 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_failure, 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool check_end_of_string) { 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int byte_length = str.length() * char_size(); 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int byte_offset = cp_offset * char_size(); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_end_of_string) { 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that there are at least str.length() characters left in the input. 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(Operand(edi), Immediate(-(byte_offset + byte_length))); 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater, on_failure); 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (on_failure == NULL) { 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instead of inlining a backtrack, (re)use the global backtrack target. 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block on_failure = &backtrack_label_; 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < str.length(); i++) { 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb(Operand(esi, edi, times_1, byte_offset + i), 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static_cast<int8_t>(str[i])); 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpw(Operand(esi, edi, times_1, byte_offset + i * sizeof(uc16)), 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(str[i])); 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_failure); 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) { 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edi, Operand(backtrack_stackpointer(), 0)); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &fallthrough); 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); // Pop. 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, on_equal); 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_reg, 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, register_location(start_reg)); // Index of start of capture 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(ebx, Operand(edx)); // Length of capture. 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The length of a capture should not be negative. This can only happen 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // if the end of the capture is unrecorded, or at a point earlier than 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the start of the capture. 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(less, on_no_match, not_taken); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If length is zero, either the capture is empty or it is completely 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // uncaptured. In either case succeed immediately. 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &fallthrough); 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label success; 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fail; 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop_increment; 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save register contents to make the registers available below. 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // After this, the eax, ecx, and edi registers are available. 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(edx, Operand(esi)); // Start of capture 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(edi, Operand(esi)); // Start of text to match against capture. 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(ebx, Operand(edi)); // End of text to match against capture. 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop; 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(eax, Operand(edi, 0)); 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb_al(Operand(edx, 0)); 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &loop_increment); 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mismatch, try case-insensitive match (converting letters to lower-case). 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(eax, 0x20); // Convert match character to lower-case. 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(ecx, Operand(eax, -'a')); 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ecx, static_cast<int32_t>('z' - 'a')); // Is eax a lowercase letter? 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above, &fail); 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Also convert capture character. 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ecx, Operand(edx, 0)); 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(ecx, 0x20); 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, Operand(ecx)); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &fail); 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop_increment); 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Increment pointers into match and capture strings. 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(edx), Immediate(1)); 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(edi), Immediate(1)); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare to end of match, and loop if not done. 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edi, Operand(ebx)); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &loop, taken); 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&success); 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fail); 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore original values before failing. 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, on_no_match); 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success); 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore original value before continuing. 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Drop original value of character position. 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(esp), Immediate(kPointerSize)); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute new value of character position after the matched part. 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(edi, Operand(esi)); 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save registers before calling C function. 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(esi); 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argument_count = 3; 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FrameAlign(argument_count, ecx); 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Put arguments into allocated stack area, last argument highest on stack. 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Parameters are 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Address byte_offset1 - Address captured substring's start. 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Address byte_offset2 - Address of current character position. 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // size_t byte_length - length of capture in bytes(!) 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_length. 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 2 * kPointerSize), ebx); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_offset2. 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Found by adding negative string-end offset of current position (edi) 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to end of string. 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(edi, Operand(esi)); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 1 * kPointerSize), edi); 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_offset1. 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Start of capture, where edx already holds string-end negative offset. 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(edx, Operand(esi)); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 0 * kPointerSize), edx); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference compare = 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::re_case_insensitive_compare_uc16(); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCFunction(compare, argument_count); 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop original values before reacting on result value. 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(esi); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if function returned non-zero for success or zero for failure. 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(eax, Operand(eax)); 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(zero, on_no_match); 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // On success, increment position by length of capture. 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(edi, Operand(ebx)); 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotBackReference( 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_reg, 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label success; 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fail; 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find length of back-referenced capture. 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, register_location(start_reg)); 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, register_location(start_reg + 1)); 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(eax, Operand(edx)); // Length to check. 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fail on partial or illegal capture (start of capture after end of capture). 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(less, on_no_match); 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Succeed on empty capture (including no capture) 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &fallthrough); 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that there are sufficient characters left in the input. 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, edi); 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(ebx, Operand(eax)); 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater, on_no_match); 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save register to make it available below. 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute pointers to match string and capture string 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(edx, Operand(esi)); // Start of capture. 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop; 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(eax, Operand(edx, 0)); 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb_al(Operand(ebx, 0)); 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_w(eax, Operand(edx, 0)); 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpw_ax(Operand(ebx, 0)); 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &fail); 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Increment pointers into capture and match string. 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(edx), Immediate(char_size())); 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(ebx), Immediate(char_size())); 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if we have reached end of match area. 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ebx, Operand(ecx)); 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &loop); 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&success); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fail); 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore backtrack stackpointer. 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, on_no_match); 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success); 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move current character position to position after match. 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, ecx); 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(edi), esi); 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore backtrack stackpointer. 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotRegistersEqual(int reg1, 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int reg2, 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, register_location(reg1)); 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, register_location(reg2)); 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotCharacter(uint32_t c, 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), c); 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckCharacterAfterAnd(uint32_t c, 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t mask, 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_equal) { 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, current_character()); 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(eax, mask); 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, c); 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_equal); 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotCharacterAfterAnd(uint32_t c, 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t mask, 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, current_character()); 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(eax, mask); 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, c); 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusAnd( 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 c, 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 minus, 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 mask, 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(minus < String::kMaxUC16CharCode); 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(current_character(), -minus)); 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(eax, mask); 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, c); 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type, 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int cp_offset, 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool check_offset, 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Range checks (c in min..max) are generally implemented by an unsigned 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (c - min) <= (max - min) check 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (type) { 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 's': 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match space-characters 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ASCII space characters are '\t'..'\r' and ' '. 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_offset) { 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacter(cp_offset, on_no_match); 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(cp_offset, 1); 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label success; 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), ' '); 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &success); 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check range 0x09..0x0d 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(current_character()), Immediate('\t')); 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), '\r' - '\t'); 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(above, on_no_match); 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'S': 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non-space characters. 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_offset) { 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacter(cp_offset, on_no_match, 1); 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(cp_offset, 1); 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ASCII space characters are '\t'..'\r' and ' '. 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), ' '); 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_no_match); 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(current_character()), Immediate('\t')); 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), '\r' - '\t'); 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'd': 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match ASCII digits ('0'..'9') 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_offset) { 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacter(cp_offset, on_no_match, 1); 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(cp_offset, 1); 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(current_character()), Immediate('0')); 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), '9' - '0'); 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(above, on_no_match); 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'D': 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non ASCII-digits 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_offset) { 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacter(cp_offset, on_no_match, 1); 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(cp_offset, 1); 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(current_character()), Immediate('0')); 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), '9' - '0'); 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case '.': { 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_offset) { 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacter(cp_offset, on_no_match, 1); 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(cp_offset, 1); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ xor_(Operand(current_character()), Immediate(0x01)); 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(current_character()), Immediate(0x0b)); 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), 0x0c - 0x0b); 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == UC16) { 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare original value to 0x2028 and 0x2029, using the already 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // computed (current_char ^ 0x01 - 0x0b). I.e., check for 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 0x201d (0x2028 - 0x0b) or 0x201e. 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(current_character()), Immediate(0x2028 - 0x0b)); 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), 1); 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case '*': 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match any character. 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_offset) { 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPosition(cp_offset, on_no_match); 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No custom implementation (yet): w, W, s(UC16), S(UC16). 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Fail() { 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(FAILURE == 0); // Return value for failure is zero. 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ xor_(eax, Operand(eax)); // zero eax. 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Finalize code - write the entry point code now we know how many 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // registers we need. 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Entry code: 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry_label_); 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Start new stack frame. 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebp); 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebp, esp); 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save callee-save registers. Order here should correspond to order of 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // kBackup_ebx etc. 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(esi); 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // Callee-save on MacOS. 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(Immediate(0)); // Make room for "input start - 1" constant. 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if we have space on the stack for registers. 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label stack_limit_hit; 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label stack_ok; 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference stack_guard_limit = 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::address_of_stack_guard_limit(); 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ecx, esp); 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(ecx, Operand::StaticVariable(stack_guard_limit)); 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle it if the stack pointer is already below the stack limit. 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below_equal, &stack_limit_hit, not_taken); 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if there is room for the variable number of registers above 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the stack limit. 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ecx, num_registers_ * kPointerSize); 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &stack_ok, taken); 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit with OutOfMemory exception. There is not enough space on the stack 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for our working registers. 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, EXCEPTION); 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&stack_limit_hit); 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCheckStackGuardState(ebx); 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(eax, Operand(eax)); 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If returned value is non-zero, we exit with the returned value as result. 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &exit_label_); 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&stack_ok); 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate space on stack for registers. 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(esp), Immediate(num_registers_ * kPointerSize)); 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load string length. 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(esi, Operand(ebp, kInputEnd)); 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load input position. 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, Operand(ebp, kInputStart)); 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set up edi to be negative offset from string end. 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(edi, Operand(esi)); 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set eax to address of char before start of input 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (effectively string position -1). 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(edi, -char_size())); 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store this value in a local variable, for use when clearing 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // position registers. 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(ebp, kInputStartMinusOne), eax); 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill saved registers with initial value = start offset - 1 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill in stack push order, to avoid accessing across an unwritten 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // page (a problem on Windows). 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ecx, kRegisterZero); 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label init_loop; 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&init_loop); 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(ebp, ecx, times_1, +0), eax); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(ecx), Immediate(kPointerSize)); 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize); 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(greater, &init_loop); 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Ensure that we have written to each stack page, in order. Skipping a page 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // on Windows can cause segmentation faults. Assuming page size is 4k. 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kPageSize = 4096; 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kRegistersPerPage = kPageSize / kPointerSize; 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = num_saved_registers_ + kRegistersPerPage - 1; 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i < num_registers_; 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i += kRegistersPerPage) { 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(i), eax); // One write every page. 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize backtrack stack pointer. 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd)); 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load previous char as initial value of current-character. 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label at_start; 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(Operand(ebp, kAtStart), Immediate(0)); 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &at_start); 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(-1, 1); // Load previous char. 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&start_label_); 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&at_start); 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(current_character(), '\n'); 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&start_label_); 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit code: 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (success_label_.is_linked()) { 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save captures when successful. 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success_label_); 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_saved_registers_ > 0) { 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // copy captures to output 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, Operand(ebp, kRegisterOutput)); 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ecx, Operand(ebp, kInputEnd)); 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(ecx, Operand(ebp, kInputStart)); 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < num_saved_registers_; i++) { 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, register_location(i)); 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(eax, Operand(ecx)); // Convert to index from start, not end. 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == UC16) { 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sar(eax, 1); // Convert byte index to character index. 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(ebx, i * kPointerSize), eax); 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, Immediate(SUCCESS)); 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit and return eax 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit_label_); 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip esp past regexp registers. 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(esp, Operand(ebp, kBackup_ebx)); 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore callee-save registers. 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(esi); 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit function frame, restore previous one. 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebp); 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Backtrack code (branch target for conditional backtracks). 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (backtrack_label_.is_linked()) { 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&backtrack_label_); 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Backtrack(); 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label exit_with_exception; 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preempt-code 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_preempt_label_.is_linked()) { 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCallTarget(&check_preempt_label_); 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCheckStackGuardState(ebx); 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(eax, Operand(eax)); 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If returning non-zero, we should end execution with the given 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result as return value. 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &exit_label_); 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // String might have moved: Reload esi from frame. 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(esi, Operand(ebp, kInputEnd)); 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeReturn(); 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Backtrack stack overflow code. 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (stack_overflow_label_.is_linked()) { 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCallTarget(&stack_overflow_label_); 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reached if the backtrack-stack limit has been hit. 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label grow_failed; 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save registers before calling C function 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(esi); 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call GrowStack(backtrack_stackpointer()) 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_arguments = 2; 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FrameAlign(num_arguments, ebx); 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(ebp, kStackHighEnd)); 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 1 * kPointerSize), eax); 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer()); 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference grow_stack = ExternalReference::re_grow_stack(); 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCFunction(grow_stack, num_arguments); 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If return NULL, we have failed to grow the stack, and 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // must exit with a stack-overflow exception. 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(eax, Operand(eax)); 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &exit_with_exception); 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Otherwise use return value as new stack pointer. 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(backtrack_stackpointer(), eax); 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore saved registers and continue. 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(esi); 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeReturn(); 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (exit_with_exception.is_linked()) { 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If any of the code above needed to exit with an exception. 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit_with_exception); 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit with Result EXCEPTION(-1) to signal thrown exception. 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, EXCEPTION); 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CodeDesc code_desc; 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm_->GetCode(&code_desc); 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code = Factory::NewCode(code_desc, 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NULL, 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::ComputeFlags(Code::REGEXP), 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm_->CodeObject()); 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LOG(RegExpCodeCreateEvent(*code, *source)); 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Handle<Object>::cast(code); 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::GoTo(Label* to) { 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, to); 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::IfRegisterGE(int reg, 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int comparand, 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_ge) { 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(register_location(reg), Immediate(comparand)); 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater_equal, if_ge); 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::IfRegisterLT(int reg, 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int comparand, 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_lt) { 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(register_location(reg), Immediate(comparand)); 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(less, if_lt); 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::IfRegisterEqPos(int reg, 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_eq) { 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edi, register_location(reg)); 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, if_eq); 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssembler::IrregexpImplementation 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegExpMacroAssemblerIA32::Implementation() { 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return kIA32Implementation; 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset, 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_end_of_input, 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool check_bounds, 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int characters) { 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_bounds) { 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPosition(cp_offset + characters - 1, on_end_of_input); 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(cp_offset, characters); 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PopCurrentPosition() { 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(edi); 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PopRegister(int register_index) { 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(eax); 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(register_index), eax); 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PushBacktrack(Label* label) { 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(Immediate::CodeRelativeOffset(label)); 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckStackLimit(); 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PushCurrentPosition() { 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(edi); 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PushRegister(int register_index, 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackCheckFlag check_stack_limit) { 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, register_location(register_index)); 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(eax); 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_stack_limit) CheckStackLimit(); 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) { 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, register_location(reg)); 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) { 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(backtrack_stackpointer(), register_location(reg)); 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(backtrack_stackpointer(), Operand(ebp, kStackHighEnd)); 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) { 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(register_index >= num_saved_registers_); // Reserved for positions! 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(register_index), Immediate(to)); 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Succeed() { 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&success_label_); 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg, 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int cp_offset) { 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (cp_offset == 0) { 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(reg), edi); 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(edi, cp_offset * char_size())); 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(reg), eax); 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::ClearRegisters(int reg_from, int reg_to) { 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg_from <= reg_to); 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, Operand(ebp, kInputStartMinusOne)); 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int reg = reg_from; reg <= reg_to; reg++) { 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(reg), eax); 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, backtrack_stackpointer()); 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(eax, Operand(ebp, kStackHighEnd)); 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(reg), eax); 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Private methods: 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) { 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_arguments = 3; 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FrameAlign(num_arguments, scratch); 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // RegExp code frame pointer. 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 2 * kPointerSize), ebp); 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Code* of self. 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 1 * kPointerSize), Immediate(masm_->CodeObject())); 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Next address on the stack (will be address of return address). 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(esp, -kPointerSize)); 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 0 * kPointerSize), eax); 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference check_stack_guard = 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::re_check_stack_guard_state(); 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCFunction(check_stack_guard, num_arguments); 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper function for reading a value out of a stack frame. 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate <typename T> 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic T& frame_entry(Address re_frame, int frame_offset) { 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset)); 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address, 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* re_code, 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address re_frame) { 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (StackGuard::IsStackOverflow()) { 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Top::StackOverflow(); 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return EXCEPTION; 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If not real stack overflow the stack guard was used to interrupt 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // execution for another purpose. 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Prepare for possible GC. 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandleScope handles; 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code_handle(re_code); 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Current string. 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_ascii = subject->IsAsciiRepresentation(); 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(re_code->instruction_start() <= *return_address); 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(*return_address <= 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block re_code->instruction_start() + re_code->instruction_size()); 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* result = Execution::HandleStackGuardInterrupt(); 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*code_handle != re_code) { // Return address no longer valid 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int delta = *code_handle - re_code; 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Overwrite the return address on the stack. 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *return_address += delta; 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result->IsException()) { 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return EXCEPTION; 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // String might have changed. 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (subject->IsAsciiRepresentation() != is_ascii) { 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we changed between an ASCII and an UC16 string, the specialized 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code cannot be used, and we need to restart regexp matching from 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch (including, potentially, compiling a new version of the code). 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RETRY; 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Otherwise, the content of the string might have moved. It must still 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // be a sequential or external string with the same content. 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the start and end pointers in the stack frame to the current 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // location (whether it has actually moved or not). 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(StringShape(*subject).IsSequential() || 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringShape(*subject).IsExternal()); 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The original start address of the characters to match. 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart); 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find the current start address of the same character at the current string 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // position. 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_index = frame_entry<int>(re_frame, kStartIndex); 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const byte* new_address = StringCharacterPosition(*subject, start_index); 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (start_address != new_address) { 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If there is a difference, update the object pointer and start and end 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // addresses in the RegExp stack frame to match the new value. 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd); 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int byte_length = end_address - start_address; 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const String*>(re_frame, kInputString) = *subject; 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const byte*>(re_frame, kInputStart) = new_address; 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length; 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 0; 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand RegExpMacroAssemblerIA32::register_location(int register_index) { 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(register_index < (1<<30)); 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_registers_ <= register_index) { 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_registers_ = register_index + 1; 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(ebp, kRegisterZero - register_index * kPointerSize); 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckPosition(int cp_offset, 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_outside_input) { 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edi, -cp_offset * char_size()); 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater_equal, on_outside_input); 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition, 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* to, 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Hint hint) { 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (condition < 0) { // No condition 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (to == NULL) { 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Backtrack(); 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(to); 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (to == NULL) { 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(condition, &backtrack_label_, hint); 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(condition, to, hint); 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::SafeCall(Label* to) { 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ call(to); 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::SafeReturn() { 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(esp, 0), Immediate(masm_->CodeObject())); 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::SafeCallTarget(Label* name) { 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(name); 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(esp, 0), Immediate(masm_->CodeObject())); 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Push(Register source) { 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!source.is(backtrack_stackpointer())); 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Push. 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(backtrack_stackpointer(), 0), source); 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Push(Immediate value) { 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Push. 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(backtrack_stackpointer(), 0), value); 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Pop(Register target) { 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!target.is(backtrack_stackpointer())); 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(target, Operand(backtrack_stackpointer(), 0)); 1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Pop. 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(backtrack_stackpointer()), Immediate(kPointerSize)); 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckPreemption() { 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for preemption. 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label no_preempt; 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference stack_guard_limit = 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::address_of_stack_guard_limit(); 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(esp, Operand::StaticVariable(stack_guard_limit)); 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above, &no_preempt, taken); 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCall(&check_preempt_label_); 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&no_preempt); 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckStackLimit() { 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (FLAG_check_stack) { 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label no_stack_overflow; 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference stack_limit = 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::address_of_regexp_stack_limit(); 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(backtrack_stackpointer(), Operand::StaticVariable(stack_limit)); 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above, &no_stack_overflow); 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCall(&stack_overflow_label_); 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&no_stack_overflow); 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::FrameAlign(int num_arguments, Register scratch) { 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(lrn): Since we no longer use the system stack arbitrarily (but we do 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // use it, e.g., for SafeCall), we know the number of elements on the stack 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // since the last frame alignment. We might be able to do this simpler then. 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int frameAlignment = OS::ActivationFrameAlignment(); 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (frameAlignment != 0) { 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make stack end at alignment and make room for num_arguments words 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and the original value of esp. 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(scratch, esp); 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(esp), Immediate((num_arguments + 1) * kPointerSize)); 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(IsPowerOf2(frameAlignment)); 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(esp, -frameAlignment); 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, num_arguments * kPointerSize), scratch); 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(Operand(esp), Immediate(num_arguments * kPointerSize)); 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CallCFunction(ExternalReference function, 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int num_arguments) { 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(eax), Immediate(function)); 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ call(Operand(eax)); 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (OS::ActivationFrameAlignment() != 0) { 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(esp, Operand(esp, num_arguments * kPointerSize)); 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(Operand(esp), Immediate(num_arguments * sizeof(int32_t))); 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset, 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int characters) { 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (characters == 4) { 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(current_character(), Operand(esi, edi, times_1, cp_offset)); 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (characters == 2) { 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_w(current_character(), Operand(esi, edi, times_1, cp_offset)); 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(characters == 1); 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset)); 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (characters == 2) { 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(current_character(), 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(characters == 1); 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_w(current_character(), 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpCEntryStub::Generate(MacroAssembler* masm_) { 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ int3(); // Unused on ia32. 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_NATIVE_REGEXP 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}} // namespace v8::internal 1175