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