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