13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_IA32) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "unicode.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "log.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "regexp-stack.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "macro-assembler.h" 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "regexp-macro-assembler.h" 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ia32/regexp-macro-assembler-ia32.h" 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifndef V8_INTERPRETED_REGEXP 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * This assembler uses the following register assignment convention 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - edx : current character. Must be loaded using LoadCurrentCharacter 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * before using any of the dispatch methods. 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - edi : current position in input, as negative offset from end of string. 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Please notice that this is the byte offset, not the character offset! 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - esi : end of input (points to byte after last character in input). 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - ebp : frame pointer. Used to access arguments, local variables and 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * RegExp registers. 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - esp : points to tip of C stack. 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - ecx : points to tip of backtrack stack 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 5525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen * The registers eax and ebx are free to use for computations. 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Each call to a public method should retain this convention. 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The stack will have the following structure: 5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block * - Isolate* isolate (Address of the current isolate) 60e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - direct_call (if 1, direct call from JavaScript code, if 0 61e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * call through the runtime system) 62e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - stack_area_base (High end of the memory area to use as 63e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * backtracking stack) 64e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - int* capture_array (int[num_saved_registers_], for output). 65e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - end of input (Address of end of string) 66e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - start of input (Address of first character in string) 67e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - start index (character index of start) 68e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - String* input_string (location of a handle containing the string) 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * --- frame alignment (if applicable) --- 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - return address 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * ebp-> - old ebp 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - backup of caller esi 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - backup of caller edi 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - backup of caller ebx 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - Offset of location before start of input (effectively character 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * position -1). Used to initialize capture registers to a non-position. 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - register 0 ebp[-4] (Only positions must be stored in the first 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - register 1 ebp[-8] num_saved_registers_ registers) 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - ... 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The first num_saved_registers_ registers are initialized to point to 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * "character -1" in the string (i.e., char_size() bytes before the first 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * character of the string). The remaining registers starts out as garbage. 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The data up to the return address must be placed there by the calling 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * code, by calling the code entry as cast to a function with the signature: 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * int (*match)(String* input_string, 88e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * int start_index, 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Address start, 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Address end, 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * int* capture_output_array, 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * bool at_start, 93e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * byte* stack_area_base, 94e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * bool direct_call) 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */ 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm_) 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32( 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Mode mode, 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int registers_to_save) 1028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : masm_(new MacroAssembler(Isolate::Current(), NULL, kRegExpCodeSize)), 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mode_(mode), 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_registers_(registers_to_save), 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_saved_registers_(registers_to_save), 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block entry_label_(), 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block start_label_(), 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block success_label_(), 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_label_(), 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block exit_label_() { 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, registers_to_save % 2); 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&entry_label_); // We'll write the entry code later. 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&start_label_); // And then continue from here. 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() { 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete masm_; 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Unuse labels in case we throw away the assembler without calling GetCode. 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block entry_label_.Unuse(); 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block start_label_.Unuse(); 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block success_label_.Unuse(); 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_label_.Unuse(); 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block exit_label_.Unuse(); 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block check_preempt_label_.Unuse(); 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_overflow_label_.Unuse(); 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerIA32::stack_limit_slack() { 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RegExpStack::kStackLimitSlack; 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (by != 0) { 1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edi, Immediate(by * char_size())); 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg >= 0); 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg < num_registers_); 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (by != 0) { 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(register_location(reg), Immediate(by)); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Backtrack() { 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPreemption(); 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop Code* offset from backtrack stack, add Code* and jump to location. 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(ebx); 1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ebx, Immediate(masm_->CodeObject())); 1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ebx); 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Bind(Label* label) { 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(label); 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) { 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), c); 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_equal); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) { 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), limit); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater, on_greater); 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckAtStart(Label* on_at_start) { 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label not_at_start; 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Did we start the match at the start of the string at all? 18025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmp(Operand(ebp, kStartIndex), Immediate(0)); 18125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen BranchOrBacktrack(not_equal, ¬_at_start); 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we did, are we still at the start of the input? 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(esi, edi, times_1, 0)); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, Operand(ebp, kInputStart)); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_at_start); 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(¬_at_start); 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotAtStart(Label* on_not_at_start) { 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Did we start the match at the start of the string at all? 19225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmp(Operand(ebp, kStartIndex), Immediate(0)); 19325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen BranchOrBacktrack(not_equal, on_not_at_start); 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we did, are we still at the start of the input? 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(esi, edi, times_1, 0)); 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, Operand(ebp, kInputStart)); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_at_start); 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) { 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), limit); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(less, on_less); 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str, 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int cp_offset, 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_failure, 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool check_end_of_string) { 21125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen#ifdef DEBUG 21225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // If input is ASCII, don't even bother calling here if the string to 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // match contains a non-ASCII character. 21425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (mode_ == ASCII) { 2159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(String::IsAscii(str.start(), str.length())); 21625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 21725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen#endif 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int byte_length = str.length() * char_size(); 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int byte_offset = cp_offset * char_size(); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_end_of_string) { 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that there are at least str.length() characters left in the input. 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(edi, Immediate(-(byte_offset + byte_length))); 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater, on_failure); 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (on_failure == NULL) { 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instead of inlining a backtrack, (re)use the global backtrack target. 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block on_failure = &backtrack_label_; 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Do one character test first to minimize loading for the case that 23225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // we don't match at all (loading more than one character introduces that 23325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // chance of reading unaligned and reading across cache boundaries). 23425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // If the first character matches, expect a larger chance of matching the 23525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // string, and start loading more characters at a time. 23625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (mode_ == ASCII) { 23725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpb(Operand(esi, edi, times_1, byte_offset), 23825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen static_cast<int8_t>(str[0])); 23925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 24025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Don't use 16-bit immediate. The size changing prefix throws off 24125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // pre-decoding. 24225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ movzx_w(eax, 24325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Operand(esi, edi, times_1, byte_offset)); 24425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmp(eax, static_cast<int32_t>(str[0])); 24525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 24625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen BranchOrBacktrack(not_equal, on_failure); 24725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 24825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ lea(ebx, Operand(esi, edi, times_1, 0)); 24925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen for (int i = 1, n = str.length(); i < n;) { 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 25125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (i <= n - 4) { 25225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen int combined_chars = 25325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint32_t>(str[i + 0]) << 0) | 25425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint32_t>(str[i + 1]) << 8) | 25525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint32_t>(str[i + 2]) << 16) | 25625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint32_t>(str[i + 3]) << 24); 25725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmp(Operand(ebx, byte_offset + i), Immediate(combined_chars)); 25825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i += 4; 25925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 26025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpb(Operand(ebx, byte_offset + i), 26125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen static_cast<int8_t>(str[i])); 26225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i += 1; 26325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 26625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (i <= n - 2) { 26725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmp(Operand(ebx, byte_offset + i * sizeof(uc16)), 26825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Immediate(*reinterpret_cast<const int*>(&str[i]))); 26925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i += 2; 27025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 27125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Avoid a 16-bit immediate operation. It uses the length-changing 27225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // 0x66 prefix which causes pre-decoder misprediction and pipeline 27325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // stalls. See 27425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // "Intel(R) 64 and IA-32 Architectures Optimization Reference Manual" 27525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // (248966.pdf) section 3.4.2.3 "Length-Changing Prefixes (LCP)" 27625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ movzx_w(eax, 27725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Operand(ebx, byte_offset + i * sizeof(uc16))); 27825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmp(eax, static_cast<int32_t>(str[i])); 27925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i += 1; 28025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_failure); 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) { 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edi, Operand(backtrack_stackpointer(), 0)); 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &fallthrough); 2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(backtrack_stackpointer(), Immediate(kPointerSize)); // Pop. 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, on_equal); 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_reg, 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, register_location(start_reg)); // Index of start of capture 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture 3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(ebx, edx); // Length of capture. 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The length of a capture should not be negative. This can only happen 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // if the end of the capture is unrecorded, or at a point earlier than 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the start of the capture. 308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch BranchOrBacktrack(less, on_no_match); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If length is zero, either the capture is empty or it is completely 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // uncaptured. In either case succeed immediately. 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &fallthrough); 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label success; 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fail; 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop_increment; 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save register contents to make the registers available below. 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // After this, the eax, ecx, and edi registers are available. 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edx, esi); // Start of capture 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edi, esi); // Start of text to match against capture. 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ebx, edi); // End of text to match against capture. 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop; 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(eax, Operand(edi, 0)); 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb_al(Operand(edx, 0)); 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &loop_increment); 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mismatch, try case-insensitive match (converting letters to lower-case). 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(eax, 0x20); // Convert match character to lower-case. 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(ecx, Operand(eax, -'a')); 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ecx, static_cast<int32_t>('z' - 'a')); // Is eax a lowercase letter? 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above, &fail); 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Also convert capture character. 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ecx, Operand(edx, 0)); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(ecx, 0x20); 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, ecx); 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &fail); 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop_increment); 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Increment pointers into match and capture strings. 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edx, Immediate(1)); 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edi, Immediate(1)); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare to end of match, and loop if not done. 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(edi, ebx); 351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(below, &loop); 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&success); 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fail); 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore original values before failing. 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, on_no_match); 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success); 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore original value before continuing. 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Drop original value of character position. 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(esp, Immediate(kPointerSize)); 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute new value of character position after the matched part. 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(edi, esi); 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save registers before calling C function. 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(esi); 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static const int argument_count = 4; 3766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ PrepareCallCFunction(argument_count, ecx); 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Put arguments into allocated stack area, last argument highest on stack. 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Parameters are 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Address byte_offset1 - Address captured substring's start. 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Address byte_offset2 - Address of current character position. 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // size_t byte_length - length of capture in bytes(!) 3828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Isolate* isolate 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Set isolate. 3858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ mov(Operand(esp, 3 * kPointerSize), 3868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Immediate(ExternalReference::isolate_address())); 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_length. 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 2 * kPointerSize), ebx); 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_offset2. 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Found by adding negative string-end offset of current position (edi) 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to end of string. 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edi, esi); 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 1 * kPointerSize), edi); 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_offset1. 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Start of capture, where edx already holds string-end negative offset. 3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edx, esi); 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 0 * kPointerSize), edx); 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm_); 4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference compare = 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate()); 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(compare, argument_count); 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop original values before reacting on result value. 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(esi); 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if function returned non-zero for success or zero for failure. 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ or_(eax, eax); 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(zero, on_no_match); 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // On success, increment position by length of capture. 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edi, ebx); 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotBackReference( 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_reg, 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label success; 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fail; 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find length of back-referenced capture. 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, register_location(start_reg)); 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, register_location(start_reg + 1)); 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(eax, edx); // Length to check. 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fail on partial or illegal capture (start of capture after end of capture). 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(less, on_no_match); 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Succeed on empty capture (including no capture) 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &fallthrough); 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that there are sufficient characters left in the input. 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, edi); 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ebx, eax); 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater, on_no_match); 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save register to make it available below. 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute pointers to match string and capture string 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. 4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edx, esi); // Start of capture. 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop; 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(eax, Operand(edx, 0)); 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb_al(Operand(ebx, 0)); 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_w(eax, Operand(edx, 0)); 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpw_ax(Operand(ebx, 0)); 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &fail); 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Increment pointers into capture and match string. 4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edx, Immediate(char_size())); 4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ebx, Immediate(char_size())); 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if we have reached end of match area. 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ebx, ecx); 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &loop); 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&success); 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fail); 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore backtrack stackpointer. 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, on_no_match); 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success); 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move current character position to position after match. 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, ecx); 4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(edi, esi); 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore backtrack stackpointer. 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotRegistersEqual(int reg1, 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int reg2, 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, register_location(reg1)); 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, register_location(reg2)); 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotCharacter(uint32_t c, 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), c); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckCharacterAfterAnd(uint32_t c, 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t mask, 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_equal) { 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, current_character()); 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(eax, mask); 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, c); 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_equal); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotCharacterAfterAnd(uint32_t c, 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t mask, 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, current_character()); 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(eax, mask); 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, c); 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusAnd( 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 c, 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 minus, 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 mask, 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(minus < String::kMaxUtf16CodeUnit); 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(current_character(), -minus)); 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(eax, mask); 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(eax, c); 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type, 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Range checks (c in min..max) are generally implemented by an unsigned 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (c - min) <= (max - min) check 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (type) { 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 's': 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match space-characters 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ASCII space characters are '\t'..'\r' and ' '. 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label success; 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), ' '); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &success); 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check range 0x09..0x0d 547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(eax, Operand(current_character(), -'\t')); 548e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, '\r' - '\t'); 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(above, on_no_match); 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success); 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'S': 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non-space characters. 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ASCII space characters are '\t'..'\r' and ' '. 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), ' '); 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_no_match); 560e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(eax, Operand(current_character(), -'\t')); 561e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, '\r' - '\t'); 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'd': 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match ASCII digits ('0'..'9') 568e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(eax, Operand(current_character(), -'0')); 569e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, '9' - '0'); 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(above, on_no_match); 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'D': 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non ASCII-digits 574e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(eax, Operand(current_character(), -'0')); 575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, '9' - '0'); 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case '.': { 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) 5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(eax, current_character()); 5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xor_(eax, Immediate(0x01)); 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(eax, Immediate(0x0b)); 584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, 0x0c - 0x0b); 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == UC16) { 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare original value to 0x2028 and 0x2029, using the already 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // computed (current_char ^ 0x01 - 0x0b). I.e., check for 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 0x201d (0x2028 - 0x0b) or 0x201e. 5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(eax, Immediate(0x2028 - 0x0b)); 591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, 0x2029 - 0x2028); 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'w': { 597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ != ASCII) { 598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Table is 128 entries, so all ASCII characters can be tested. 5993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(current_character(), Immediate('z')); 600e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(above, on_no_match); 601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. 603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference word_map = ExternalReference::re_word_character_map(); 604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test_b(current_character(), 605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Operand::StaticArray(current_character(), times_1, word_map)); 606e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(zero, on_no_match); 607e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'W': { 610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ != ASCII) { 612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Table is 128 entries, so all ASCII characters can be tested. 6133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(current_character(), Immediate('z')); 614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(above, &done); 615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. 617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference word_map = ExternalReference::re_word_character_map(); 618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test_b(current_character(), 619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Operand::StaticArray(current_character(), times_1, word_map)); 620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(not_zero, on_no_match); 621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ != ASCII) { 622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&done); 623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Non-standard classes (with no syntactic shorthand) used internally. 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case '*': 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match any character. 629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'n': { 631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029). 632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // The opposite of '.'. 6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(eax, current_character()); 6343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xor_(eax, Immediate(0x01)); 635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 6363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(eax, Immediate(0x0b)); 637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, 0x0c - 0x0b); 638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ == ASCII) { 639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(above, on_no_match); 640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(below_equal, &done); 643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(UC16, mode_); 644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Compare original value to 0x2028 and 0x2029, using the already 645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // computed (current_char ^ 0x01 - 0x0b). I.e., check for 646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // 0x201d (0x2028 - 0x0b) or 0x201e. 6473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(eax, Immediate(0x2028 - 0x0b)); 648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, 1); 649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(above, on_no_match); 650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&done); 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // No custom implementation (yet): s(UC16), S(UC16). 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Fail() { 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(FAILURE == 0); // Return value for failure is zero. 6639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Set(eax, Immediate(0)); 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 668053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve BlockHandle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Finalize code - write the entry point code now we know how many 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // registers we need. 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Entry code: 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry_label_); 6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Tell the system that we have a stack frame. Because the type is MANUAL, no 6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // code is generated. 6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm_, StackFrame::MANUAL); 6783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Actually emit code to start a new stack frame. 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebp); 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebp, esp); 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save callee-save registers. Order here should correspond to order of 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // kBackup_ebx etc. 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(esi); 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // Callee-save on MacOS. 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(Immediate(0)); // Make room for "input start - 1" constant. 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if we have space on the stack for registers. 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label stack_limit_hit; 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label stack_ok; 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 69444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::address_of_stack_limit(masm_->isolate()); 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ecx, esp); 696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ sub(ecx, Operand::StaticVariable(stack_limit)); 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle it if the stack pointer is already below the stack limit. 698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(below_equal, &stack_limit_hit); 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if there is room for the variable number of registers above 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the stack limit. 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ecx, num_registers_ * kPointerSize); 702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &stack_ok); 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit with OutOfMemory exception. There is not enough space on the stack 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for our working registers. 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, EXCEPTION); 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&stack_limit_hit); 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCheckStackGuardState(ebx); 7103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ or_(eax, eax); 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If returned value is non-zero, we exit with the returned value as result. 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &exit_label_); 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&stack_ok); 7156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Load start index for later use. 7166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, Operand(ebp, kStartIndex)); 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate space on stack for registers. 7193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(esp, Immediate(num_registers_ * kPointerSize)); 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load string length. 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(esi, Operand(ebp, kInputEnd)); 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load input position. 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, Operand(ebp, kInputStart)); 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set up edi to be negative offset from string end. 7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(edi, esi); 7266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Set eax to address of char before start of the string. 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (effectively string position -1). 7296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ neg(ebx); 7306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (mode_ == UC16) { 7316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(eax, Operand(edi, ebx, times_2, -char_size())); 7326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 7336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(eax, Operand(edi, ebx, times_1, -char_size())); 7346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store this value in a local variable, for use when clearing 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // position registers. 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(ebp, kInputStartMinusOne), eax); 738d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill saved registers with initial value = start offset - 1 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill in stack push order, to avoid accessing across an unwritten 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // page (a problem on Windows). 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ecx, kRegisterZero); 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label init_loop; 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&init_loop); 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(ebp, ecx, times_1, +0), eax); 7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(ecx, Immediate(kPointerSize)); 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize); 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(greater, &init_loop); 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Ensure that we have written to each stack page, in order. Skipping a page 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // on Windows can cause segmentation faults. Assuming page size is 4k. 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kPageSize = 4096; 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kRegistersPerPage = kPageSize / kPointerSize; 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = num_saved_registers_ + kRegistersPerPage - 1; 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i < num_registers_; 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i += kRegistersPerPage) { 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(i), eax); // One write every page. 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize backtrack stack pointer. 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd)); 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load previous char as initial value of current-character. 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label at_start; 76625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmp(Operand(ebp, kStartIndex), Immediate(0)); 76725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ j(equal, &at_start); 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(-1, 1); // Load previous char. 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&start_label_); 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&at_start); 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(current_character(), '\n'); 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&start_label_); 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit code: 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (success_label_.is_linked()) { 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save captures when successful. 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success_label_); 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_saved_registers_ > 0) { 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // copy captures to output 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, Operand(ebp, kRegisterOutput)); 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ecx, Operand(ebp, kInputEnd)); 7836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(ebp, kStartIndex)); 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(ecx, Operand(ebp, kInputStart)); 7856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (mode_ == UC16) { 7866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(ecx, Operand(ecx, edx, times_2, 0)); 7876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ecx, edx); 7896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < num_saved_registers_; i++) { 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, register_location(i)); 7926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Convert to index from start of string, not end. 7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(eax, ecx); 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == UC16) { 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sar(eax, 1); // Convert byte index to character index. 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(ebx, i * kPointerSize), eax); 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, Immediate(SUCCESS)); 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit and return eax 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit_label_); 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip esp past regexp registers. 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(esp, Operand(ebp, kBackup_ebx)); 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore callee-save registers. 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(esi); 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit function frame, restore previous one. 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebp); 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Backtrack code (branch target for conditional backtracks). 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (backtrack_label_.is_linked()) { 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&backtrack_label_); 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Backtrack(); 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label exit_with_exception; 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preempt-code 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_preempt_label_.is_linked()) { 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCallTarget(&check_preempt_label_); 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCheckStackGuardState(ebx); 8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ or_(eax, eax); 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If returning non-zero, we should end execution with the given 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result as return value. 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &exit_label_); 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // String might have moved: Reload esi from frame. 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(esi, Operand(ebp, kInputEnd)); 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeReturn(); 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Backtrack stack overflow code. 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (stack_overflow_label_.is_linked()) { 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCallTarget(&stack_overflow_label_); 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reached if the backtrack-stack limit has been hit. 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label grow_failed; 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save registers before calling C function 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(esi); 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call GrowStack(backtrack_stackpointer()) 8538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static const int num_arguments = 3; 8546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ PrepareCallCFunction(num_arguments, ebx); 8558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ mov(Operand(esp, 2 * kPointerSize), 8568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Immediate(ExternalReference::isolate_address())); 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(ebp, kStackHighEnd)); 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 1 * kPointerSize), eax); 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer()); 86044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference grow_stack = 86144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::re_grow_stack(masm_->isolate()); 8626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallCFunction(grow_stack, num_arguments); 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If return NULL, we have failed to grow the stack, and 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // must exit with a stack-overflow exception. 8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ or_(eax, eax); 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &exit_with_exception); 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Otherwise use return value as new stack pointer. 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(backtrack_stackpointer(), eax); 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore saved registers and continue. 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(esi); 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeReturn(); 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (exit_with_exception.is_linked()) { 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If any of the code above needed to exit with an exception. 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit_with_exception); 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit with Result EXCEPTION(-1) to signal thrown exception. 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, EXCEPTION); 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CodeDesc code_desc; 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm_->GetCode(&code_desc); 88544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> code = 88644f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm_->isolate()->factory()->NewCode(code_desc, 88744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Code::ComputeFlags(Code::REGEXP), 88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm_->CodeObject()); 88944f0eee88ff00398ff7f715fab053374d808c90dSteve Block PROFILE(masm_->isolate(), RegExpCodeCreateEvent(*code, *source)); 890053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block return Handle<HeapObject>::cast(code); 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::GoTo(Label* to) { 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, to); 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::IfRegisterGE(int reg, 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int comparand, 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_ge) { 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(register_location(reg), Immediate(comparand)); 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater_equal, if_ge); 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::IfRegisterLT(int reg, 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int comparand, 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_lt) { 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(register_location(reg), Immediate(comparand)); 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(less, if_lt); 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::IfRegisterEqPos(int reg, 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_eq) { 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edi, register_location(reg)); 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, if_eq); 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssembler::IrregexpImplementation 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegExpMacroAssemblerIA32::Implementation() { 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return kIA32Implementation; 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset, 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_end_of_input, 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool check_bounds, 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int characters) { 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_bounds) { 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPosition(cp_offset + characters - 1, on_end_of_input); 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(cp_offset, characters); 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PopCurrentPosition() { 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(edi); 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PopRegister(int register_index) { 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(eax); 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(register_index), eax); 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PushBacktrack(Label* label) { 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(Immediate::CodeRelativeOffset(label)); 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckStackLimit(); 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PushCurrentPosition() { 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(edi); 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PushRegister(int register_index, 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackCheckFlag check_stack_limit) { 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, register_location(register_index)); 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(eax); 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_stack_limit) CheckStackLimit(); 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) { 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, register_location(reg)); 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) { 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(backtrack_stackpointer(), register_location(reg)); 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(backtrack_stackpointer(), Operand(ebp, kStackHighEnd)); 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 981f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid RegExpMacroAssemblerIA32::SetCurrentPositionFromEnd(int by) { 982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label after_position; 983f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ cmp(edi, -by * char_size()); 984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(greater_equal, &after_position, Label::kNear); 985f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(edi, -by * char_size()); 986f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // On RegExp code entry (where this operation is used), the character before 987f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // the current position is expected to be already loaded. 988f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // We have advanced the position, so it's safe to read backwards. 989f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch LoadCurrentCharacterUnchecked(-1, 1); 990f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&after_position); 991f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) { 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(register_index >= num_saved_registers_); // Reserved for positions! 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(register_index), Immediate(to)); 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Succeed() { 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&success_label_); 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg, 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int cp_offset) { 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (cp_offset == 0) { 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(reg), edi); 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(edi, cp_offset * char_size())); 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(reg), eax); 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::ClearRegisters(int reg_from, int reg_to) { 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg_from <= reg_to); 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, Operand(ebp, kInputStartMinusOne)); 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int reg = reg_from; reg <= reg_to; reg++) { 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(reg), eax); 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, backtrack_stackpointer()); 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(eax, Operand(ebp, kStackHighEnd)); 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(reg), eax); 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Private methods: 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) { 10346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int num_arguments = 3; 10356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ PrepareCallCFunction(num_arguments, scratch); 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // RegExp code frame pointer. 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 2 * kPointerSize), ebp); 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Code* of self. 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 1 * kPointerSize), Immediate(masm_->CodeObject())); 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Next address on the stack (will be address of return address). 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(esp, -kPointerSize)); 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 0 * kPointerSize), eax); 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference check_stack_guard = 104444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::re_check_stack_guard_state(masm_->isolate()); 10456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallCFunction(check_stack_guard, num_arguments); 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper function for reading a value out of a stack frame. 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate <typename T> 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic T& frame_entry(Address re_frame, int frame_offset) { 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset)); 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address, 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* re_code, 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address re_frame) { 105944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate); 106044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(isolate == Isolate::Current()); 106144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (isolate->stack_guard()->IsStackOverflow()) { 106244f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate->StackOverflow(); 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return EXCEPTION; 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If not real stack overflow the stack guard was used to interrupt 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // execution for another purpose. 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1069e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If this is a direct call from JavaScript retry the RegExp forcing the call 1070e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // through the runtime system. Currently the direct call cannot handle a GC. 1071e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (frame_entry<int>(re_frame, kDirectCall) == 1) { 1072e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return RETRY; 1073e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 1074e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Prepare for possible GC. 107669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HandleScope handles(isolate); 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code_handle(re_code); 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); 108069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Current string. 108269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch bool is_ascii = subject->IsAsciiRepresentationUnderneath(); 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(re_code->instruction_start() <= *return_address); 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(*return_address <= 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block re_code->instruction_start() + re_code->instruction_size()); 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate); 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*code_handle != re_code) { // Return address no longer valid 109169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int delta = code_handle->address() - re_code->address(); 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Overwrite the return address on the stack. 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *return_address += delta; 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result->IsException()) { 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return EXCEPTION; 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 110069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Handle<String> subject_tmp = subject; 110169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int slice_offset = 0; 110269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 110369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Extract the underlying string and the slice offset. 110469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (StringShape(*subject_tmp).IsCons()) { 110569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); 110669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (StringShape(*subject_tmp).IsSliced()) { 110769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch SlicedString* slice = SlicedString::cast(*subject_tmp); 110869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch subject_tmp = Handle<String>(slice->parent()); 110969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch slice_offset = slice->offset(); 111069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 111169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // String might have changed. 111369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (subject_tmp->IsAsciiRepresentation() != is_ascii) { 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we changed between an ASCII and an UC16 string, the specialized 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code cannot be used, and we need to restart regexp matching from 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch (including, potentially, compiling a new version of the code). 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RETRY; 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Otherwise, the content of the string might have moved. It must still 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // be a sequential or external string with the same content. 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the start and end pointers in the stack frame to the current 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // location (whether it has actually moved or not). 112469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ASSERT(StringShape(*subject_tmp).IsSequential() || 112569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch StringShape(*subject_tmp).IsExternal()); 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The original start address of the characters to match. 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart); 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find the current start address of the same character at the current string 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // position. 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_index = frame_entry<int>(re_frame, kStartIndex); 113369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch const byte* new_address = StringCharacterPosition(*subject_tmp, 113469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch start_index + slice_offset); 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (start_address != new_address) { 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If there is a difference, update the object pointer and start and end 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // addresses in the RegExp stack frame to match the new value. 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd); 114069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int byte_length = static_cast<int>(end_address - start_address); 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const String*>(re_frame, kInputString) = *subject; 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const byte*>(re_frame, kInputStart) = new_address; 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length; 11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (frame_entry<const String*>(re_frame, kInputString) != *subject) { 11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Subject string might have been a ConsString that underwent 11463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // short-circuiting during GC. That will not change start_address but 11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // will change pointer inside the subject handle. 11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_entry<const String*>(re_frame, kInputString) = *subject; 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 0; 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand RegExpMacroAssemblerIA32::register_location(int register_index) { 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(register_index < (1<<30)); 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_registers_ <= register_index) { 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_registers_ = register_index + 1; 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(ebp, kRegisterZero - register_index * kPointerSize); 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckPosition(int cp_offset, 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_outside_input) { 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edi, -cp_offset * char_size()); 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater_equal, on_outside_input); 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition, 1172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* to) { 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (condition < 0) { // No condition 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (to == NULL) { 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Backtrack(); 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(to); 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (to == NULL) { 1182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(condition, &backtrack_label_); 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(condition, to); 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::SafeCall(Label* to) { 11906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label return_to; 11916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(Immediate::CodeRelativeOffset(&return_to)); 11926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ jmp(to); 11936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&return_to); 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::SafeReturn() { 11986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ebx); 11993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ebx, Immediate(masm_->CodeObject())); 12003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ebx); 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::SafeCallTarget(Label* name) { 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(name); 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Push(Register source) { 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!source.is(backtrack_stackpointer())); 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Push. 12123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(backtrack_stackpointer(), Immediate(kPointerSize)); 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(backtrack_stackpointer(), 0), source); 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Push(Immediate value) { 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Push. 12193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(backtrack_stackpointer(), Immediate(kPointerSize)); 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(backtrack_stackpointer(), 0), value); 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Pop(Register target) { 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!target.is(backtrack_stackpointer())); 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(target, Operand(backtrack_stackpointer(), 0)); 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Pop. 12283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(backtrack_stackpointer(), Immediate(kPointerSize)); 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckPreemption() { 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for preemption. 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label no_preempt; 1235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 123644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::address_of_stack_limit(masm_->isolate()); 1237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(esp, Operand::StaticVariable(stack_limit)); 1238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above, &no_preempt); 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCall(&check_preempt_label_); 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&no_preempt); 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckStackLimit() { 1247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label no_stack_overflow; 1248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 124944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::address_of_regexp_stack_limit(masm_->isolate()); 1250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(backtrack_stackpointer(), Operand::StaticVariable(stack_limit)); 1251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ j(above, &no_stack_overflow); 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SafeCall(&stack_overflow_label_); 1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&no_stack_overflow); 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset, 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int characters) { 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (characters == 4) { 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(current_character(), Operand(esi, edi, times_1, cp_offset)); 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (characters == 2) { 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_w(current_character(), Operand(esi, edi, times_1, cp_offset)); 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(characters == 1); 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset)); 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (characters == 2) { 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(current_character(), 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(characters == 1); 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_w(current_character(), 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif // V8_INTERPRETED_REGEXP 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}} // namespace v8::internal 1289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1290f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 1291