1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/regexp/ia32/regexp-macro-assembler-ia32.h" 8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/log.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/macro-assembler.h" 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/regexp/regexp-macro-assembler.h" 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/regexp/regexp-stack.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/unicode.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifndef V8_INTERPRETED_REGEXP 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * This assembler uses the following register assignment convention 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * - edx : Current character. Must be loaded using LoadCurrentCharacter 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * before using any of the dispatch methods. Temporarily stores the 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * index of capture start after a matching pass for a global regexp. 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * - edi : Current position in input, as negative offset from end of string. 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Please notice that this is the byte offset, not the character offset! 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - esi : end of input (points to byte after last character in input). 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * - ebp : Frame pointer. Used to access arguments, local variables and 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * RegExp registers. 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * - esp : Points to tip of C stack. 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * - ecx : Points to tip of backtrack stack 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 3225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen * The registers eax and ebx are free to use for computations. 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Each call to a public method should retain this convention. 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The stack will have the following structure: 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * - Isolate* isolate (address of the current isolate) 37e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - direct_call (if 1, direct call from JavaScript code, if 0 38e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * call through the runtime system) 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * - stack_area_base (high end of the memory area to use as 40e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * backtracking stack) 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * - capture array size (may fit multiple sets of matches) 42e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - int* capture_array (int[num_saved_registers_], for output). 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * - end of input (address of end of string) 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * - start of input (address of first character in string) 45e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - start index (character index of start) 46e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - String* input_string (location of a handle containing the string) 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * --- frame alignment (if applicable) --- 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - return address 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * ebp-> - old ebp 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - backup of caller esi 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - backup of caller edi 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - backup of caller ebx 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * - success counter (only for global regexps to count matches). 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - Offset of location before start of input (effectively character 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * string start - 1). Used to initialize capture registers to a 56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch * non-position. 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch * - register 0 ebp[-4] (only positions must be stored in the first 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - register 1 ebp[-8] num_saved_registers_ registers) 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - ... 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The first num_saved_registers_ registers are initialized to point to 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * "character -1" in the string (i.e., char_size() bytes before the first 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * character of the string). The remaining registers starts out as garbage. 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The data up to the return address must be placed there by the calling 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * code, by calling the code entry as cast to a function with the signature: 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * int (*match)(String* input_string, 68e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * int start_index, 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Address start, 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Address end, 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * int* capture_output_array, 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * bool at_start, 73e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * byte* stack_area_base, 74e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * bool direct_call) 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */ 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm_) 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(Isolate* isolate, Zone* zone, 80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Mode mode, 81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int registers_to_save) 82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : NativeRegExpMacroAssembler(isolate, zone), 83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch masm_(new MacroAssembler(isolate, NULL, kRegExpCodeSize, 84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CodeObjectRequired::kYes)), 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mode_(mode), 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_registers_(registers_to_save), 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_saved_registers_(registers_to_save), 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block entry_label_(), 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block start_label_(), 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block success_label_(), 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_label_(), 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block exit_label_() { 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0, registers_to_save % 2); 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&entry_label_); // We'll write the entry code later. 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&start_label_); // And then continue from here. 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() { 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete masm_; 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Unuse labels in case we throw away the assembler without calling GetCode. 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block entry_label_.Unuse(); 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block start_label_.Unuse(); 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block success_label_.Unuse(); 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_label_.Unuse(); 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block exit_label_.Unuse(); 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block check_preempt_label_.Unuse(); 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_overflow_label_.Unuse(); 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerIA32::stack_limit_slack() { 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RegExpStack::kStackLimitSlack; 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) { 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (by != 0) { 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edi, Immediate(by * char_size())); 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) { 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(reg >= 0); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(reg < num_registers_); 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (by != 0) { 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(register_location(reg), Immediate(by)); 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Backtrack() { 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPreemption(); 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop Code* offset from backtrack stack, add Code* and jump to location. 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(ebx); 1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ebx, Immediate(masm_->CodeObject())); 1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ebx); 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Bind(Label* label) { 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(label); 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) { 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), c); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_equal); 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) { 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), limit); 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater, on_greater); 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckAtStart(Label* on_at_start) { 160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(eax, Operand(edi, -char_size())); 161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, Operand(ebp, kStringStartMinusOne)); 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_at_start); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid RegExpMacroAssemblerIA32::CheckNotAtStart(int cp_offset, 167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* on_not_at_start) { 168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(eax, Operand(edi, -char_size() + cp_offset * char_size())); 169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, Operand(ebp, kStringStartMinusOne)); 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_at_start); 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) { 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), limit); 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(less, on_less); 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) { 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edi, Operand(backtrack_stackpointer(), 0)); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &fallthrough); 1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(backtrack_stackpointer(), Immediate(kPointerSize)); // Pop. 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, on_equal); 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase( 191342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch int start_reg, bool read_backward, bool unicode, Label* on_no_match) { 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, register_location(start_reg)); // Index of start of capture 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture 1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(ebx, edx); // Length of capture. 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // At this point, the capture registers are either both set or both cleared. 198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the capture length is zero, then the capture is either empty or cleared. 199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Fall through in both cases. 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &fallthrough); 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that there are sufficient characters left in the input. 203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (read_backward) { 204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, Operand(ebp, kStringStartMinusOne)); 205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(eax, ebx); 206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(edi, eax); 207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch BranchOrBacktrack(less_equal, on_no_match); 208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, edi); 210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(eax, ebx); 211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch BranchOrBacktrack(greater, on_no_match); 212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode_ == LATIN1) { 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label success; 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fail; 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop_increment; 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save register contents to make the registers available below. 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // After this, the eax, ecx, and edi registers are available. 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edx, esi); // Start of capture 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edi, esi); // Start of text to match against capture. 225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (read_backward) { 226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(edi, ebx); // Offset by length when matching backwards. 227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ebx, edi); // End of text to match against capture. 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop; 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(eax, Operand(edi, 0)); 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb_al(Operand(edx, 0)); 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &loop_increment); 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mismatch, try case-insensitive match (converting letters to lower-case). 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(eax, 0x20); // Convert match character to lower-case. 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(ecx, Operand(eax, -'a')); 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ecx, static_cast<int32_t>('z' - 'a')); // Is eax a lowercase letter? 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label convert_capture; 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below_equal, &convert_capture); // In range 'a'-'z'. 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Latin-1: Check for values in range [224,254] but not 247. 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(ecx, Immediate(224 - 'a')); 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ecx, Immediate(254 - 224)); 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above, &fail); // Weren't Latin-1 letters. 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ecx, Immediate(247 - 224)); // Check for 247. 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &fail); 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&convert_capture); 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Also convert capture character. 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(ecx, Operand(edx, 0)); 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(ecx, 0x20); 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(eax, ecx); 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &fail); 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop_increment); 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Increment pointers into match and capture strings. 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edx, Immediate(1)); 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edi, Immediate(1)); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare to end of match, and loop if not done. 2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(edi, ebx); 262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(below, &loop); 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&success); 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fail); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore original values before failing. 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, on_no_match); 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success); 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore original value before continuing. 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Drop original value of character position. 2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(esp, Immediate(kPointerSize)); 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute new value of character position after the matched part. 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(edi, esi); 278014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (read_backward) { 279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Subtract match length if we matched backward. 280014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(edi, register_location(start_reg)); 281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(edi, register_location(start_reg + 1)); 282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(mode_ == UC16); 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save registers before calling C function. 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(esi); 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static const int argument_count = 4; 2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ PrepareCallCFunction(argument_count, ecx); 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Put arguments into allocated stack area, last argument highest on stack. 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Parameters are 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Address byte_offset1 - Address captured substring's start. 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Address byte_offset2 - Address of current character position. 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // size_t byte_length - length of capture in bytes(!) 298342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch// Isolate* isolate or 0 if unicode flag. 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Set isolate. 301342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch#ifdef V8_I18N_SUPPORT 302342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if (unicode) { 303342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch __ mov(Operand(esp, 3 * kPointerSize), Immediate(0)); 304342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch } else // NOLINT 305342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch#endif // V8_I18N_SUPPORT 306342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch { 307342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch __ mov(Operand(esp, 3 * kPointerSize), 308342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch Immediate(ExternalReference::isolate_address(isolate()))); 309342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch } 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_length. 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 2 * kPointerSize), ebx); 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_offset2. 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Found by adding negative string-end offset of current position (edi) 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to end of string. 3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edi, esi); 316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (read_backward) { 317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(edi, ebx); // Offset by length when matching backwards. 318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 1 * kPointerSize), edi); 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_offset1. 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Start of capture, where edx already holds string-end negative offset. 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edx, esi); 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 0 * kPointerSize), edx); 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm_); 3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference compare = 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::re_case_insensitive_compare_uc16(isolate()); 3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(compare, argument_count); 3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop original values before reacting on result value. 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(esi); 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if function returned non-zero for success or zero for failure. 3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ or_(eax, eax); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(zero, on_no_match); 340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // On success, advance position by length of capture. 341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (read_backward) { 342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(edi, ebx); 343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(edi, ebx); 345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid RegExpMacroAssemblerIA32::CheckNotBackReference(int start_reg, 352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch bool read_backward, 353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label* on_no_match) { 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label success; 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fail; 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find length of back-referenced capture. 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edx, register_location(start_reg)); 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, register_location(start_reg + 1)); 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(eax, edx); // Length to check. 362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // At this point, the capture registers are either both set or both cleared. 364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the capture length is zero, then the capture is either empty or cleared. 365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Fall through in both cases. 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &fallthrough); 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that there are sufficient characters left in the input. 369014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (read_backward) { 370014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, Operand(ebp, kStringStartMinusOne)); 371014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(ebx, eax); 372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(edi, ebx); 373014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch BranchOrBacktrack(less_equal, on_no_match); 374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(ebx, edi); 376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(ebx, eax); 377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch BranchOrBacktrack(greater, on_no_match); 378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save register to make it available below. 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute pointers to match string and capture string 3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edx, esi); // Start of capture. 385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match. 386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (read_backward) { 387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(ebx, eax); // Offset by length when matching backwards. 388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop; 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode_ == LATIN1) { 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(eax, Operand(edx, 0)); 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb_al(Operand(ebx, 0)); 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(mode_ == UC16); 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_w(eax, Operand(edx, 0)); 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpw_ax(Operand(ebx, 0)); 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &fail); 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Increment pointers into capture and match string. 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(edx, Immediate(char_size())); 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ebx, Immediate(char_size())); 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if we have reached end of match area. 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(ebx, ecx); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &loop); 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&success); 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fail); 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore backtrack stackpointer. 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, on_no_match); 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success); 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move current character position to position after match. 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, ecx); 4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(edi, esi); 419014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (read_backward) { 420014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Subtract match length if we matched backward. 421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(edi, register_location(start_reg)); 422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ sub(edi, register_location(start_reg + 1)); 423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore backtrack stackpointer. 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotCharacter(uint32_t c, 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), c); 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckCharacterAfterAnd(uint32_t c, 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t mask, 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_equal) { 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (c == 0) { 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(current_character(), Immediate(mask)); 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, mask); 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(eax, current_character()); 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, c); 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_equal); 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotCharacterAfterAnd(uint32_t c, 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t mask, 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (c == 0) { 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(current_character(), Immediate(mask)); 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, mask); 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(eax, current_character()); 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, c); 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusAnd( 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 c, 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 minus, 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 mask, 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(minus < String::kMaxUtf16CodeUnit); 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(current_character(), -minus)); 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (c == 0) { 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(eax, Immediate(mask)); 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(eax, mask); 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, c); 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RegExpMacroAssemblerIA32::CheckCharacterInRange( 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uc16 from, 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uc16 to, 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* on_in_range) { 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(eax, Operand(current_character(), -from)); 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, to - from); 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BranchOrBacktrack(below_equal, on_in_range); 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RegExpMacroAssemblerIA32::CheckCharacterNotInRange( 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uc16 from, 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uc16 to, 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* on_not_in_range) { 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(eax, Operand(current_character(), -from)); 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, to - from); 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BranchOrBacktrack(above, on_not_in_range); 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid RegExpMacroAssemblerIA32::CheckBitInTable( 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<ByteArray> table, 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* on_bit_set) { 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Immediate(table)); 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index = current_character(); 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) { 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, kTableSize - 1); 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(ebx, current_character()); 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch index = ebx; 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5131b268ca467c924004286c97bac133db489cf43d0Ben Murdoch __ cmpb(FieldOperand(eax, index, times_1, ByteArray::kHeaderSize), 5141b268ca467c924004286c97bac133db489cf43d0Ben Murdoch Immediate(0)); 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BranchOrBacktrack(not_equal, on_bit_set); 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type, 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Range checks (c in min..max) are generally implemented by an unsigned 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (c - min) <= (max - min) check 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (type) { 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 's': 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match space-characters 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode_ == LATIN1) { 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // One byte space characters are '\t'..'\r', ' ' and \u00a0. 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label success; 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(current_character(), ' '); 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &success, Label::kNear); 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check range 0x09..0x0d 532e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(eax, Operand(current_character(), -'\t')); 533e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, '\r' - '\t'); 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below_equal, &success, Label::kNear); 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // \u00a0 (NBSP). 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, 0x00a0 - '\t'); 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BranchOrBacktrack(not_equal, on_no_match); 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success); 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'S': 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The emitted code for generic character classes is good enough. 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'd': 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match ASCII digits ('0'..'9') 547e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(eax, Operand(current_character(), -'0')); 548e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, '9' - '0'); 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(above, on_no_match); 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'D': 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non ASCII-digits 553e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(eax, Operand(current_character(), -'0')); 554e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, '9' - '0'); 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case '.': { 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) 5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(eax, current_character()); 5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xor_(eax, Immediate(0x01)); 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(eax, Immediate(0x0b)); 563e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, 0x0c - 0x0b); 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == UC16) { 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare original value to 0x2028 and 0x2029, using the already 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // computed (current_char ^ 0x01 - 0x0b). I.e., check for 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 0x201d (0x2028 - 0x0b) or 0x201e. 5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(eax, Immediate(0x2028 - 0x0b)); 570e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, 0x2029 - 0x2028); 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 575e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'w': { 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode_ != LATIN1) { 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Table is 256 entries, so all Latin1 characters can be tested. 5783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(current_character(), Immediate('z')); 579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(above, on_no_match); 580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0, word_character_map[0]); // Character '\0' is not a word char. 582e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference word_map = ExternalReference::re_word_character_map(); 583e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test_b(current_character(), 584e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Operand::StaticArray(current_character(), times_1, word_map)); 585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(zero, on_no_match); 586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 587e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 588e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'W': { 589e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode_ != LATIN1) { 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Table is 256 entries, so all Latin1 characters can be tested. 5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmp(current_character(), Immediate('z')); 593e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(above, &done); 594e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0, word_character_map[0]); // Character '\0' is not a word char. 596e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference word_map = ExternalReference::re_word_character_map(); 597e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ test_b(current_character(), 598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Operand::StaticArray(current_character(), times_1, word_map)); 599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(not_zero, on_no_match); 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode_ != LATIN1) { 601e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&done); 602e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Non-standard classes (with no syntactic shorthand) used internally. 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case '*': 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match any character. 608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'n': { 610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029). 611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // The opposite of '.'. 6123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(eax, current_character()); 6133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ xor_(eax, Immediate(0x01)); 614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 6153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(eax, Immediate(0x0b)); 616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, 0x0c - 0x0b); 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode_ == LATIN1) { 618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(above, on_no_match); 619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(below_equal, &done); 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(UC16, mode_); 623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Compare original value to 0x2028 and 0x2029, using the already 624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // computed (current_char ^ 0x01 - 0x0b). I.e., check for 625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // 0x201d (0x2028 - 0x0b) or 0x201e. 6263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(eax, Immediate(0x2028 - 0x0b)); 627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmp(eax, 1); 628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(above, on_no_match); 629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&done); 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // No custom implementation (yet): s(UC16), S(UC16). 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Fail() { 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(FAILURE == 0); // Return value for failure is zero. 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!global()) { 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(eax, Immediate(FAILURE)); 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 649053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve BlockHandle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label return_eax; 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Finalize code - write the entry point code now we know how many 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // registers we need. 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Entry code: 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry_label_); 6563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Tell the system that we have a stack frame. Because the type is MANUAL, no 6583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // code is generated. 6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm_, StackFrame::MANUAL); 6603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Actually emit code to start a new stack frame. 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebp); 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebp, esp); 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save callee-save registers. Order here should correspond to order of 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // kBackup_ebx etc. 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(esi); 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(ebx); // Callee-save on MacOS. 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Immediate(0)); // Number of successful matches in a global regexp. 670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ push(Immediate(0)); // Make room for "string start - 1" constant. 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if we have space on the stack for registers. 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label stack_limit_hit; 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label stack_ok; 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_stack_limit(isolate()); 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ecx, esp); 679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ sub(ecx, Operand::StaticVariable(stack_limit)); 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle it if the stack pointer is already below the stack limit. 681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(below_equal, &stack_limit_hit); 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if there is room for the variable number of registers above 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the stack limit. 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(ecx, num_registers_ * kPointerSize); 685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &stack_ok); 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit with OutOfMemory exception. There is not enough space on the stack 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for our working registers. 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, EXCEPTION); 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&return_eax); 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&stack_limit_hit); 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCheckStackGuardState(ebx); 6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ or_(eax, eax); 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If returned value is non-zero, we exit with the returned value as result. 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &return_eax); 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&stack_ok); 6986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Load start index for later use. 6996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(ebx, Operand(ebp, kStartIndex)); 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate space on stack for registers. 7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(esp, Immediate(num_registers_ * kPointerSize)); 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load string length. 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(esi, Operand(ebp, kInputEnd)); 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load input position. 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, Operand(ebp, kInputStart)); 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set up edi to be negative offset from string end. 7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(edi, esi); 7096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 7106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Set eax to address of char before start of the string. 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (effectively string position -1). 7126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ neg(ebx); 7136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (mode_ == UC16) { 7146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(eax, Operand(edi, ebx, times_2, -char_size())); 7156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 7166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(eax, Operand(edi, ebx, times_1, -char_size())); 7176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store this value in a local variable, for use when clearing 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // position registers. 720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand(ebp, kStringStartMinusOne), eax); 721d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_OS_WIN 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Ensure that we write to each stack page, in order. Skipping a page 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // on Windows can cause segmentation faults. Assuming page size is 4k. 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kPageSize = 4096; 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kRegistersPerPage = kPageSize / kPointerSize; 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = num_saved_registers_ + kRegistersPerPage - 1; 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i < num_registers_; 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i += kRegistersPerPage) { 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(i), eax); // One write every page. 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_OS_WIN 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label load_char_start_regexp, start_regexp; 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load newline if index is at start, previous character otherwise. 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(Operand(ebp, kStartIndex), Immediate(0)); 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &load_char_start_regexp, Label::kNear); 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(current_character(), '\n'); 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&start_regexp, Label::kNear); 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Global regexp restarts matching here. 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&load_char_start_regexp); 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load previous char as initial value of current character register. 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadCurrentCharacterUnchecked(-1, 1); 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&start_regexp); 746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initialize on-stack registers. 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fill saved registers with initial value = start offset - 1 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fill in stack push order, to avoid accessing across an unwritten 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // page (a problem on Windows). 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (num_saved_registers_ > 8) { 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, kRegisterZero); 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label init_loop; 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&init_loop); 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(ebp, ecx, times_1, 0), eax); 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(ecx, Immediate(kPointerSize)); 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize); 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(greater, &init_loop); 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { // Unroll the loop. 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < num_saved_registers_; i++) { 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(register_location(i), eax); 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize backtrack stack pointer. 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd)); 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&start_label_); 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit code: 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (success_label_.is_linked()) { 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save captures when successful. 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success_label_); 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_saved_registers_ > 0) { 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // copy captures to output 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ebx, Operand(ebp, kRegisterOutput)); 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(ecx, Operand(ebp, kInputEnd)); 7806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ mov(edx, Operand(ebp, kStartIndex)); 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(ecx, Operand(ebp, kInputStart)); 7826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (mode_ == UC16) { 7836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(ecx, Operand(ecx, edx, times_2, 0)); 7846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ecx, edx); 7866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < num_saved_registers_; i++) { 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, register_location(i)); 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (i == 0 && global_with_zero_length_check()) { 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Keep capture start in edx for the zero-length check later. 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(edx, eax); 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 7936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Convert to index from start of string, not end. 7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(eax, ecx); 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == UC16) { 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sar(eax, 1); // Convert byte index to character index. 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(ebx, i * kPointerSize), eax); 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (global()) { 803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Restart matching if the regular expression is flagged as global. 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Increment success counter. 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ inc(Operand(ebp, kSuccessfulCaptures)); 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Capture results have been stored, so the number of remaining global 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // output registers is reduced by the number of stored captures. 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, Operand(ebp, kNumOutputRegisters)); 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(ecx, Immediate(num_saved_registers_)); 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check whether we have enough room for another set of capture results. 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ecx, Immediate(num_saved_registers_)); 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(less, &exit_label_); 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(ebp, kNumOutputRegisters), ecx); 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Advance the location for output. 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(Operand(ebp, kRegisterOutput), 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(num_saved_registers_ * kPointerSize)); 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Prepare eax to initialize registers with its value in the next run. 820014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, Operand(ebp, kStringStartMinusOne)); 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (global_with_zero_length_check()) { 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Special case for zero-length matches. 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // edx: capture start index 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(edi, edx); 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Not a zero-length match, restart. 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &load_char_start_regexp); 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // edi (offset from the end) is zero if we already reached the end. 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(edi, edi); 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &exit_label_, Label::kNear); 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Advance current position after a zero-length match. 832342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch Label advance; 833342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch __ bind(&advance); 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode_ == UC16) { 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(edi, Immediate(2)); 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ inc(edi); 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 839342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if (global_unicode()) CheckNotInSurrogatePair(0, &advance); 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&load_char_start_regexp); 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Immediate(SUCCESS)); 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit_label_); 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (global()) { 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the number of successful captures. 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Operand(ebp, kSuccessfulCaptures)); 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&return_eax); 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip esp past regexp registers. 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(esp, Operand(ebp, kBackup_ebx)); 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore callee-save registers. 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebx); 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(esi); 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit function frame, restore previous one. 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(ebp); 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Backtrack code (branch target for conditional backtracks). 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (backtrack_label_.is_linked()) { 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&backtrack_label_); 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Backtrack(); 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label exit_with_exception; 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preempt-code 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_preempt_label_.is_linked()) { 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCallTarget(&check_preempt_label_); 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCheckStackGuardState(ebx); 8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ or_(eax, eax); 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If returning non-zero, we should end execution with the given 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result as return value. 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &return_eax); 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // String might have moved: Reload esi from frame. 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(esi, Operand(ebp, kInputEnd)); 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeReturn(); 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Backtrack stack overflow code. 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (stack_overflow_label_.is_linked()) { 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCallTarget(&stack_overflow_label_); 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reached if the backtrack-stack limit has been hit. 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label grow_failed; 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save registers before calling C function 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(esi); 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(edi); 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call GrowStack(backtrack_stackpointer()) 9038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static const int num_arguments = 3; 9046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ PrepareCallCFunction(num_arguments, ebx); 9058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ mov(Operand(esp, 2 * kPointerSize), 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(ExternalReference::isolate_address(isolate()))); 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(ebp, kStackHighEnd)); 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 1 * kPointerSize), eax); 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer()); 91044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference grow_stack = 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::re_grow_stack(isolate()); 9126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallCFunction(grow_stack, num_arguments); 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If return NULL, we have failed to grow the stack, and 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // must exit with a stack-overflow exception. 9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ or_(eax, eax); 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &exit_with_exception); 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Otherwise use return value as new stack pointer. 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(backtrack_stackpointer(), eax); 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore saved registers and continue. 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(edi); 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(esi); 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeReturn(); 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (exit_with_exception.is_linked()) { 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If any of the code above needed to exit with an exception. 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit_with_exception); 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit with Result EXCEPTION(-1) to signal thrown exception. 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, EXCEPTION); 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&return_eax); 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CodeDesc code_desc; 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm_->GetCode(&code_desc); 93544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> code = 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->factory()->NewCode(code_desc, 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::ComputeFlags(Code::REGEXP), 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm_->CodeObject()); 9391b268ca467c924004286c97bac133db489cf43d0Ben Murdoch PROFILE(masm_->isolate(), 9401b268ca467c924004286c97bac133db489cf43d0Ben Murdoch RegExpCodeCreateEvent(AbstractCode::cast(*code), *source)); 941053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block return Handle<HeapObject>::cast(code); 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::GoTo(Label* to) { 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, to); 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::IfRegisterGE(int reg, 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int comparand, 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_ge) { 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(register_location(reg), Immediate(comparand)); 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater_equal, if_ge); 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::IfRegisterLT(int reg, 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int comparand, 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_lt) { 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(register_location(reg), Immediate(comparand)); 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(less, if_lt); 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::IfRegisterEqPos(int reg, 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_eq) { 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmp(edi, register_location(reg)); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, if_eq); 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssembler::IrregexpImplementation 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegExpMacroAssemblerIA32::Implementation() { 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return kIA32Implementation; 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset, 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_end_of_input, 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool check_bounds, 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int characters) { 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works) 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_bounds) { 985014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (cp_offset >= 0) { 986014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CheckPosition(cp_offset + characters - 1, on_end_of_input); 987014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 988014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CheckPosition(cp_offset, on_end_of_input); 989014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(cp_offset, characters); 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PopCurrentPosition() { 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(edi); 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PopRegister(int register_index) { 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(eax); 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(register_index), eax); 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PushBacktrack(Label* label) { 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(Immediate::CodeRelativeOffset(label)); 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckStackLimit(); 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PushCurrentPosition() { 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(edi); 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::PushRegister(int register_index, 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackCheckFlag check_stack_limit) { 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, register_location(register_index)); 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(eax); 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_stack_limit) CheckStackLimit(); 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) { 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(edi, register_location(reg)); 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) { 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(backtrack_stackpointer(), register_location(reg)); 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ add(backtrack_stackpointer(), Operand(ebp, kStackHighEnd)); 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1035f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid RegExpMacroAssemblerIA32::SetCurrentPositionFromEnd(int by) { 1036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label after_position; 1037f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ cmp(edi, -by * char_size()); 1038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(greater_equal, &after_position, Label::kNear); 1039f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ mov(edi, -by * char_size()); 1040f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // On RegExp code entry (where this operation is used), the character before 1041f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // the current position is expected to be already loaded. 1042f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // We have advanced the position, so it's safe to read backwards. 1043f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch LoadCurrentCharacterUnchecked(-1, 1); 1044f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&after_position); 1045f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) { 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(register_index >= num_saved_registers_); // Reserved for positions! 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(register_index), Immediate(to)); 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool RegExpMacroAssemblerIA32::Succeed() { 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&success_label_); 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return global(); 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg, 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int cp_offset) { 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (cp_offset == 0) { 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(reg), edi); 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(edi, cp_offset * char_size())); 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(reg), eax); 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::ClearRegisters(int reg_from, int reg_to) { 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(reg_from <= reg_to); 1073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(eax, Operand(ebp, kStringStartMinusOne)); 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int reg = reg_from; reg <= reg_to; reg++) { 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(reg), eax); 1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) { 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(eax, backtrack_stackpointer()); 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sub(eax, Operand(ebp, kStackHighEnd)); 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(register_location(reg), eax); 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Private methods: 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) { 10906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int num_arguments = 3; 10916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ PrepareCallCFunction(num_arguments, scratch); 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // RegExp code frame pointer. 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 2 * kPointerSize), ebp); 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Code* of self. 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 1 * kPointerSize), Immediate(masm_->CodeObject())); 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Next address on the stack (will be address of return address). 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(eax, Operand(esp, -kPointerSize)); 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(esp, 0 * kPointerSize), eax); 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference check_stack_guard = 1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::re_check_stack_guard_state(isolate()); 11016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CallCFunction(check_stack_guard, num_arguments); 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper function for reading a value out of a stack frame. 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate <typename T> 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic T& frame_entry(Address re_frame, int frame_offset) { 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset)); 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <typename T> 1113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic T* frame_entry_address(Address re_frame, int frame_offset) { 1114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return reinterpret_cast<T*>(re_frame + frame_offset); 1115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 1116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address, 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* re_code, 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address re_frame) { 1121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return NativeRegExpMacroAssembler::CheckStackGuardState( 1122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch frame_entry<Isolate*>(re_frame, kIsolate), 1123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch frame_entry<int>(re_frame, kStartIndex), 1124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code, 1125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch frame_entry_address<String*>(re_frame, kInputString), 1126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch frame_entry_address<const byte*>(re_frame, kInputStart), 1127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch frame_entry_address<const byte*>(re_frame, kInputEnd)); 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand RegExpMacroAssemblerIA32::register_location(int register_index) { 1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(register_index < (1<<30)); 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_registers_ <= register_index) { 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_registers_ = register_index + 1; 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(ebp, kRegisterZero - register_index * kPointerSize); 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckPosition(int cp_offset, 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_outside_input) { 1142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (cp_offset >= 0) { 1143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(edi, -cp_offset * char_size()); 1144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch BranchOrBacktrack(greater_equal, on_outside_input); 1145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 1146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ lea(eax, Operand(edi, cp_offset * char_size())); 1147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(eax, Operand(ebp, kStringStartMinusOne)); 1148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch BranchOrBacktrack(less_equal, on_outside_input); 1149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition, 1154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* to) { 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (condition < 0) { // No condition 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (to == NULL) { 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Backtrack(); 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(to); 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (to == NULL) { 1164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(condition, &backtrack_label_); 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(condition, to); 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::SafeCall(Label* to) { 11726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label return_to; 11736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ push(Immediate::CodeRelativeOffset(&return_to)); 11746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ jmp(to); 11756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&return_to); 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::SafeReturn() { 11806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ pop(ebx); 11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(ebx, Immediate(masm_->CodeObject())); 11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ebx); 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::SafeCallTarget(Label* name) { 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(name); 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Push(Register source) { 1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!source.is(backtrack_stackpointer())); 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Push. 11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(backtrack_stackpointer(), Immediate(kPointerSize)); 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(backtrack_stackpointer(), 0), source); 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Push(Immediate value) { 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Push. 12013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sub(backtrack_stackpointer(), Immediate(kPointerSize)); 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(Operand(backtrack_stackpointer(), 0), value); 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::Pop(Register target) { 1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!target.is(backtrack_stackpointer())); 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(target, Operand(backtrack_stackpointer(), 0)); 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Pop. 12103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ add(backtrack_stackpointer(), Immediate(kPointerSize)); 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckPreemption() { 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for preemption. 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label no_preempt; 1217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_stack_limit(isolate()); 1219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(esp, Operand::StaticVariable(stack_limit)); 1220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above, &no_preempt); 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCall(&check_preempt_label_); 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&no_preempt); 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::CheckStackLimit() { 1229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label no_stack_overflow; 1230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_regexp_stack_limit(isolate()); 1232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmp(backtrack_stackpointer(), Operand::StaticVariable(stack_limit)); 1233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ j(above, &no_stack_overflow); 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SafeCall(&stack_overflow_label_); 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&no_stack_overflow); 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset, 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int characters) { 1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode_ == LATIN1) { 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (characters == 4) { 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(current_character(), Operand(esi, edi, times_1, cp_offset)); 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (characters == 2) { 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_w(current_character(), Operand(esi, edi, times_1, cp_offset)); 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(characters == 1); 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset)); 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(mode_ == UC16); 1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (characters == 2) { 1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ mov(current_character(), 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(characters == 1); 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzx_w(current_character(), 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(esi, edi, times_1, cp_offset * sizeof(uc16))); 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif // V8_INTERPRETED_REGEXP 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 1271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 1272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1273f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_IA32 1274