115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
2a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// Redistribution and use in source and binary forms, with or without
3a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// modification, are permitted provided that the following conditions are
4a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// met:
5a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//
6a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//     * Redistributions of source code must retain the above copyright
7a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//       notice, this list of conditions and the following disclaimer.
8a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//     * Redistributions in binary form must reproduce the above
9a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//       copyright notice, this list of conditions and the following
10a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//       disclaimer in the documentation and/or other materials provided
11a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//       with the distribution.
12a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//     * Neither the name of Google Inc. nor the names of its
13a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//       contributors may be used to endorse or promote products derived
14a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//       from this software without specific prior written permission.
15a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org//
16a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
28a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include "v8.h"
299dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
3093a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_IA32
319dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
32c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org#include "cpu-profiler.h"
338bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org#include "unicode.h"
34a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include "log.h"
353291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org#include "regexp-stack.h"
36a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include "macro-assembler.h"
37a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#include "regexp-macro-assembler.h"
383a37e9b96c768f6b5b6b09542e1cb1a1ece7a022ager@chromium.org#include "ia32/regexp-macro-assembler-ia32.h"
39a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4071affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
4171affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace internal {
42a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
43c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org#ifndef V8_INTERPRETED_REGEXP
44a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org/*
45a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org * This assembler uses the following register assignment convention
4615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org * - edx : Current character.  Must be loaded using LoadCurrentCharacter
4715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *         before using any of the dispatch methods.  Temporarily stores the
4815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *         index of capture start after a matching pass for a global regexp.
4915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org * - edi : Current position in input, as negative offset from end of string.
50a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org *         Please notice that this is the byte offset, not the character offset!
51a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org * - esi : end of input (points to byte after last character in input).
5215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org * - ebp : Frame pointer.  Used to access arguments, local variables and
53bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org *         RegExp registers.
5415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org * - esp : Points to tip of C stack.
5515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org * - ecx : Points to tip of backtrack stack
56a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org *
57dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org * The registers eax and ebx are free to use for computations.
58a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org *
59a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org * Each call to a public method should retain this convention.
60a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org * The stack will have the following structure:
6115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *       - Isolate* isolate     (address of the current isolate)
620c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org *       - direct_call          (if 1, direct call from JavaScript code, if 0
630c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org *                               call through the runtime system)
6415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *       - stack_area_base      (high end of the memory area to use as
650c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org *                               backtracking stack)
6615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *       - capture array size   (may fit multiple sets of matches)
670c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org *       - int* capture_array   (int[num_saved_registers_], for output).
6815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *       - end of input         (address of end of string)
6915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *       - start of input       (address of first character in string)
700c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org *       - start index          (character index of start)
710c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org *       - String* input_string (location of a handle containing the string)
72bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org *       --- frame alignment (if applicable) ---
73a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org *       - return address
74a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org * ebp-> - old ebp
753291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org *       - backup of caller esi
763291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org *       - backup of caller edi
773291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org *       - backup of caller ebx
7815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *       - success counter      (only for global regexps to count matches).
79bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org *       - Offset of location before start of input (effectively character
80bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org *         position -1). Used to initialize capture registers to a non-position.
8115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org *       - register 0  ebp[-4]  (only positions must be stored in the first
82a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org *       - register 1  ebp[-8]   num_saved_registers_ registers)
83a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org *       - ...
84a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org *
85a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org * The first num_saved_registers_ registers are initialized to point to
86a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org * "character -1" in the string (i.e., char_size() bytes before the first
87a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org * character of the string). The remaining registers starts out as garbage.
88a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org *
89a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org * The data up to the return address must be placed there by the calling
90911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org * code, by calling the code entry as cast to a function with the signature:
91bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org * int (*match)(String* input_string,
920c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org *              int start_index,
93bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org *              Address start,
94bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org *              Address end,
95bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org *              int* capture_output_array,
96bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org *              bool at_start,
970c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org *              byte* stack_area_base,
980c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org *              bool direct_call)
99a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org */
100a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
10165dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org#define __ ACCESS_MASM(masm_)
102a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
103a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(
104a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Mode mode,
1057028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    int registers_to_save,
1067028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    Zone* zone)
1077028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org    : NativeRegExpMacroAssembler(zone),
1081fd77d58ca66b2711f09cdea32c0c2d1a01b3ae5danno@chromium.org      masm_(new MacroAssembler(zone->isolate(), NULL, kRegExpCodeSize)),
109a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      mode_(mode),
110a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      num_registers_(registers_to_save),
111a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      num_saved_registers_(registers_to_save),
112a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      entry_label_(),
113a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      start_label_(),
114a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      success_label_(),
11537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      backtrack_label_(),
116061ef74c9b8acd038edf4b4355c50d097c8a9683kasperl@chromium.org      exit_label_() {
11718ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ASSERT_EQ(0, registers_to_save % 2);
118a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ jmp(&entry_label_);   // We'll write the entry code later.
119a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ bind(&start_label_);  // And then continue from here.
120a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
121a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
122a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
123a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() {
124a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  delete masm_;
125a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Unuse labels in case we throw away the assembler without calling GetCode.
126a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  entry_label_.Unuse();
127a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  start_label_.Unuse();
128a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  success_label_.Unuse();
12937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  backtrack_label_.Unuse();
130a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  exit_label_.Unuse();
13137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  check_preempt_label_.Unuse();
1323291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  stack_overflow_label_.Unuse();
1333291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org}
1343291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
1353291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
1363291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgint RegExpMacroAssemblerIA32::stack_limit_slack()  {
1373291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  return RegExpStack::kStackLimitSlack;
138a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
139a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
140a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
141a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) {
1428bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  if (by != 0) {
143c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(edi, Immediate(by * char_size()));
1448bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  }
145a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
146a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
147a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
148a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) {
149a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ASSERT(reg >= 0);
150a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ASSERT(reg < num_registers_);
1513291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  if (by != 0) {
1523291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ add(register_location(reg), Immediate(by));
1533291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  }
154a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
155a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
156a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
157a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::Backtrack() {
1583291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  CheckPreemption();
1593291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Pop Code* offset from backtrack stack, add Code* and jump to location.
1603291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  Pop(ebx);
161c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(ebx, Immediate(masm_->CodeObject()));
162c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ jmp(ebx);
163a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
164a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
165a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
166a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::Bind(Label* label) {
167a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ bind(label);
168a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
169a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1703291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
17137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) {
172a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ cmp(current_character(), c);
173a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  BranchOrBacktrack(equal, on_equal);
174a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
175a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
176a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
177a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) {
178a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ cmp(current_character(), limit);
179a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  BranchOrBacktrack(greater, on_greater);
180a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
181a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
182a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
183ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.orgvoid RegExpMacroAssemblerIA32::CheckAtStart(Label* on_at_start) {
184bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  Label not_at_start;
185ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org  // Did we start the match at the start of the string at all?
186dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org  __ cmp(Operand(ebp, kStartIndex), Immediate(0));
187dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org  BranchOrBacktrack(not_equal, &not_at_start);
188ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org  // If we did, are we still at the start of the input?
189bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  __ lea(eax, Operand(esi, edi, times_1, 0));
190bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  __ cmp(eax, Operand(ebp, kInputStart));
191ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org  BranchOrBacktrack(equal, on_at_start);
192bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  __ bind(&not_at_start);
193ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org}
194ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
195ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
196a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::CheckNotAtStart(Label* on_not_at_start) {
1973291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Did we start the match at the start of the string at all?
198dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org  __ cmp(Operand(ebp, kStartIndex), Immediate(0));
199dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org  BranchOrBacktrack(not_equal, on_not_at_start);
2003291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // If we did, are we still at the start of the input?
201bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  __ lea(eax, Operand(esi, edi, times_1, 0));
202bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  __ cmp(eax, Operand(ebp, kInputStart));
203a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  BranchOrBacktrack(not_equal, on_not_at_start);
204a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
205a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
206a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
207a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) {
208a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ cmp(current_character(), limit);
209a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  BranchOrBacktrack(less, on_less);
210a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
211a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
212a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
2138bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.orgvoid RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) {
2148bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  Label fallthrough;
2153291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ cmp(edi, Operand(backtrack_stackpointer(), 0));
216bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  __ j(not_equal, &fallthrough);
217c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(backtrack_stackpointer(), Immediate(kPointerSize));  // Pop.
2188bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  BranchOrBacktrack(no_condition, on_equal);
2198bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  __ bind(&fallthrough);
220a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
221a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
222a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
223a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
2248bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    int start_reg,
2258bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    Label* on_no_match) {
226a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Label fallthrough;
2273291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(edx, register_location(start_reg));  // Index of start of capture
2283291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(ebx, register_location(start_reg + 1));  // Index of end of capture
229c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(ebx, edx);  // Length of capture.
2303291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
2313291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // The length of a capture should not be negative. This can only happen
2323291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // if the end of the capture is unrecorded, or at a point earlier than
2333291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // the start of the capture.
2347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  BranchOrBacktrack(less, on_no_match);
2353291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
2363291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // If length is zero, either the capture is empty or it is completely
2373291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // uncaptured. In either case succeed immediately.
238a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ j(equal, &fallthrough);
239a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
2405a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  // Check that there are sufficient characters left in the input.
2415a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ mov(eax, edi);
2425a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  __ add(eax, ebx);
2435a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  BranchOrBacktrack(greater, on_no_match);
2445a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org
2458bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  if (mode_ == ASCII) {
2468bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    Label success;
2478bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    Label fail;
24837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    Label loop_increment;
2493291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Save register contents to make the registers available below.
2508bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    __ push(edi);
2513291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ push(backtrack_stackpointer());
252245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    // After this, the eax, ecx, and edi registers are available.
2533291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
254c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(edx, esi);  // Start of capture
255c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(edi, esi);  // Start of text to match against capture.
256c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(ebx, edi);  // End of text to match against capture.
25737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
2588bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    Label loop;
2598bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    __ bind(&loop);
26037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    __ movzx_b(eax, Operand(edi, 0));
26137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    __ cmpb_al(Operand(edx, 0));
262bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    __ j(equal, &loop_increment);
26337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
2643291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Mismatch, try case-insensitive match (converting letters to lower-case).
2653291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ or_(eax, 0x20);  // Convert match character to lower-case.
2663291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ lea(ecx, Operand(eax, -'a'));
2673291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ cmp(ecx, static_cast<int32_t>('z' - 'a'));  // Is eax a lowercase letter?
26859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    Label convert_capture;
26959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ j(below_equal, &convert_capture);  // In range 'a'-'z'.
27059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    // Latin-1: Check for values in range [224,254] but not 247.
27159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ sub(ecx, Immediate(224 - 'a'));
27259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ cmp(ecx, Immediate(254 - 224));
27359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ j(above, &fail);  // Weren't Latin-1 letters.
27459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ cmp(ecx, Immediate(247 - 224));  // Check for 247.
27559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ j(equal, &fail);
27659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    __ bind(&convert_capture);
2773291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Also convert capture character.
2783291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ movzx_b(ecx, Operand(edx, 0));
2793291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ or_(ecx, 0x20);
2803291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
281c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmp(eax, ecx);
282bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    __ j(not_equal, &fail);
28337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
28437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    __ bind(&loop_increment);
2853291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Increment pointers into match and capture strings.
286c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(edx, Immediate(1));
287c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(edi, Immediate(1));
2883291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Compare to end of match, and loop if not done.
289c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ cmp(edi, ebx);
2907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ j(below, &loop);
291bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com    __ jmp(&success);
2928bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org
2938bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    __ bind(&fail);
2943291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Restore original values before failing.
2953291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ pop(backtrack_stackpointer());
2968bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    __ pop(edi);
2978bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    BranchOrBacktrack(no_condition, on_no_match);
298a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
2998bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    __ bind(&success);
3003291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Restore original value before continuing.
3013291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ pop(backtrack_stackpointer());
3023291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Drop original value of character position.
303c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(esp, Immediate(kPointerSize));
3043291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Compute new value of character position after the matched part.
305c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sub(edi, esi);
3068bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  } else {
30737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    ASSERT(mode_ == UC16);
3083291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Save registers before calling C function.
3098bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    __ push(esi);
3108bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    __ push(edi);
3113291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ push(backtrack_stackpointer());
3123291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ push(ebx);
313bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
314c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    static const int argument_count = 4;
315ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org    __ PrepareCallCFunction(argument_count, ecx);
316ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    // Put arguments into allocated stack area, last argument highest on stack.
317ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    // Parameters are
318bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    //   Address byte_offset1 - Address captured substring's start.
319bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    //   Address byte_offset2 - Address of current character position.
320ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    //   size_t byte_length - length of capture in bytes(!)
321c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    //   Isolate* isolate
322ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
323c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    // Set isolate.
324c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    __ mov(Operand(esp, 3 * kPointerSize),
32532d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org           Immediate(ExternalReference::isolate_address(isolate())));
326ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    // Set byte_length.
327bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    __ mov(Operand(esp, 2 * kPointerSize), ebx);
328ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    // Set byte_offset2.
329ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    // Found by adding negative string-end offset of current position (edi)
330bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    // to end of string.
331c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(edi, esi);
332bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    __ mov(Operand(esp, 1 * kPointerSize), edi);
333ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    // Set byte_offset1.
334245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org    // Start of capture, where edx already holds string-end negative offset.
335c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(edx, esi);
336bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    __ mov(Operand(esp, 0 * kPointerSize), edx);
337ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
338c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    {
339c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      AllowExternalCallThatCantCauseGC scope(masm_);
340c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      ExternalReference compare =
34132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org          ExternalReference::re_case_insensitive_compare_uc16(isolate());
342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ CallCFunction(compare, argument_count);
343c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    }
3443291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Pop original values before reacting on result value.
3453291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ pop(ebx);
3463291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ pop(backtrack_stackpointer());
3478bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    __ pop(edi);
3488bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    __ pop(esi);
34937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
3503291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Check if function returned non-zero for success or zero for failure.
351c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ or_(eax, eax);
3528bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    BranchOrBacktrack(zero, on_no_match);
3533291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // On success, increment position by length of capture.
354c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ add(edi, ebx);
3558bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  }
356a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ bind(&fallthrough);
357a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
358a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
359a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
360a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::CheckNotBackReference(
3618bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    int start_reg,
3628bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    Label* on_no_match) {
363a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  Label fallthrough;
36437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  Label success;
36537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  Label fail;
3663291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
3673291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Find length of back-referenced capture.
36837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  __ mov(edx, register_location(start_reg));
3693291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(eax, register_location(start_reg + 1));
370c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(eax, edx);  // Length to check.
3713291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Fail on partial or illegal capture (start of capture after end of capture).
372a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  BranchOrBacktrack(less, on_no_match);
3733291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Succeed on empty capture (including no capture)
374a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ j(equal, &fallthrough);
37537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
3763291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Check that there are sufficient characters left in the input.
377a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ mov(ebx, edi);
378c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(ebx, eax);
379a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  BranchOrBacktrack(greater, on_no_match);
380a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
3813291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Save register to make it available below.
3823291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ push(backtrack_stackpointer());
3833291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
3843291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Compute pointers to match string and capture string
3853291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ lea(ebx, Operand(esi, edi, times_1, 0));  // Start of match.
386c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(edx, esi);  // Start of capture.
3873291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ lea(ecx, Operand(eax, ebx, times_1, 0));  // End of match
38837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
38937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  Label loop;
39037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  __ bind(&loop);
39137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  if (mode_ == ASCII) {
39237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    __ movzx_b(eax, Operand(edx, 0));
3933291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ cmpb_al(Operand(ebx, 0));
39437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  } else {
39537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    ASSERT(mode_ == UC16);
39637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    __ movzx_w(eax, Operand(edx, 0));
3973291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ cmpw_ax(Operand(ebx, 0));
39837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  }
399bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  __ j(not_equal, &fail);
4003291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Increment pointers into capture and match string.
401c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(edx, Immediate(char_size()));
402c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(ebx, Immediate(char_size()));
4033291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Check if we have reached end of match area.
404c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(ebx, ecx);
40537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  __ j(below, &loop);
406bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  __ jmp(&success);
40737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
40837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  __ bind(&fail);
4093291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Restore backtrack stackpointer.
4103291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ pop(backtrack_stackpointer());
411a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  BranchOrBacktrack(no_condition, on_no_match);
412a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
413a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ bind(&success);
4143291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Move current character position to position after match.
4153291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(edi, ecx);
416c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(edi, esi);
4173291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Restore backtrack stackpointer.
4183291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ pop(backtrack_stackpointer());
4193291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
420a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ bind(&fallthrough);
421a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
422a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
423a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
42437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid RegExpMacroAssemblerIA32::CheckNotCharacter(uint32_t c,
42537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                                 Label* on_not_equal) {
426a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ cmp(current_character(), c);
427a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  BranchOrBacktrack(not_equal, on_not_equal);
428a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
429a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
430a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
43137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid RegExpMacroAssemblerIA32::CheckCharacterAfterAnd(uint32_t c,
43237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                                      uint32_t mask,
43337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                                      Label* on_equal) {
4341456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  if (c == 0) {
4351456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    __ test(current_character(), Immediate(mask));
4361456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  } else {
4377d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ mov(eax, mask);
4387d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ and_(eax, current_character());
4391456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    __ cmp(eax, c);
4401456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  }
44137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  BranchOrBacktrack(equal, on_equal);
44237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com}
44337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
44437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
44537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid RegExpMacroAssemblerIA32::CheckNotCharacterAfterAnd(uint32_t c,
44637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                                         uint32_t mask,
44737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                                         Label* on_not_equal) {
4481456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  if (c == 0) {
4491456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    __ test(current_character(), Immediate(mask));
4501456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  } else {
4517d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ mov(eax, mask);
4527d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ and_(eax, current_character());
4531456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    __ cmp(eax, c);
4541456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  }
455a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  BranchOrBacktrack(not_equal, on_not_equal);
456a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
457a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
458a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
45937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusAnd(
460a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    uc16 c,
46137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    uc16 minus,
462a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    uc16 mask,
463a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    Label* on_not_equal) {
464154ff99473e866f5eb00a44045e27866a7fdce29yangguo@chromium.org  ASSERT(minus < String::kMaxUtf16CodeUnit);
46537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  __ lea(eax, Operand(current_character(), -minus));
4661456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  if (c == 0) {
4671456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    __ test(eax, Immediate(mask));
4681456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  } else {
4691456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    __ and_(eax, mask);
4701456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    __ cmp(eax, c);
4711456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  }
472a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  BranchOrBacktrack(not_equal, on_not_equal);
473a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
474a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
4753291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
4761456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgvoid RegExpMacroAssemblerIA32::CheckCharacterInRange(
4771456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    uc16 from,
4781456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    uc16 to,
4791456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    Label* on_in_range) {
4801456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  __ lea(eax, Operand(current_character(), -from));
4811456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  __ cmp(eax, to - from);
4821456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  BranchOrBacktrack(below_equal, on_in_range);
4831456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org}
4841456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
4851456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
4861456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgvoid RegExpMacroAssemblerIA32::CheckCharacterNotInRange(
4871456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    uc16 from,
4881456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    uc16 to,
4891456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    Label* on_not_in_range) {
4901456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  __ lea(eax, Operand(current_character(), -from));
4911456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  __ cmp(eax, to - from);
4921456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  BranchOrBacktrack(above, on_not_in_range);
4931456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org}
4941456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
4951456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
4961456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.orgvoid RegExpMacroAssemblerIA32::CheckBitInTable(
4971456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    Handle<ByteArray> table,
4981456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    Label* on_bit_set) {
4991456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  __ mov(eax, Immediate(table));
5001456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  Register index = current_character();
50159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  if (mode_ != ASCII || kTableMask != String::kMaxOneByteCharCode) {
5027d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ mov(ebx, kTableSize - 1);
5037d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org    __ and_(ebx, current_character());
5041456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org    index = ebx;
5051456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  }
5061456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  __ cmpb(FieldOperand(eax, index, times_1, ByteArray::kHeaderSize), 0);
5071456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org  BranchOrBacktrack(not_equal, on_bit_set);
5081456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org}
5091456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
5101456e708d277e725ca42a03463af16fe471c9210jkummerow@chromium.org
51137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.combool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type,
51237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                                          Label* on_no_match) {
51337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // Range checks (c in min..max) are generally implemented by an unsigned
51437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // (c - min) <= (max - min) check
51537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  switch (type) {
51637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  case 's':
51737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    // Match space-characters
51837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    if (mode_ == ASCII) {
5196e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      // One byte space characters are '\t'..'\r', ' ' and \u00a0.
52037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      Label success;
52137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      __ cmp(current_character(), ' ');
5226e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      __ j(equal, &success, Label::kNear);
52337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      // Check range 0x09..0x0d
5240c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      __ lea(eax, Operand(current_character(), -'\t'));
5250c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      __ cmp(eax, '\r' - '\t');
5266e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      __ j(below_equal, &success, Label::kNear);
5276e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      // \u00a0 (NBSP).
5286e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      __ cmp(eax, 0x00a0 - '\t');
5296e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org      BranchOrBacktrack(not_equal, on_no_match);
53037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      __ bind(&success);
53137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      return true;
53237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    }
53337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    return false;
53437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  case 'S':
5356e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org    // The emitted code for generic character classes is good enough.
53637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    return false;
53737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  case 'd':
53837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    // Match ASCII digits ('0'..'9')
5390c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    __ lea(eax, Operand(current_character(), -'0'));
5400c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    __ cmp(eax, '9' - '0');
5413291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    BranchOrBacktrack(above, on_no_match);
54237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    return true;
54337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  case 'D':
54437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    // Match non ASCII-digits
5450c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    __ lea(eax, Operand(current_character(), -'0'));
5460c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    __ cmp(eax, '9' - '0');
5473291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    BranchOrBacktrack(below_equal, on_no_match);
54837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    return true;
54937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  case '.': {
55037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
551c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(eax, current_character());
552c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ xor_(eax, Immediate(0x01));
5533291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
554c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sub(eax, Immediate(0x0b));
5550c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    __ cmp(eax, 0x0c - 0x0b);
5563291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    BranchOrBacktrack(below_equal, on_no_match);
55737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    if (mode_ == UC16) {
55837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      // Compare original value to 0x2028 and 0x2029, using the already
5593291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
5603291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org      // 0x201d (0x2028 - 0x0b) or 0x201e.
561c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ sub(eax, Immediate(0x2028 - 0x0b));
5620c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      __ cmp(eax, 0x2029 - 0x2028);
5633291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org      BranchOrBacktrack(below_equal, on_no_match);
56437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    }
56537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    return true;
56637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  }
5670c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  case 'w': {
568b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    if (mode_ != ASCII) {
569b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      // Table is 128 entries, so all ASCII characters can be tested.
570c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ cmp(current_character(), Immediate('z'));
571b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      BranchOrBacktrack(above, on_no_match);
572b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
573b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    ASSERT_EQ(0, word_character_map[0]);  // Character '\0' is not a word char.
574b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    ExternalReference word_map = ExternalReference::re_word_character_map();
575b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ test_b(current_character(),
576b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org              Operand::StaticArray(current_character(), times_1, word_map));
577b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    BranchOrBacktrack(zero, on_no_match);
5780c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    return true;
5790c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  }
5800c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  case 'W': {
581b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    Label done;
582b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    if (mode_ != ASCII) {
583b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      // Table is 128 entries, so all ASCII characters can be tested.
584c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ cmp(current_character(), Immediate('z'));
585bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com      __ j(above, &done);
586b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
587b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    ASSERT_EQ(0, word_character_map[0]);  // Character '\0' is not a word char.
588b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    ExternalReference word_map = ExternalReference::re_word_character_map();
589b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    __ test_b(current_character(),
590b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org              Operand::StaticArray(current_character(), times_1, word_map));
591b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    BranchOrBacktrack(not_zero, on_no_match);
592b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    if (mode_ != ASCII) {
593b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org      __ bind(&done);
594b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org    }
5950c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    return true;
5960c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  }
5970c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  // Non-standard classes (with no syntactic shorthand) used internally.
59837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  case '*':
59937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    // Match any character.
6000c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    return true;
6010c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  case 'n': {
6020c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029).
6030c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    // The opposite of '.'.
604c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ mov(eax, current_character());
605c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ xor_(eax, Immediate(0x01));
6060c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
607c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ sub(eax, Immediate(0x0b));
6080c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    __ cmp(eax, 0x0c - 0x0b);
6090c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    if (mode_ == ASCII) {
6100c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      BranchOrBacktrack(above, on_no_match);
6110c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    } else {
6120c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      Label done;
6130c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      BranchOrBacktrack(below_equal, &done);
6140c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      ASSERT_EQ(UC16, mode_);
6150c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      // Compare original value to 0x2028 and 0x2029, using the already
6160c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
6170c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      // 0x201d (0x2028 - 0x0b) or 0x201e.
618c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      __ sub(eax, Immediate(0x2028 - 0x0b));
6190c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      __ cmp(eax, 1);
6200c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      BranchOrBacktrack(above, on_no_match);
6210c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org      __ bind(&done);
62237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    }
62337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    return true;
6240c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  }
6250c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  // No custom implementation (yet): s(UC16), S(UC16).
62637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  default:
62737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    return false;
62837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  }
62937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com}
630a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
631a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
632a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::Fail() {
63315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  STATIC_ASSERT(FAILURE == 0);  // Return value for failure is zero.
63415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  if (!global()) {
63515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    __ Set(eax, Immediate(FAILURE));
63615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  }
637a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ jmp(&exit_label_);
638a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
639a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
640a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
64183a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.orgHandle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
64215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  Label return_eax;
643a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Finalize code - write the entry point code now we know how many
644a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // registers we need.
645a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
646a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Entry code:
647a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ bind(&entry_label_);
648c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
649c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Tell the system that we have a stack frame.  Because the type is MANUAL, no
650c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // code is generated.
651c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  FrameScope scope(masm_, StackFrame::MANUAL);
652c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
653c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Actually emit code to start a new stack frame.
6543291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ push(ebp);
6553291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(ebp, esp);
656bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // Save callee-save registers. Order here should correspond to order of
657a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // kBackup_ebx etc.
658a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ push(esi);
659a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ push(edi);
660a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ push(ebx);  // Callee-save on MacOS.
66115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ push(Immediate(0));  // Number of successful matches in a global regexp.
662245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org  __ push(Immediate(0));  // Make room for "input start - 1" constant.
6633291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
6643291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Check if we have space on the stack for registers.
6653291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  Label stack_limit_hit;
6663291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  Label stack_ok;
6673291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
668c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  ExternalReference stack_limit =
66932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ExternalReference::address_of_stack_limit(isolate());
6703291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(ecx, esp);
671c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  __ sub(ecx, Operand::StaticVariable(stack_limit));
6723291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Handle it if the stack pointer is already below the stack limit.
673bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  __ j(below_equal, &stack_limit_hit);
6743291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Check if there is room for the variable number of registers above
6753291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // the stack limit.
6763291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ cmp(ecx, num_registers_ * kPointerSize);
677bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  __ j(above_equal, &stack_ok);
678bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // Exit with OutOfMemory exception. There is not enough space on the stack
679bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // for our working registers.
6803291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(eax, EXCEPTION);
68115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ jmp(&return_eax);
6823291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
6833291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ bind(&stack_limit_hit);
684bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  CallCheckStackGuardState(ebx);
685c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ or_(eax, eax);
686bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // If returned value is non-zero, we exit with the returned value as result.
68715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ j(not_zero, &return_eax);
6883291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
6893291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ bind(&stack_ok);
690cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  // Load start index for later use.
691cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  __ mov(ebx, Operand(ebp, kStartIndex));
6923291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
6933291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Allocate space on stack for registers.
694c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(esp, Immediate(num_registers_ * kPointerSize));
695a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Load string length.
696bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  __ mov(esi, Operand(ebp, kInputEnd));
697a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Load input position.
698bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  __ mov(edi, Operand(ebp, kInputStart));
699a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Set up edi to be negative offset from string end.
700c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(edi, esi);
701cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
702cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  // Set eax to address of char before start of the string.
703911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // (effectively string position -1).
704cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  __ neg(ebx);
705cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  if (mode_ == UC16) {
706cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    __ lea(eax, Operand(edi, ebx, times_2, -char_size()));
707cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  } else {
708cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    __ lea(eax, Operand(edi, ebx, times_1, -char_size()));
709cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  }
710911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // Store this value in a local variable, for use when clearing
711911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  // position registers.
712911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org  __ mov(Operand(ebp, kInputStartMinusOne), eax);
713b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org
71415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org#ifdef WIN32
71515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Ensure that we write to each stack page, in order. Skipping a page
7163291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // on Windows can cause segmentation faults. Assuming page size is 4k.
7173291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  const int kPageSize = 4096;
7183291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  const int kRegistersPerPage = kPageSize / kPointerSize;
7193291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  for (int i = num_saved_registers_ + kRegistersPerPage - 1;
7203291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org      i < num_registers_;
7213291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org      i += kRegistersPerPage) {
7223291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ mov(register_location(i), eax);  // One write every page.
723a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
72415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org#endif  // WIN32
72515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
72615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  Label load_char_start_regexp, start_regexp;
72715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Load newline if index is at start, previous character otherwise.
72815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ cmp(Operand(ebp, kStartIndex), Immediate(0));
72915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ j(not_equal, &load_char_start_regexp, Label::kNear);
73015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ mov(current_character(), '\n');
73115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ jmp(&start_regexp, Label::kNear);
7323291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
73315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Global regexp restarts matching here.
73415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ bind(&load_char_start_regexp);
73515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Load previous char as initial value of current character register.
73615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  LoadCurrentCharacterUnchecked(-1, 1);
73715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ bind(&start_regexp);
73815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
73915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  // Initialize on-stack registers.
74015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  if (num_saved_registers_ > 0) {  // Always is, if generated from a regexp.
74115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    // Fill saved registers with initial value = start offset - 1
74215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    // Fill in stack push order, to avoid accessing across an unwritten
74315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    // page (a problem on Windows).
74415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    if (num_saved_registers_ > 8) {
74515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ mov(ecx, kRegisterZero);
74615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      Label init_loop;
74715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ bind(&init_loop);
74815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ mov(Operand(ebp, ecx, times_1, 0), eax);
74915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ sub(ecx, Immediate(kPointerSize));
75015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize);
75115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ j(greater, &init_loop);
75215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    } else {  // Unroll the loop.
75315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      for (int i = 0; i < num_saved_registers_; i++) {
75415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org        __ mov(register_location(i), eax);
75515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      }
75615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    }
75715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  }
7583291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
7593291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Initialize backtrack stack pointer.
7603291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
761a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
76215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ jmp(&start_label_);
763a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
764a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  // Exit code:
76537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  if (success_label_.is_linked()) {
7663291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Save captures when successful.
76737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    __ bind(&success_label_);
76837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    if (num_saved_registers_ > 0) {
76937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      // copy captures to output
77037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      __ mov(ebx, Operand(ebp, kRegisterOutput));
771bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org      __ mov(ecx, Operand(ebp, kInputEnd));
772cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      __ mov(edx, Operand(ebp, kStartIndex));
773bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org      __ sub(ecx, Operand(ebp, kInputStart));
774cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      if (mode_ == UC16) {
775cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org        __ lea(ecx, Operand(ecx, edx, times_2, 0));
776cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      } else {
777c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ add(ecx, edx);
778cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org      }
77937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      for (int i = 0; i < num_saved_registers_; i++) {
78037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com        __ mov(eax, register_location(i));
781400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        if (i == 0 && global_with_zero_length_check()) {
78215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org          // Keep capture start in edx for the zero-length check later.
78315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org          __ mov(edx, eax);
78415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org        }
785cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org        // Convert to index from start of string, not end.
786c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com        __ add(eax, ecx);
78737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com        if (mode_ == UC16) {
78837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com          __ sar(eax, 1);  // Convert byte index to character index.
78937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com        }
79037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com        __ mov(Operand(ebx, i * kPointerSize), eax);
791a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      }
792a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
79315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
79415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    if (global()) {
79515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    // Restart matching if the regular expression is flagged as global.
79615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      // Increment success counter.
79715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ inc(Operand(ebp, kSuccessfulCaptures));
79815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      // Capture results have been stored, so the number of remaining global
79915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      // output registers is reduced by the number of stored captures.
80015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ mov(ecx, Operand(ebp, kNumOutputRegisters));
80115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ sub(ecx, Immediate(num_saved_registers_));
80215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      // Check whether we have enough room for another set of capture results.
80315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ cmp(ecx, Immediate(num_saved_registers_));
80415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ j(less, &exit_label_);
80515613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
80615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ mov(Operand(ebp, kNumOutputRegisters), ecx);
80715613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      // Advance the location for output.
80815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ add(Operand(ebp, kRegisterOutput),
80915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org             Immediate(num_saved_registers_ * kPointerSize));
81015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
81115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      // Prepare eax to initialize registers with its value in the next run.
81215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ mov(eax, Operand(ebp, kInputStartMinusOne));
81315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
814400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org      if (global_with_zero_length_check()) {
815400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        // Special case for zero-length matches.
816400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        // edx: capture start index
817400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        __ cmp(edi, edx);
818400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        // Not a zero-length match, restart.
819400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        __ j(not_equal, &load_char_start_regexp);
820400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        // edi (offset from the end) is zero if we already reached the end.
821400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        __ test(edi, edi);
822400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        __ j(zero, &exit_label_, Label::kNear);
823400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        // Advance current position after a zero-length match.
824400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        if (mode_ == UC16) {
825400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org          __ add(edi, Immediate(2));
826400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        } else {
827400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org          __ inc(edi);
828400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org        }
82915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      }
830400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org
83115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ jmp(&load_char_start_regexp);
83215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    } else {
83315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org      __ mov(eax, Immediate(SUCCESS));
83415613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    }
835a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
83615613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
837a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ bind(&exit_label_);
83815613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  if (global()) {
83915613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    // Return the number of successful captures.
84015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    __ mov(eax, Operand(ebp, kSuccessfulCaptures));
84115613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  }
84215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org
84315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  __ bind(&return_eax);
8443291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Skip esp past regexp registers.
8453291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ lea(esp, Operand(ebp, kBackup_ebx));
8463291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Restore callee-save registers.
847a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ pop(ebx);
848a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ pop(edi);
849a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ pop(esi);
8503291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Exit function frame, restore previous one.
8513291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ pop(ebp);
852a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ ret(0);
853a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
85437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // Backtrack code (branch target for conditional backtracks).
85537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  if (backtrack_label_.is_linked()) {
85637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    __ bind(&backtrack_label_);
85737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    Backtrack();
85837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  }
85937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
8603291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  Label exit_with_exception;
8613291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
86237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // Preempt-code
86337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  if (check_preempt_label_.is_linked()) {
8645a6af92a1549c81fb61855518f43b712e4c0e469christian.plesner.hansen@gmail.com    SafeCallTarget(&check_preempt_label_);
8653291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
8663291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ push(backtrack_stackpointer());
86737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    __ push(edi);
86837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
869bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    CallCheckStackGuardState(ebx);
870c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ or_(eax, eax);
871bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    // If returning non-zero, we should end execution with the given
872bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    // result as return value.
87315613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    __ j(not_zero, &return_eax);
87437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
87537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    __ pop(edi);
8763291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ pop(backtrack_stackpointer());
877bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    // String might have moved: Reload esi from frame.
878bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    __ mov(esi, Operand(ebp, kInputEnd));
8793291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    SafeReturn();
8803291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  }
8813291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
8823291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Backtrack stack overflow code.
8833291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  if (stack_overflow_label_.is_linked()) {
8845a6af92a1549c81fb61855518f43b712e4c0e469christian.plesner.hansen@gmail.com    SafeCallTarget(&stack_overflow_label_);
8853291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Reached if the backtrack-stack limit has been hit.
8863291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
8873291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    Label grow_failed;
8883291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Save registers before calling C function
8893291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ push(esi);
8903291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ push(edi);
8913291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
8923291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Call GrowStack(backtrack_stackpointer())
893c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    static const int num_arguments = 3;
894ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org    __ PrepareCallCFunction(num_arguments, ebx);
895c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org    __ mov(Operand(esp, 2 * kPointerSize),
89632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org           Immediate(ExternalReference::isolate_address(isolate())));
8976f10e41fef1524c70846d970268de222e41c594cager@chromium.org    __ lea(eax, Operand(ebp, kStackHighEnd));
8986f10e41fef1524c70846d970268de222e41c594cager@chromium.org    __ mov(Operand(esp, 1 * kPointerSize), eax);
8996f10e41fef1524c70846d970268de222e41c594cager@chromium.org    __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer());
900ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    ExternalReference grow_stack =
90132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        ExternalReference::re_grow_stack(isolate());
902ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org    __ CallCFunction(grow_stack, num_arguments);
9033291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // If return NULL, we have failed to grow the stack, and
9043291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // must exit with a stack-overflow exception.
905c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ or_(eax, eax);
9063291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ j(equal, &exit_with_exception);
9073291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Otherwise use return value as new stack pointer.
9083291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ mov(backtrack_stackpointer(), eax);
9093291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Restore saved registers and continue.
9103291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ pop(edi);
9113291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ pop(esi);
91237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    SafeReturn();
9133291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  }
91437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
9153291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  if (exit_with_exception.is_linked()) {
9163291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // If any of the code above needed to exit with an exception.
9173291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ bind(&exit_with_exception);
9183291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    // Exit with Result EXCEPTION(-1) to signal thrown exception.
9193291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    __ mov(eax, EXCEPTION);
92015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org    __ jmp(&return_eax);
92137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  }
92237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
923a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  CodeDesc code_desc;
924a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  masm_->GetCode(&code_desc);
925ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Handle<Code> code =
92632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      isolate()->factory()->NewCode(code_desc,
92732d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                                    Code::ComputeFlags(Code::REGEXP),
92832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org                                    masm_->CodeObject());
92932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  PROFILE(isolate(), RegExpCodeCreateEvent(*code, *source));
93083a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  return Handle<HeapObject>::cast(code);
931a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
932a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
933a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
934a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::GoTo(Label* to) {
9358bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  BranchOrBacktrack(no_condition, to);
936a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
937a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
938a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
939a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::IfRegisterGE(int reg,
940a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                            int comparand,
941a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                            Label* if_ge) {
942a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ cmp(register_location(reg), Immediate(comparand));
943a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  BranchOrBacktrack(greater_equal, if_ge);
944a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
945a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
946a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
947a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::IfRegisterLT(int reg,
948a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                            int comparand,
949a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org                                            Label* if_lt) {
950a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ cmp(register_location(reg), Immediate(comparand));
951a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  BranchOrBacktrack(less, if_lt);
952a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
953a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
954a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
9553291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgvoid RegExpMacroAssemblerIA32::IfRegisterEqPos(int reg,
9563291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                                               Label* if_eq) {
9573291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ cmp(edi, register_location(reg));
9583291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  BranchOrBacktrack(equal, if_eq);
9593291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org}
9603291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
9613291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
962a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgRegExpMacroAssembler::IrregexpImplementation
963a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    RegExpMacroAssemblerIA32::Implementation() {
964a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  return kIA32Implementation;
965a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
966a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
967a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
968a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset,
96937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                                    Label* on_end_of_input,
97037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                                    bool check_bounds,
97137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                                    int characters) {
972ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org  ASSERT(cp_offset >= -1);      // ^ and \b can look behind one character.
973a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ASSERT(cp_offset < (1<<30));  // Be sane! (And ensure negation works)
97418ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  if (check_bounds) {
97518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org    CheckPosition(cp_offset + characters - 1, on_end_of_input);
97618ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  }
97737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  LoadCurrentCharacterUnchecked(cp_offset, characters);
978a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
979a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
980a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
981a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::PopCurrentPosition() {
9823291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  Pop(edi);
983a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
984a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
985a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
986a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::PopRegister(int register_index) {
9873291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  Pop(eax);
9883291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(register_location(register_index), eax);
989a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
990a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
991a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
992a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::PushBacktrack(Label* label) {
9933291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  Push(Immediate::CodeRelativeOffset(label));
99437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  CheckStackLimit();
995a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
996a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
997a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
998a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::PushCurrentPosition() {
9993291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  Push(edi);
1000a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
1001a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1002a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
10033291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgvoid RegExpMacroAssemblerIA32::PushRegister(int register_index,
10043291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                                            StackCheckFlag check_stack_limit) {
10053291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(eax, register_location(register_index));
10063291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  Push(eax);
10073291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  if (check_stack_limit) CheckStackLimit();
1008a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
1009a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1010a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1011a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) {
1012a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ mov(edi, register_location(reg));
1013a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
1014a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1015a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1016a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) {
10173291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(backtrack_stackpointer(), register_location(reg));
10186f10e41fef1524c70846d970268de222e41c594cager@chromium.org  __ add(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
1019a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
1020a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
10214a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.orgvoid RegExpMacroAssemblerIA32::SetCurrentPositionFromEnd(int by)  {
102283a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  Label after_position;
10234a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  __ cmp(edi, -by * char_size());
102483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org  __ j(greater_equal, &after_position, Label::kNear);
10254a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  __ mov(edi, -by * char_size());
10264a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  // On RegExp code entry (where this operation is used), the character before
10274a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  // the current position is expected to be already loaded.
10284a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  // We have advanced the position, so it's safe to read backwards.
10294a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  LoadCurrentCharacterUnchecked(-1, 1);
10304a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  __ bind(&after_position);
10314a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org}
1032a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1033e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
1034a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) {
1035a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ASSERT(register_index >= num_saved_registers_);  // Reserved for positions!
1036a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ mov(register_location(register_index), Immediate(to));
1037a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
1038a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1039a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
104015613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.orgbool RegExpMacroAssemblerIA32::Succeed() {
1041a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  __ jmp(&success_label_);
104215613d0b07bac19e341905ff374c930420b3b9c8mstarzinger@chromium.org  return global();
1043a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
1044a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1045a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
10468bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.orgvoid RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg,
10478bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org                                                              int cp_offset) {
10488bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  if (cp_offset == 0) {
10498bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    __ mov(register_location(reg), edi);
10508bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  } else {
10518bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    __ lea(eax, Operand(edi, cp_offset * char_size()));
10528bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org    __ mov(register_location(reg), eax);
10538bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org  }
1054a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
1055a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
10568bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org
1057ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.orgvoid RegExpMacroAssemblerIA32::ClearRegisters(int reg_from, int reg_to) {
1058ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org  ASSERT(reg_from <= reg_to);
10593291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(eax, Operand(ebp, kInputStartMinusOne));
1060ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org  for (int reg = reg_from; reg <= reg_to; reg++) {
1061ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    __ mov(register_location(reg), eax);
1062ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org  }
10633291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org}
10643291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
10653291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
1066a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
10676f10e41fef1524c70846d970268de222e41c594cager@chromium.org  __ mov(eax, backtrack_stackpointer());
10686f10e41fef1524c70846d970268de222e41c594cager@chromium.org  __ sub(eax, Operand(ebp, kStackHighEnd));
10696f10e41fef1524c70846d970268de222e41c594cager@chromium.org  __ mov(register_location(reg), eax);
1070a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
1071a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1072a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1073bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org// Private methods:
10748bb60585bafbf81564e6b30fcf18c82615a76f95ager@chromium.org
1075bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.orgvoid RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) {
1076ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  static const int num_arguments = 3;
1077ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  __ PrepareCallCFunction(num_arguments, scratch);
1078bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // RegExp code frame pointer.
1079bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  __ mov(Operand(esp, 2 * kPointerSize), ebp);
1080bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // Code* of self.
1081bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  __ mov(Operand(esp, 1 * kPointerSize), Immediate(masm_->CodeObject()));
1082bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // Next address on the stack (will be address of return address).
1083bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  __ lea(eax, Operand(esp, -kPointerSize));
1084bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  __ mov(Operand(esp, 0 * kPointerSize), eax);
108518ad94b919217ffbcd2d3159eeb5f8c588761c47ager@chromium.org  ExternalReference check_stack_guard =
108632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ExternalReference::re_check_stack_guard_state(isolate());
1087ce5e87bd905d592a8bd612b3dedf7a994177c13aager@chromium.org  __ CallCFunction(check_stack_guard, num_arguments);
1088bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org}
1089bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
1090bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
1091bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org// Helper function for reading a value out of a stack frame.
1092bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.orgtemplate <typename T>
1093bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.orgstatic T& frame_entry(Address re_frame, int frame_offset) {
1094bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset));
1095bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org}
1096bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
1097bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
1098381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.orgint RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
1099bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org                                                   Code* re_code,
1100bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org                                                   Address re_frame) {
1101ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
1102ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ASSERT(isolate == Isolate::Current());
1103ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (isolate->stack_guard()->IsStackOverflow()) {
1104ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    isolate->StackOverflow();
1105bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    return EXCEPTION;
110637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  }
110737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
110837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // If not real stack overflow the stack guard was used to interrupt
110937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // execution for another purpose.
111037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
11110c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  // If this is a direct call from JavaScript retry the RegExp forcing the call
11120c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  // through the runtime system. Currently the direct call cannot handle a GC.
11130c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  if (frame_entry<int>(re_frame, kDirectCall) == 1) {
11140c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org    return RETRY;
11150c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org  }
11160c20e676f8a0209982ff89e5a9c707771748a585fschneider@chromium.org
111737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // Prepare for possible GC.
11184668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  HandleScope handles(isolate);
111937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  Handle<Code> code_handle(re_code);
11203291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
1121bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
11224668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
1123bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // Current string.
11248e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  bool is_ascii = subject->IsOneByteRepresentationUnderneath();
1125bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
1126381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org  ASSERT(re_code->instruction_start() <= *return_address);
1127381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org  ASSERT(*return_address <=
112837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      re_code->instruction_start() + re_code->instruction_size());
112937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
1130812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org  MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
113137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
113237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  if (*code_handle != re_code) {  // Return address no longer valid
113380c42ed5ace766a3a02b30a53a25e5e81e234723yangguo@chromium.org    int delta = code_handle->address() - re_code->address();
1134381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org    // Overwrite the return address on the stack.
1135381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org    *return_address += delta;
113637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  }
113737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
113837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  if (result->IsException()) {
1139bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    return EXCEPTION;
1140bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  }
1141bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
11424668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  Handle<String> subject_tmp = subject;
11434668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  int slice_offset = 0;
11444668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
11454668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // Extract the underlying string and the slice offset.
11464668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  if (StringShape(*subject_tmp).IsCons()) {
11474668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
11484668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  } else if (StringShape(*subject_tmp).IsSliced()) {
11494668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    SlicedString* slice = SlicedString::cast(*subject_tmp);
11504668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    subject_tmp = Handle<String>(slice->parent());
11514668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    slice_offset = slice->offset();
11524668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  }
11534668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
1154bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // String might have changed.
11558e8d8825f97138de12985f8e0d3163074dff5258ulan@chromium.org  if (subject_tmp->IsOneByteRepresentation() != is_ascii) {
1156bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    // If we changed between an ASCII and an UC16 string, the specialized
1157bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    // code cannot be used, and we need to restart regexp matching from
1158bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    // scratch (including, potentially, compiling a new version of the code).
1159bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    return RETRY;
116037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  }
1161bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
1162bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // Otherwise, the content of the string might have moved. It must still
1163bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // be a sequential or external string with the same content.
1164bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // Update the start and end pointers in the stack frame to the current
1165bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // location (whether it has actually moved or not).
11664668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  ASSERT(StringShape(*subject_tmp).IsSequential() ||
11674668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org      StringShape(*subject_tmp).IsExternal());
1168bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
1169bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // The original start address of the characters to match.
1170bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
1171bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
1172bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // Find the current start address of the same character at the current string
1173bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  // position.
1174bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  int start_index = frame_entry<int>(re_frame, kStartIndex);
11754668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  const byte* new_address = StringCharacterPosition(*subject_tmp,
11764668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org                                                    start_index + slice_offset);
1177bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
1178bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  if (start_address != new_address) {
1179755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    // If there is a difference, update the object pointer and start and end
1180755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    // addresses in the RegExp stack frame to match the new value.
1181bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
11824668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org    int byte_length = static_cast<int>(end_address - start_address);
1183755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org    frame_entry<const String*>(re_frame, kInputString) = *subject;
1184bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    frame_entry<const byte*>(re_frame, kInputStart) = new_address;
1185bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org    frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
1186394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  } else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
1187394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // Subject string might have been a ConsString that underwent
1188394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // short-circuiting during GC. That will not change start_address but
1189394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    // will change pointer inside the subject handle.
1190394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com    frame_entry<const String*>(re_frame, kInputString) = *subject;
1191bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  }
1192bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
119337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  return 0;
119437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com}
119537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
119637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
1197a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgOperand RegExpMacroAssemblerIA32::register_location(int register_index) {
1198a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  ASSERT(register_index < (1<<30));
1199a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (num_registers_ <= register_index) {
1200a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    num_registers_ = register_index + 1;
1201a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
12023291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  return Operand(ebp, kRegisterZero - register_index * kPointerSize);
1203a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
1204a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1205a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
120637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid RegExpMacroAssemblerIA32::CheckPosition(int cp_offset,
120737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                             Label* on_outside_input) {
120837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  __ cmp(edi, -cp_offset * char_size());
120937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  BranchOrBacktrack(greater_equal, on_outside_input);
121037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com}
121137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
121237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
1213a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition,
12147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org                                                 Label* to) {
1215a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (condition < 0) {  // No condition
1216a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    if (to == NULL) {
1217a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      Backtrack();
1218a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org      return;
1219a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    }
1220a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    __ jmp(to);
1221a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return;
1222a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
1223a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  if (to == NULL) {
12247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org    __ j(condition, &backtrack_label_);
1225a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org    return;
1226a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org  }
12277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org  __ j(condition, to);
1228a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
1229a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1230a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
123137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid RegExpMacroAssemblerIA32::SafeCall(Label* to) {
1232ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  Label return_to;
1233ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  __ push(Immediate::CodeRelativeOffset(&return_to));
1234ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  __ jmp(to);
1235ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  __ bind(&return_to);
123637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com}
123737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
123837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
123937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid RegExpMacroAssemblerIA32::SafeReturn() {
1240ac091b7d178f1853ede4a5cba58e767e6adf7d96ager@chromium.org  __ pop(ebx);
1241c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(ebx, Immediate(masm_->CodeObject()));
1242c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ jmp(ebx);
12435a6af92a1549c81fb61855518f43b712e4c0e469christian.plesner.hansen@gmail.com}
12445a6af92a1549c81fb61855518f43b712e4c0e469christian.plesner.hansen@gmail.com
12455a6af92a1549c81fb61855518f43b712e4c0e469christian.plesner.hansen@gmail.com
12465a6af92a1549c81fb61855518f43b712e4c0e469christian.plesner.hansen@gmail.comvoid RegExpMacroAssemblerIA32::SafeCallTarget(Label* name) {
12475a6af92a1549c81fb61855518f43b712e4c0e469christian.plesner.hansen@gmail.com  __ bind(name);
12483291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org}
12493291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
12503291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
12513291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgvoid RegExpMacroAssemblerIA32::Push(Register source) {
12523291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  ASSERT(!source.is(backtrack_stackpointer()));
12533291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Notice: This updates flags, unlike normal Push.
1254c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(backtrack_stackpointer(), Immediate(kPointerSize));
12553291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(Operand(backtrack_stackpointer(), 0), source);
12563291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org}
12573291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
12583291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
12593291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgvoid RegExpMacroAssemblerIA32::Push(Immediate value) {
12603291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Notice: This updates flags, unlike normal Push.
1261c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(backtrack_stackpointer(), Immediate(kPointerSize));
12623291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(Operand(backtrack_stackpointer(), 0), value);
12633291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org}
12643291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
12653291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
12663291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgvoid RegExpMacroAssemblerIA32::Pop(Register target) {
12673291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  ASSERT(!target.is(backtrack_stackpointer()));
12683291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ mov(target, Operand(backtrack_stackpointer(), 0));
12693291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Notice: This updates flags, unlike normal Pop.
1270c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(backtrack_stackpointer(), Immediate(kPointerSize));
12713291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org}
12723291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
12733291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
12743291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgvoid RegExpMacroAssemblerIA32::CheckPreemption() {
12753291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Check for preemption.
12763291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  Label no_preempt;
1277c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  ExternalReference stack_limit =
127832d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ExternalReference::address_of_stack_limit(isolate());
1279c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org  __ cmp(esp, Operand::StaticVariable(stack_limit));
1280bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  __ j(above, &no_preempt);
12813291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
12823291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  SafeCall(&check_preempt_label_);
12833291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
12843291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  __ bind(&no_preempt);
128537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com}
128637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
128737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com
1288a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.orgvoid RegExpMacroAssemblerIA32::CheckStackLimit() {
12893811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  Label no_stack_overflow;
12903811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  ExternalReference stack_limit =
129132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org      ExternalReference::address_of_regexp_stack_limit(isolate());
12923811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  __ cmp(backtrack_stackpointer(), Operand::StaticVariable(stack_limit));
1293bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com  __ j(above, &no_stack_overflow);
1294a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
12953811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  SafeCall(&stack_overflow_label_);
1296a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
12973811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org  __ bind(&no_stack_overflow);
1298a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
1299a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1300a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
130137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.comvoid RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset,
130237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                                                             int characters) {
130337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  if (mode_ == ASCII) {
130437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    if (characters == 4) {
130537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      __ mov(current_character(), Operand(esi, edi, times_1, cp_offset));
130637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    } else if (characters == 2) {
130737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      __ movzx_w(current_character(), Operand(esi, edi, times_1, cp_offset));
130837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    } else {
130937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      ASSERT(characters == 1);
131037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset));
131137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    }
131237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  } else {
131337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    ASSERT(mode_ == UC16);
131437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    if (characters == 2) {
131537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      __ mov(current_character(),
1316a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org             Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
131737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    } else {
131837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      ASSERT(characters == 1);
131937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com      __ movzx_w(current_character(),
132037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com                 Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
132137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    }
132237abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  }
1323a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}
1324a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1325a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org
1326a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org#undef __
1327911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
1328c9c80823e038328f2e1060d7feef0762a50adf06ricow@chromium.org#endif  // V8_INTERPRETED_REGEXP
1329911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org
1330a74f0daeb278665869b4b6a3bc2739e88fed93b1ager@chromium.org}}  // namespace v8::internal
13319dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com
13329dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif  // V8_TARGET_ARCH_IA32
1333