Home | History | Annotate | Download | only in ia32
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/v8.h"
      6 
      7 #if V8_TARGET_ARCH_IA32
      8 
      9 #include "src/cpu-profiler.h"
     10 #include "src/log.h"
     11 #include "src/macro-assembler.h"
     12 #include "src/regexp-macro-assembler.h"
     13 #include "src/regexp-stack.h"
     14 #include "src/unicode.h"
     15 
     16 #include "src/ia32/regexp-macro-assembler-ia32.h"
     17 
     18 namespace v8 {
     19 namespace internal {
     20 
     21 #ifndef V8_INTERPRETED_REGEXP
     22 /*
     23  * This assembler uses the following register assignment convention
     24  * - edx : Current character.  Must be loaded using LoadCurrentCharacter
     25  *         before using any of the dispatch methods.  Temporarily stores the
     26  *         index of capture start after a matching pass for a global regexp.
     27  * - edi : Current position in input, as negative offset from end of string.
     28  *         Please notice that this is the byte offset, not the character offset!
     29  * - esi : end of input (points to byte after last character in input).
     30  * - ebp : Frame pointer.  Used to access arguments, local variables and
     31  *         RegExp registers.
     32  * - esp : Points to tip of C stack.
     33  * - ecx : Points to tip of backtrack stack
     34  *
     35  * The registers eax and ebx are free to use for computations.
     36  *
     37  * Each call to a public method should retain this convention.
     38  * The stack will have the following structure:
     39  *       - Isolate* isolate     (address of the current isolate)
     40  *       - direct_call          (if 1, direct call from JavaScript code, if 0
     41  *                               call through the runtime system)
     42  *       - stack_area_base      (high end of the memory area to use as
     43  *                               backtracking stack)
     44  *       - capture array size   (may fit multiple sets of matches)
     45  *       - int* capture_array   (int[num_saved_registers_], for output).
     46  *       - end of input         (address of end of string)
     47  *       - start of input       (address of first character in string)
     48  *       - start index          (character index of start)
     49  *       - String* input_string (location of a handle containing the string)
     50  *       --- frame alignment (if applicable) ---
     51  *       - return address
     52  * ebp-> - old ebp
     53  *       - backup of caller esi
     54  *       - backup of caller edi
     55  *       - backup of caller ebx
     56  *       - success counter      (only for global regexps to count matches).
     57  *       - Offset of location before start of input (effectively character
     58  *         position -1). Used to initialize capture registers to a non-position.
     59  *       - register 0  ebp[-4]  (only positions must be stored in the first
     60  *       - register 1  ebp[-8]   num_saved_registers_ registers)
     61  *       - ...
     62  *
     63  * The first num_saved_registers_ registers are initialized to point to
     64  * "character -1" in the string (i.e., char_size() bytes before the first
     65  * character of the string). The remaining registers starts out as garbage.
     66  *
     67  * The data up to the return address must be placed there by the calling
     68  * code, by calling the code entry as cast to a function with the signature:
     69  * int (*match)(String* input_string,
     70  *              int start_index,
     71  *              Address start,
     72  *              Address end,
     73  *              int* capture_output_array,
     74  *              bool at_start,
     75  *              byte* stack_area_base,
     76  *              bool direct_call)
     77  */
     78 
     79 #define __ ACCESS_MASM(masm_)
     80 
     81 RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(
     82     Mode mode,
     83     int registers_to_save,
     84     Zone* zone)
     85     : NativeRegExpMacroAssembler(zone),
     86       masm_(new MacroAssembler(zone->isolate(), NULL, kRegExpCodeSize)),
     87       mode_(mode),
     88       num_registers_(registers_to_save),
     89       num_saved_registers_(registers_to_save),
     90       entry_label_(),
     91       start_label_(),
     92       success_label_(),
     93       backtrack_label_(),
     94       exit_label_() {
     95   DCHECK_EQ(0, registers_to_save % 2);
     96   __ jmp(&entry_label_);   // We'll write the entry code later.
     97   __ bind(&start_label_);  // And then continue from here.
     98 }
     99 
    100 
    101 RegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() {
    102   delete masm_;
    103   // Unuse labels in case we throw away the assembler without calling GetCode.
    104   entry_label_.Unuse();
    105   start_label_.Unuse();
    106   success_label_.Unuse();
    107   backtrack_label_.Unuse();
    108   exit_label_.Unuse();
    109   check_preempt_label_.Unuse();
    110   stack_overflow_label_.Unuse();
    111 }
    112 
    113 
    114 int RegExpMacroAssemblerIA32::stack_limit_slack()  {
    115   return RegExpStack::kStackLimitSlack;
    116 }
    117 
    118 
    119 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) {
    120   if (by != 0) {
    121     __ add(edi, Immediate(by * char_size()));
    122   }
    123 }
    124 
    125 
    126 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) {
    127   DCHECK(reg >= 0);
    128   DCHECK(reg < num_registers_);
    129   if (by != 0) {
    130     __ add(register_location(reg), Immediate(by));
    131   }
    132 }
    133 
    134 
    135 void RegExpMacroAssemblerIA32::Backtrack() {
    136   CheckPreemption();
    137   // Pop Code* offset from backtrack stack, add Code* and jump to location.
    138   Pop(ebx);
    139   __ add(ebx, Immediate(masm_->CodeObject()));
    140   __ jmp(ebx);
    141 }
    142 
    143 
    144 void RegExpMacroAssemblerIA32::Bind(Label* label) {
    145   __ bind(label);
    146 }
    147 
    148 
    149 void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) {
    150   __ cmp(current_character(), c);
    151   BranchOrBacktrack(equal, on_equal);
    152 }
    153 
    154 
    155 void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) {
    156   __ cmp(current_character(), limit);
    157   BranchOrBacktrack(greater, on_greater);
    158 }
    159 
    160 
    161 void RegExpMacroAssemblerIA32::CheckAtStart(Label* on_at_start) {
    162   Label not_at_start;
    163   // Did we start the match at the start of the string at all?
    164   __ cmp(Operand(ebp, kStartIndex), Immediate(0));
    165   BranchOrBacktrack(not_equal, &not_at_start);
    166   // If we did, are we still at the start of the input?
    167   __ lea(eax, Operand(esi, edi, times_1, 0));
    168   __ cmp(eax, Operand(ebp, kInputStart));
    169   BranchOrBacktrack(equal, on_at_start);
    170   __ bind(&not_at_start);
    171 }
    172 
    173 
    174 void RegExpMacroAssemblerIA32::CheckNotAtStart(Label* on_not_at_start) {
    175   // Did we start the match at the start of the string at all?
    176   __ cmp(Operand(ebp, kStartIndex), Immediate(0));
    177   BranchOrBacktrack(not_equal, on_not_at_start);
    178   // If we did, are we still at the start of the input?
    179   __ lea(eax, Operand(esi, edi, times_1, 0));
    180   __ cmp(eax, Operand(ebp, kInputStart));
    181   BranchOrBacktrack(not_equal, on_not_at_start);
    182 }
    183 
    184 
    185 void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) {
    186   __ cmp(current_character(), limit);
    187   BranchOrBacktrack(less, on_less);
    188 }
    189 
    190 
    191 void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) {
    192   Label fallthrough;
    193   __ cmp(edi, Operand(backtrack_stackpointer(), 0));
    194   __ j(not_equal, &fallthrough);
    195   __ add(backtrack_stackpointer(), Immediate(kPointerSize));  // Pop.
    196   BranchOrBacktrack(no_condition, on_equal);
    197   __ bind(&fallthrough);
    198 }
    199 
    200 
    201 void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
    202     int start_reg,
    203     Label* on_no_match) {
    204   Label fallthrough;
    205   __ mov(edx, register_location(start_reg));  // Index of start of capture
    206   __ mov(ebx, register_location(start_reg + 1));  // Index of end of capture
    207   __ sub(ebx, edx);  // Length of capture.
    208 
    209   // The length of a capture should not be negative. This can only happen
    210   // if the end of the capture is unrecorded, or at a point earlier than
    211   // the start of the capture.
    212   BranchOrBacktrack(less, on_no_match);
    213 
    214   // If length is zero, either the capture is empty or it is completely
    215   // uncaptured. In either case succeed immediately.
    216   __ j(equal, &fallthrough);
    217 
    218   // Check that there are sufficient characters left in the input.
    219   __ mov(eax, edi);
    220   __ add(eax, ebx);
    221   BranchOrBacktrack(greater, on_no_match);
    222 
    223   if (mode_ == LATIN1) {
    224     Label success;
    225     Label fail;
    226     Label loop_increment;
    227     // Save register contents to make the registers available below.
    228     __ push(edi);
    229     __ push(backtrack_stackpointer());
    230     // After this, the eax, ecx, and edi registers are available.
    231 
    232     __ add(edx, esi);  // Start of capture
    233     __ add(edi, esi);  // Start of text to match against capture.
    234     __ add(ebx, edi);  // End of text to match against capture.
    235 
    236     Label loop;
    237     __ bind(&loop);
    238     __ movzx_b(eax, Operand(edi, 0));
    239     __ cmpb_al(Operand(edx, 0));
    240     __ j(equal, &loop_increment);
    241 
    242     // Mismatch, try case-insensitive match (converting letters to lower-case).
    243     __ or_(eax, 0x20);  // Convert match character to lower-case.
    244     __ lea(ecx, Operand(eax, -'a'));
    245     __ cmp(ecx, static_cast<int32_t>('z' - 'a'));  // Is eax a lowercase letter?
    246     Label convert_capture;
    247     __ j(below_equal, &convert_capture);  // In range 'a'-'z'.
    248     // Latin-1: Check for values in range [224,254] but not 247.
    249     __ sub(ecx, Immediate(224 - 'a'));
    250     __ cmp(ecx, Immediate(254 - 224));
    251     __ j(above, &fail);  // Weren't Latin-1 letters.
    252     __ cmp(ecx, Immediate(247 - 224));  // Check for 247.
    253     __ j(equal, &fail);
    254     __ bind(&convert_capture);
    255     // Also convert capture character.
    256     __ movzx_b(ecx, Operand(edx, 0));
    257     __ or_(ecx, 0x20);
    258 
    259     __ cmp(eax, ecx);
    260     __ j(not_equal, &fail);
    261 
    262     __ bind(&loop_increment);
    263     // Increment pointers into match and capture strings.
    264     __ add(edx, Immediate(1));
    265     __ add(edi, Immediate(1));
    266     // Compare to end of match, and loop if not done.
    267     __ cmp(edi, ebx);
    268     __ j(below, &loop);
    269     __ jmp(&success);
    270 
    271     __ bind(&fail);
    272     // Restore original values before failing.
    273     __ pop(backtrack_stackpointer());
    274     __ pop(edi);
    275     BranchOrBacktrack(no_condition, on_no_match);
    276 
    277     __ bind(&success);
    278     // Restore original value before continuing.
    279     __ pop(backtrack_stackpointer());
    280     // Drop original value of character position.
    281     __ add(esp, Immediate(kPointerSize));
    282     // Compute new value of character position after the matched part.
    283     __ sub(edi, esi);
    284   } else {
    285     DCHECK(mode_ == UC16);
    286     // Save registers before calling C function.
    287     __ push(esi);
    288     __ push(edi);
    289     __ push(backtrack_stackpointer());
    290     __ push(ebx);
    291 
    292     static const int argument_count = 4;
    293     __ PrepareCallCFunction(argument_count, ecx);
    294     // Put arguments into allocated stack area, last argument highest on stack.
    295     // Parameters are
    296     //   Address byte_offset1 - Address captured substring's start.
    297     //   Address byte_offset2 - Address of current character position.
    298     //   size_t byte_length - length of capture in bytes(!)
    299     //   Isolate* isolate
    300 
    301     // Set isolate.
    302     __ mov(Operand(esp, 3 * kPointerSize),
    303            Immediate(ExternalReference::isolate_address(isolate())));
    304     // Set byte_length.
    305     __ mov(Operand(esp, 2 * kPointerSize), ebx);
    306     // Set byte_offset2.
    307     // Found by adding negative string-end offset of current position (edi)
    308     // to end of string.
    309     __ add(edi, esi);
    310     __ mov(Operand(esp, 1 * kPointerSize), edi);
    311     // Set byte_offset1.
    312     // Start of capture, where edx already holds string-end negative offset.
    313     __ add(edx, esi);
    314     __ mov(Operand(esp, 0 * kPointerSize), edx);
    315 
    316     {
    317       AllowExternalCallThatCantCauseGC scope(masm_);
    318       ExternalReference compare =
    319           ExternalReference::re_case_insensitive_compare_uc16(isolate());
    320       __ CallCFunction(compare, argument_count);
    321     }
    322     // Pop original values before reacting on result value.
    323     __ pop(ebx);
    324     __ pop(backtrack_stackpointer());
    325     __ pop(edi);
    326     __ pop(esi);
    327 
    328     // Check if function returned non-zero for success or zero for failure.
    329     __ or_(eax, eax);
    330     BranchOrBacktrack(zero, on_no_match);
    331     // On success, increment position by length of capture.
    332     __ add(edi, ebx);
    333   }
    334   __ bind(&fallthrough);
    335 }
    336 
    337 
    338 void RegExpMacroAssemblerIA32::CheckNotBackReference(
    339     int start_reg,
    340     Label* on_no_match) {
    341   Label fallthrough;
    342   Label success;
    343   Label fail;
    344 
    345   // Find length of back-referenced capture.
    346   __ mov(edx, register_location(start_reg));
    347   __ mov(eax, register_location(start_reg + 1));
    348   __ sub(eax, edx);  // Length to check.
    349   // Fail on partial or illegal capture (start of capture after end of capture).
    350   BranchOrBacktrack(less, on_no_match);
    351   // Succeed on empty capture (including no capture)
    352   __ j(equal, &fallthrough);
    353 
    354   // Check that there are sufficient characters left in the input.
    355   __ mov(ebx, edi);
    356   __ add(ebx, eax);
    357   BranchOrBacktrack(greater, on_no_match);
    358 
    359   // Save register to make it available below.
    360   __ push(backtrack_stackpointer());
    361 
    362   // Compute pointers to match string and capture string
    363   __ lea(ebx, Operand(esi, edi, times_1, 0));  // Start of match.
    364   __ add(edx, esi);  // Start of capture.
    365   __ lea(ecx, Operand(eax, ebx, times_1, 0));  // End of match
    366 
    367   Label loop;
    368   __ bind(&loop);
    369   if (mode_ == LATIN1) {
    370     __ movzx_b(eax, Operand(edx, 0));
    371     __ cmpb_al(Operand(ebx, 0));
    372   } else {
    373     DCHECK(mode_ == UC16);
    374     __ movzx_w(eax, Operand(edx, 0));
    375     __ cmpw_ax(Operand(ebx, 0));
    376   }
    377   __ j(not_equal, &fail);
    378   // Increment pointers into capture and match string.
    379   __ add(edx, Immediate(char_size()));
    380   __ add(ebx, Immediate(char_size()));
    381   // Check if we have reached end of match area.
    382   __ cmp(ebx, ecx);
    383   __ j(below, &loop);
    384   __ jmp(&success);
    385 
    386   __ bind(&fail);
    387   // Restore backtrack stackpointer.
    388   __ pop(backtrack_stackpointer());
    389   BranchOrBacktrack(no_condition, on_no_match);
    390 
    391   __ bind(&success);
    392   // Move current character position to position after match.
    393   __ mov(edi, ecx);
    394   __ sub(edi, esi);
    395   // Restore backtrack stackpointer.
    396   __ pop(backtrack_stackpointer());
    397 
    398   __ bind(&fallthrough);
    399 }
    400 
    401 
    402 void RegExpMacroAssemblerIA32::CheckNotCharacter(uint32_t c,
    403                                                  Label* on_not_equal) {
    404   __ cmp(current_character(), c);
    405   BranchOrBacktrack(not_equal, on_not_equal);
    406 }
    407 
    408 
    409 void RegExpMacroAssemblerIA32::CheckCharacterAfterAnd(uint32_t c,
    410                                                       uint32_t mask,
    411                                                       Label* on_equal) {
    412   if (c == 0) {
    413     __ test(current_character(), Immediate(mask));
    414   } else {
    415     __ mov(eax, mask);
    416     __ and_(eax, current_character());
    417     __ cmp(eax, c);
    418   }
    419   BranchOrBacktrack(equal, on_equal);
    420 }
    421 
    422 
    423 void RegExpMacroAssemblerIA32::CheckNotCharacterAfterAnd(uint32_t c,
    424                                                          uint32_t mask,
    425                                                          Label* on_not_equal) {
    426   if (c == 0) {
    427     __ test(current_character(), Immediate(mask));
    428   } else {
    429     __ mov(eax, mask);
    430     __ and_(eax, current_character());
    431     __ cmp(eax, c);
    432   }
    433   BranchOrBacktrack(not_equal, on_not_equal);
    434 }
    435 
    436 
    437 void RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusAnd(
    438     uc16 c,
    439     uc16 minus,
    440     uc16 mask,
    441     Label* on_not_equal) {
    442   DCHECK(minus < String::kMaxUtf16CodeUnit);
    443   __ lea(eax, Operand(current_character(), -minus));
    444   if (c == 0) {
    445     __ test(eax, Immediate(mask));
    446   } else {
    447     __ and_(eax, mask);
    448     __ cmp(eax, c);
    449   }
    450   BranchOrBacktrack(not_equal, on_not_equal);
    451 }
    452 
    453 
    454 void RegExpMacroAssemblerIA32::CheckCharacterInRange(
    455     uc16 from,
    456     uc16 to,
    457     Label* on_in_range) {
    458   __ lea(eax, Operand(current_character(), -from));
    459   __ cmp(eax, to - from);
    460   BranchOrBacktrack(below_equal, on_in_range);
    461 }
    462 
    463 
    464 void RegExpMacroAssemblerIA32::CheckCharacterNotInRange(
    465     uc16 from,
    466     uc16 to,
    467     Label* on_not_in_range) {
    468   __ lea(eax, Operand(current_character(), -from));
    469   __ cmp(eax, to - from);
    470   BranchOrBacktrack(above, on_not_in_range);
    471 }
    472 
    473 
    474 void RegExpMacroAssemblerIA32::CheckBitInTable(
    475     Handle<ByteArray> table,
    476     Label* on_bit_set) {
    477   __ mov(eax, Immediate(table));
    478   Register index = current_character();
    479   if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) {
    480     __ mov(ebx, kTableSize - 1);
    481     __ and_(ebx, current_character());
    482     index = ebx;
    483   }
    484   __ cmpb(FieldOperand(eax, index, times_1, ByteArray::kHeaderSize), 0);
    485   BranchOrBacktrack(not_equal, on_bit_set);
    486 }
    487 
    488 
    489 bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type,
    490                                                           Label* on_no_match) {
    491   // Range checks (c in min..max) are generally implemented by an unsigned
    492   // (c - min) <= (max - min) check
    493   switch (type) {
    494   case 's':
    495     // Match space-characters
    496     if (mode_ == LATIN1) {
    497       // One byte space characters are '\t'..'\r', ' ' and \u00a0.
    498       Label success;
    499       __ cmp(current_character(), ' ');
    500       __ j(equal, &success, Label::kNear);
    501       // Check range 0x09..0x0d
    502       __ lea(eax, Operand(current_character(), -'\t'));
    503       __ cmp(eax, '\r' - '\t');
    504       __ j(below_equal, &success, Label::kNear);
    505       // \u00a0 (NBSP).
    506       __ cmp(eax, 0x00a0 - '\t');
    507       BranchOrBacktrack(not_equal, on_no_match);
    508       __ bind(&success);
    509       return true;
    510     }
    511     return false;
    512   case 'S':
    513     // The emitted code for generic character classes is good enough.
    514     return false;
    515   case 'd':
    516     // Match ASCII digits ('0'..'9')
    517     __ lea(eax, Operand(current_character(), -'0'));
    518     __ cmp(eax, '9' - '0');
    519     BranchOrBacktrack(above, on_no_match);
    520     return true;
    521   case 'D':
    522     // Match non ASCII-digits
    523     __ lea(eax, Operand(current_character(), -'0'));
    524     __ cmp(eax, '9' - '0');
    525     BranchOrBacktrack(below_equal, on_no_match);
    526     return true;
    527   case '.': {
    528     // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
    529     __ mov(eax, current_character());
    530     __ xor_(eax, Immediate(0x01));
    531     // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
    532     __ sub(eax, Immediate(0x0b));
    533     __ cmp(eax, 0x0c - 0x0b);
    534     BranchOrBacktrack(below_equal, on_no_match);
    535     if (mode_ == UC16) {
    536       // Compare original value to 0x2028 and 0x2029, using the already
    537       // computed (current_char ^ 0x01 - 0x0b). I.e., check for
    538       // 0x201d (0x2028 - 0x0b) or 0x201e.
    539       __ sub(eax, Immediate(0x2028 - 0x0b));
    540       __ cmp(eax, 0x2029 - 0x2028);
    541       BranchOrBacktrack(below_equal, on_no_match);
    542     }
    543     return true;
    544   }
    545   case 'w': {
    546     if (mode_ != LATIN1) {
    547       // Table is 256 entries, so all Latin1 characters can be tested.
    548       __ cmp(current_character(), Immediate('z'));
    549       BranchOrBacktrack(above, on_no_match);
    550     }
    551     DCHECK_EQ(0, word_character_map[0]);  // Character '\0' is not a word char.
    552     ExternalReference word_map = ExternalReference::re_word_character_map();
    553     __ test_b(current_character(),
    554               Operand::StaticArray(current_character(), times_1, word_map));
    555     BranchOrBacktrack(zero, on_no_match);
    556     return true;
    557   }
    558   case 'W': {
    559     Label done;
    560     if (mode_ != LATIN1) {
    561       // Table is 256 entries, so all Latin1 characters can be tested.
    562       __ cmp(current_character(), Immediate('z'));
    563       __ j(above, &done);
    564     }
    565     DCHECK_EQ(0, word_character_map[0]);  // Character '\0' is not a word char.
    566     ExternalReference word_map = ExternalReference::re_word_character_map();
    567     __ test_b(current_character(),
    568               Operand::StaticArray(current_character(), times_1, word_map));
    569     BranchOrBacktrack(not_zero, on_no_match);
    570     if (mode_ != LATIN1) {
    571       __ bind(&done);
    572     }
    573     return true;
    574   }
    575   // Non-standard classes (with no syntactic shorthand) used internally.
    576   case '*':
    577     // Match any character.
    578     return true;
    579   case 'n': {
    580     // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029).
    581     // The opposite of '.'.
    582     __ mov(eax, current_character());
    583     __ xor_(eax, Immediate(0x01));
    584     // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
    585     __ sub(eax, Immediate(0x0b));
    586     __ cmp(eax, 0x0c - 0x0b);
    587     if (mode_ == LATIN1) {
    588       BranchOrBacktrack(above, on_no_match);
    589     } else {
    590       Label done;
    591       BranchOrBacktrack(below_equal, &done);
    592       DCHECK_EQ(UC16, mode_);
    593       // Compare original value to 0x2028 and 0x2029, using the already
    594       // computed (current_char ^ 0x01 - 0x0b). I.e., check for
    595       // 0x201d (0x2028 - 0x0b) or 0x201e.
    596       __ sub(eax, Immediate(0x2028 - 0x0b));
    597       __ cmp(eax, 1);
    598       BranchOrBacktrack(above, on_no_match);
    599       __ bind(&done);
    600     }
    601     return true;
    602   }
    603   // No custom implementation (yet): s(UC16), S(UC16).
    604   default:
    605     return false;
    606   }
    607 }
    608 
    609 
    610 void RegExpMacroAssemblerIA32::Fail() {
    611   STATIC_ASSERT(FAILURE == 0);  // Return value for failure is zero.
    612   if (!global()) {
    613     __ Move(eax, Immediate(FAILURE));
    614   }
    615   __ jmp(&exit_label_);
    616 }
    617 
    618 
    619 Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
    620   Label return_eax;
    621   // Finalize code - write the entry point code now we know how many
    622   // registers we need.
    623 
    624   // Entry code:
    625   __ bind(&entry_label_);
    626 
    627   // Tell the system that we have a stack frame.  Because the type is MANUAL, no
    628   // code is generated.
    629   FrameScope scope(masm_, StackFrame::MANUAL);
    630 
    631   // Actually emit code to start a new stack frame.
    632   __ push(ebp);
    633   __ mov(ebp, esp);
    634   // Save callee-save registers. Order here should correspond to order of
    635   // kBackup_ebx etc.
    636   __ push(esi);
    637   __ push(edi);
    638   __ push(ebx);  // Callee-save on MacOS.
    639   __ push(Immediate(0));  // Number of successful matches in a global regexp.
    640   __ push(Immediate(0));  // Make room for "input start - 1" constant.
    641 
    642   // Check if we have space on the stack for registers.
    643   Label stack_limit_hit;
    644   Label stack_ok;
    645 
    646   ExternalReference stack_limit =
    647       ExternalReference::address_of_stack_limit(isolate());
    648   __ mov(ecx, esp);
    649   __ sub(ecx, Operand::StaticVariable(stack_limit));
    650   // Handle it if the stack pointer is already below the stack limit.
    651   __ j(below_equal, &stack_limit_hit);
    652   // Check if there is room for the variable number of registers above
    653   // the stack limit.
    654   __ cmp(ecx, num_registers_ * kPointerSize);
    655   __ j(above_equal, &stack_ok);
    656   // Exit with OutOfMemory exception. There is not enough space on the stack
    657   // for our working registers.
    658   __ mov(eax, EXCEPTION);
    659   __ jmp(&return_eax);
    660 
    661   __ bind(&stack_limit_hit);
    662   CallCheckStackGuardState(ebx);
    663   __ or_(eax, eax);
    664   // If returned value is non-zero, we exit with the returned value as result.
    665   __ j(not_zero, &return_eax);
    666 
    667   __ bind(&stack_ok);
    668   // Load start index for later use.
    669   __ mov(ebx, Operand(ebp, kStartIndex));
    670 
    671   // Allocate space on stack for registers.
    672   __ sub(esp, Immediate(num_registers_ * kPointerSize));
    673   // Load string length.
    674   __ mov(esi, Operand(ebp, kInputEnd));
    675   // Load input position.
    676   __ mov(edi, Operand(ebp, kInputStart));
    677   // Set up edi to be negative offset from string end.
    678   __ sub(edi, esi);
    679 
    680   // Set eax to address of char before start of the string.
    681   // (effectively string position -1).
    682   __ neg(ebx);
    683   if (mode_ == UC16) {
    684     __ lea(eax, Operand(edi, ebx, times_2, -char_size()));
    685   } else {
    686     __ lea(eax, Operand(edi, ebx, times_1, -char_size()));
    687   }
    688   // Store this value in a local variable, for use when clearing
    689   // position registers.
    690   __ mov(Operand(ebp, kInputStartMinusOne), eax);
    691 
    692 #if V8_OS_WIN
    693   // Ensure that we write to each stack page, in order. Skipping a page
    694   // on Windows can cause segmentation faults. Assuming page size is 4k.
    695   const int kPageSize = 4096;
    696   const int kRegistersPerPage = kPageSize / kPointerSize;
    697   for (int i = num_saved_registers_ + kRegistersPerPage - 1;
    698       i < num_registers_;
    699       i += kRegistersPerPage) {
    700     __ mov(register_location(i), eax);  // One write every page.
    701   }
    702 #endif  // V8_OS_WIN
    703 
    704   Label load_char_start_regexp, start_regexp;
    705   // Load newline if index is at start, previous character otherwise.
    706   __ cmp(Operand(ebp, kStartIndex), Immediate(0));
    707   __ j(not_equal, &load_char_start_regexp, Label::kNear);
    708   __ mov(current_character(), '\n');
    709   __ jmp(&start_regexp, Label::kNear);
    710 
    711   // Global regexp restarts matching here.
    712   __ bind(&load_char_start_regexp);
    713   // Load previous char as initial value of current character register.
    714   LoadCurrentCharacterUnchecked(-1, 1);
    715   __ bind(&start_regexp);
    716 
    717   // Initialize on-stack registers.
    718   if (num_saved_registers_ > 0) {  // Always is, if generated from a regexp.
    719     // Fill saved registers with initial value = start offset - 1
    720     // Fill in stack push order, to avoid accessing across an unwritten
    721     // page (a problem on Windows).
    722     if (num_saved_registers_ > 8) {
    723       __ mov(ecx, kRegisterZero);
    724       Label init_loop;
    725       __ bind(&init_loop);
    726       __ mov(Operand(ebp, ecx, times_1, 0), eax);
    727       __ sub(ecx, Immediate(kPointerSize));
    728       __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize);
    729       __ j(greater, &init_loop);
    730     } else {  // Unroll the loop.
    731       for (int i = 0; i < num_saved_registers_; i++) {
    732         __ mov(register_location(i), eax);
    733       }
    734     }
    735   }
    736 
    737   // Initialize backtrack stack pointer.
    738   __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
    739 
    740   __ jmp(&start_label_);
    741 
    742   // Exit code:
    743   if (success_label_.is_linked()) {
    744     // Save captures when successful.
    745     __ bind(&success_label_);
    746     if (num_saved_registers_ > 0) {
    747       // copy captures to output
    748       __ mov(ebx, Operand(ebp, kRegisterOutput));
    749       __ mov(ecx, Operand(ebp, kInputEnd));
    750       __ mov(edx, Operand(ebp, kStartIndex));
    751       __ sub(ecx, Operand(ebp, kInputStart));
    752       if (mode_ == UC16) {
    753         __ lea(ecx, Operand(ecx, edx, times_2, 0));
    754       } else {
    755         __ add(ecx, edx);
    756       }
    757       for (int i = 0; i < num_saved_registers_; i++) {
    758         __ mov(eax, register_location(i));
    759         if (i == 0 && global_with_zero_length_check()) {
    760           // Keep capture start in edx for the zero-length check later.
    761           __ mov(edx, eax);
    762         }
    763         // Convert to index from start of string, not end.
    764         __ add(eax, ecx);
    765         if (mode_ == UC16) {
    766           __ sar(eax, 1);  // Convert byte index to character index.
    767         }
    768         __ mov(Operand(ebx, i * kPointerSize), eax);
    769       }
    770     }
    771 
    772     if (global()) {
    773     // Restart matching if the regular expression is flagged as global.
    774       // Increment success counter.
    775       __ inc(Operand(ebp, kSuccessfulCaptures));
    776       // Capture results have been stored, so the number of remaining global
    777       // output registers is reduced by the number of stored captures.
    778       __ mov(ecx, Operand(ebp, kNumOutputRegisters));
    779       __ sub(ecx, Immediate(num_saved_registers_));
    780       // Check whether we have enough room for another set of capture results.
    781       __ cmp(ecx, Immediate(num_saved_registers_));
    782       __ j(less, &exit_label_);
    783 
    784       __ mov(Operand(ebp, kNumOutputRegisters), ecx);
    785       // Advance the location for output.
    786       __ add(Operand(ebp, kRegisterOutput),
    787              Immediate(num_saved_registers_ * kPointerSize));
    788 
    789       // Prepare eax to initialize registers with its value in the next run.
    790       __ mov(eax, Operand(ebp, kInputStartMinusOne));
    791 
    792       if (global_with_zero_length_check()) {
    793         // Special case for zero-length matches.
    794         // edx: capture start index
    795         __ cmp(edi, edx);
    796         // Not a zero-length match, restart.
    797         __ j(not_equal, &load_char_start_regexp);
    798         // edi (offset from the end) is zero if we already reached the end.
    799         __ test(edi, edi);
    800         __ j(zero, &exit_label_, Label::kNear);
    801         // Advance current position after a zero-length match.
    802         if (mode_ == UC16) {
    803           __ add(edi, Immediate(2));
    804         } else {
    805           __ inc(edi);
    806         }
    807       }
    808 
    809       __ jmp(&load_char_start_regexp);
    810     } else {
    811       __ mov(eax, Immediate(SUCCESS));
    812     }
    813   }
    814 
    815   __ bind(&exit_label_);
    816   if (global()) {
    817     // Return the number of successful captures.
    818     __ mov(eax, Operand(ebp, kSuccessfulCaptures));
    819   }
    820 
    821   __ bind(&return_eax);
    822   // Skip esp past regexp registers.
    823   __ lea(esp, Operand(ebp, kBackup_ebx));
    824   // Restore callee-save registers.
    825   __ pop(ebx);
    826   __ pop(edi);
    827   __ pop(esi);
    828   // Exit function frame, restore previous one.
    829   __ pop(ebp);
    830   __ ret(0);
    831 
    832   // Backtrack code (branch target for conditional backtracks).
    833   if (backtrack_label_.is_linked()) {
    834     __ bind(&backtrack_label_);
    835     Backtrack();
    836   }
    837 
    838   Label exit_with_exception;
    839 
    840   // Preempt-code
    841   if (check_preempt_label_.is_linked()) {
    842     SafeCallTarget(&check_preempt_label_);
    843 
    844     __ push(backtrack_stackpointer());
    845     __ push(edi);
    846 
    847     CallCheckStackGuardState(ebx);
    848     __ or_(eax, eax);
    849     // If returning non-zero, we should end execution with the given
    850     // result as return value.
    851     __ j(not_zero, &return_eax);
    852 
    853     __ pop(edi);
    854     __ pop(backtrack_stackpointer());
    855     // String might have moved: Reload esi from frame.
    856     __ mov(esi, Operand(ebp, kInputEnd));
    857     SafeReturn();
    858   }
    859 
    860   // Backtrack stack overflow code.
    861   if (stack_overflow_label_.is_linked()) {
    862     SafeCallTarget(&stack_overflow_label_);
    863     // Reached if the backtrack-stack limit has been hit.
    864 
    865     Label grow_failed;
    866     // Save registers before calling C function
    867     __ push(esi);
    868     __ push(edi);
    869 
    870     // Call GrowStack(backtrack_stackpointer())
    871     static const int num_arguments = 3;
    872     __ PrepareCallCFunction(num_arguments, ebx);
    873     __ mov(Operand(esp, 2 * kPointerSize),
    874            Immediate(ExternalReference::isolate_address(isolate())));
    875     __ lea(eax, Operand(ebp, kStackHighEnd));
    876     __ mov(Operand(esp, 1 * kPointerSize), eax);
    877     __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer());
    878     ExternalReference grow_stack =
    879         ExternalReference::re_grow_stack(isolate());
    880     __ CallCFunction(grow_stack, num_arguments);
    881     // If return NULL, we have failed to grow the stack, and
    882     // must exit with a stack-overflow exception.
    883     __ or_(eax, eax);
    884     __ j(equal, &exit_with_exception);
    885     // Otherwise use return value as new stack pointer.
    886     __ mov(backtrack_stackpointer(), eax);
    887     // Restore saved registers and continue.
    888     __ pop(edi);
    889     __ pop(esi);
    890     SafeReturn();
    891   }
    892 
    893   if (exit_with_exception.is_linked()) {
    894     // If any of the code above needed to exit with an exception.
    895     __ bind(&exit_with_exception);
    896     // Exit with Result EXCEPTION(-1) to signal thrown exception.
    897     __ mov(eax, EXCEPTION);
    898     __ jmp(&return_eax);
    899   }
    900 
    901   CodeDesc code_desc;
    902   masm_->GetCode(&code_desc);
    903   Handle<Code> code =
    904       isolate()->factory()->NewCode(code_desc,
    905                                     Code::ComputeFlags(Code::REGEXP),
    906                                     masm_->CodeObject());
    907   PROFILE(isolate(), RegExpCodeCreateEvent(*code, *source));
    908   return Handle<HeapObject>::cast(code);
    909 }
    910 
    911 
    912 void RegExpMacroAssemblerIA32::GoTo(Label* to) {
    913   BranchOrBacktrack(no_condition, to);
    914 }
    915 
    916 
    917 void RegExpMacroAssemblerIA32::IfRegisterGE(int reg,
    918                                             int comparand,
    919                                             Label* if_ge) {
    920   __ cmp(register_location(reg), Immediate(comparand));
    921   BranchOrBacktrack(greater_equal, if_ge);
    922 }
    923 
    924 
    925 void RegExpMacroAssemblerIA32::IfRegisterLT(int reg,
    926                                             int comparand,
    927                                             Label* if_lt) {
    928   __ cmp(register_location(reg), Immediate(comparand));
    929   BranchOrBacktrack(less, if_lt);
    930 }
    931 
    932 
    933 void RegExpMacroAssemblerIA32::IfRegisterEqPos(int reg,
    934                                                Label* if_eq) {
    935   __ cmp(edi, register_location(reg));
    936   BranchOrBacktrack(equal, if_eq);
    937 }
    938 
    939 
    940 RegExpMacroAssembler::IrregexpImplementation
    941     RegExpMacroAssemblerIA32::Implementation() {
    942   return kIA32Implementation;
    943 }
    944 
    945 
    946 void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset,
    947                                                     Label* on_end_of_input,
    948                                                     bool check_bounds,
    949                                                     int characters) {
    950   DCHECK(cp_offset >= -1);      // ^ and \b can look behind one character.
    951   DCHECK(cp_offset < (1<<30));  // Be sane! (And ensure negation works)
    952   if (check_bounds) {
    953     CheckPosition(cp_offset + characters - 1, on_end_of_input);
    954   }
    955   LoadCurrentCharacterUnchecked(cp_offset, characters);
    956 }
    957 
    958 
    959 void RegExpMacroAssemblerIA32::PopCurrentPosition() {
    960   Pop(edi);
    961 }
    962 
    963 
    964 void RegExpMacroAssemblerIA32::PopRegister(int register_index) {
    965   Pop(eax);
    966   __ mov(register_location(register_index), eax);
    967 }
    968 
    969 
    970 void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) {
    971   Push(Immediate::CodeRelativeOffset(label));
    972   CheckStackLimit();
    973 }
    974 
    975 
    976 void RegExpMacroAssemblerIA32::PushCurrentPosition() {
    977   Push(edi);
    978 }
    979 
    980 
    981 void RegExpMacroAssemblerIA32::PushRegister(int register_index,
    982                                             StackCheckFlag check_stack_limit) {
    983   __ mov(eax, register_location(register_index));
    984   Push(eax);
    985   if (check_stack_limit) CheckStackLimit();
    986 }
    987 
    988 
    989 void RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) {
    990   __ mov(edi, register_location(reg));
    991 }
    992 
    993 
    994 void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) {
    995   __ mov(backtrack_stackpointer(), register_location(reg));
    996   __ add(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
    997 }
    998 
    999 void RegExpMacroAssemblerIA32::SetCurrentPositionFromEnd(int by)  {
   1000   Label after_position;
   1001   __ cmp(edi, -by * char_size());
   1002   __ j(greater_equal, &after_position, Label::kNear);
   1003   __ mov(edi, -by * char_size());
   1004   // On RegExp code entry (where this operation is used), the character before
   1005   // the current position is expected to be already loaded.
   1006   // We have advanced the position, so it's safe to read backwards.
   1007   LoadCurrentCharacterUnchecked(-1, 1);
   1008   __ bind(&after_position);
   1009 }
   1010 
   1011 
   1012 void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) {
   1013   DCHECK(register_index >= num_saved_registers_);  // Reserved for positions!
   1014   __ mov(register_location(register_index), Immediate(to));
   1015 }
   1016 
   1017 
   1018 bool RegExpMacroAssemblerIA32::Succeed() {
   1019   __ jmp(&success_label_);
   1020   return global();
   1021 }
   1022 
   1023 
   1024 void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg,
   1025                                                               int cp_offset) {
   1026   if (cp_offset == 0) {
   1027     __ mov(register_location(reg), edi);
   1028   } else {
   1029     __ lea(eax, Operand(edi, cp_offset * char_size()));
   1030     __ mov(register_location(reg), eax);
   1031   }
   1032 }
   1033 
   1034 
   1035 void RegExpMacroAssemblerIA32::ClearRegisters(int reg_from, int reg_to) {
   1036   DCHECK(reg_from <= reg_to);
   1037   __ mov(eax, Operand(ebp, kInputStartMinusOne));
   1038   for (int reg = reg_from; reg <= reg_to; reg++) {
   1039     __ mov(register_location(reg), eax);
   1040   }
   1041 }
   1042 
   1043 
   1044 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
   1045   __ mov(eax, backtrack_stackpointer());
   1046   __ sub(eax, Operand(ebp, kStackHighEnd));
   1047   __ mov(register_location(reg), eax);
   1048 }
   1049 
   1050 
   1051 // Private methods:
   1052 
   1053 void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) {
   1054   static const int num_arguments = 3;
   1055   __ PrepareCallCFunction(num_arguments, scratch);
   1056   // RegExp code frame pointer.
   1057   __ mov(Operand(esp, 2 * kPointerSize), ebp);
   1058   // Code* of self.
   1059   __ mov(Operand(esp, 1 * kPointerSize), Immediate(masm_->CodeObject()));
   1060   // Next address on the stack (will be address of return address).
   1061   __ lea(eax, Operand(esp, -kPointerSize));
   1062   __ mov(Operand(esp, 0 * kPointerSize), eax);
   1063   ExternalReference check_stack_guard =
   1064       ExternalReference::re_check_stack_guard_state(isolate());
   1065   __ CallCFunction(check_stack_guard, num_arguments);
   1066 }
   1067 
   1068 
   1069 // Helper function for reading a value out of a stack frame.
   1070 template <typename T>
   1071 static T& frame_entry(Address re_frame, int frame_offset) {
   1072   return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset));
   1073 }
   1074 
   1075 
   1076 int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
   1077                                                    Code* re_code,
   1078                                                    Address re_frame) {
   1079   Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
   1080   StackLimitCheck check(isolate);
   1081   if (check.JsHasOverflowed()) {
   1082     isolate->StackOverflow();
   1083     return EXCEPTION;
   1084   }
   1085 
   1086   // If not real stack overflow the stack guard was used to interrupt
   1087   // execution for another purpose.
   1088 
   1089   // If this is a direct call from JavaScript retry the RegExp forcing the call
   1090   // through the runtime system. Currently the direct call cannot handle a GC.
   1091   if (frame_entry<int>(re_frame, kDirectCall) == 1) {
   1092     return RETRY;
   1093   }
   1094 
   1095   // Prepare for possible GC.
   1096   HandleScope handles(isolate);
   1097   Handle<Code> code_handle(re_code);
   1098 
   1099   Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
   1100 
   1101   // Current string.
   1102   bool is_one_byte = subject->IsOneByteRepresentationUnderneath();
   1103 
   1104   DCHECK(re_code->instruction_start() <= *return_address);
   1105   DCHECK(*return_address <=
   1106       re_code->instruction_start() + re_code->instruction_size());
   1107 
   1108   Object* result = isolate->stack_guard()->HandleInterrupts();
   1109 
   1110   if (*code_handle != re_code) {  // Return address no longer valid
   1111     int delta = code_handle->address() - re_code->address();
   1112     // Overwrite the return address on the stack.
   1113     *return_address += delta;
   1114   }
   1115 
   1116   if (result->IsException()) {
   1117     return EXCEPTION;
   1118   }
   1119 
   1120   Handle<String> subject_tmp = subject;
   1121   int slice_offset = 0;
   1122 
   1123   // Extract the underlying string and the slice offset.
   1124   if (StringShape(*subject_tmp).IsCons()) {
   1125     subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
   1126   } else if (StringShape(*subject_tmp).IsSliced()) {
   1127     SlicedString* slice = SlicedString::cast(*subject_tmp);
   1128     subject_tmp = Handle<String>(slice->parent());
   1129     slice_offset = slice->offset();
   1130   }
   1131 
   1132   // String might have changed.
   1133   if (subject_tmp->IsOneByteRepresentation() != is_one_byte) {
   1134     // If we changed between an LATIN1 and an UC16 string, the specialized
   1135     // code cannot be used, and we need to restart regexp matching from
   1136     // scratch (including, potentially, compiling a new version of the code).
   1137     return RETRY;
   1138   }
   1139 
   1140   // Otherwise, the content of the string might have moved. It must still
   1141   // be a sequential or external string with the same content.
   1142   // Update the start and end pointers in the stack frame to the current
   1143   // location (whether it has actually moved or not).
   1144   DCHECK(StringShape(*subject_tmp).IsSequential() ||
   1145       StringShape(*subject_tmp).IsExternal());
   1146 
   1147   // The original start address of the characters to match.
   1148   const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
   1149 
   1150   // Find the current start address of the same character at the current string
   1151   // position.
   1152   int start_index = frame_entry<int>(re_frame, kStartIndex);
   1153   const byte* new_address = StringCharacterPosition(*subject_tmp,
   1154                                                     start_index + slice_offset);
   1155 
   1156   if (start_address != new_address) {
   1157     // If there is a difference, update the object pointer and start and end
   1158     // addresses in the RegExp stack frame to match the new value.
   1159     const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
   1160     int byte_length = static_cast<int>(end_address - start_address);
   1161     frame_entry<const String*>(re_frame, kInputString) = *subject;
   1162     frame_entry<const byte*>(re_frame, kInputStart) = new_address;
   1163     frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
   1164   } else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
   1165     // Subject string might have been a ConsString that underwent
   1166     // short-circuiting during GC. That will not change start_address but
   1167     // will change pointer inside the subject handle.
   1168     frame_entry<const String*>(re_frame, kInputString) = *subject;
   1169   }
   1170 
   1171   return 0;
   1172 }
   1173 
   1174 
   1175 Operand RegExpMacroAssemblerIA32::register_location(int register_index) {
   1176   DCHECK(register_index < (1<<30));
   1177   if (num_registers_ <= register_index) {
   1178     num_registers_ = register_index + 1;
   1179   }
   1180   return Operand(ebp, kRegisterZero - register_index * kPointerSize);
   1181 }
   1182 
   1183 
   1184 void RegExpMacroAssemblerIA32::CheckPosition(int cp_offset,
   1185                                              Label* on_outside_input) {
   1186   __ cmp(edi, -cp_offset * char_size());
   1187   BranchOrBacktrack(greater_equal, on_outside_input);
   1188 }
   1189 
   1190 
   1191 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition,
   1192                                                  Label* to) {
   1193   if (condition < 0) {  // No condition
   1194     if (to == NULL) {
   1195       Backtrack();
   1196       return;
   1197     }
   1198     __ jmp(to);
   1199     return;
   1200   }
   1201   if (to == NULL) {
   1202     __ j(condition, &backtrack_label_);
   1203     return;
   1204   }
   1205   __ j(condition, to);
   1206 }
   1207 
   1208 
   1209 void RegExpMacroAssemblerIA32::SafeCall(Label* to) {
   1210   Label return_to;
   1211   __ push(Immediate::CodeRelativeOffset(&return_to));
   1212   __ jmp(to);
   1213   __ bind(&return_to);
   1214 }
   1215 
   1216 
   1217 void RegExpMacroAssemblerIA32::SafeReturn() {
   1218   __ pop(ebx);
   1219   __ add(ebx, Immediate(masm_->CodeObject()));
   1220   __ jmp(ebx);
   1221 }
   1222 
   1223 
   1224 void RegExpMacroAssemblerIA32::SafeCallTarget(Label* name) {
   1225   __ bind(name);
   1226 }
   1227 
   1228 
   1229 void RegExpMacroAssemblerIA32::Push(Register source) {
   1230   DCHECK(!source.is(backtrack_stackpointer()));
   1231   // Notice: This updates flags, unlike normal Push.
   1232   __ sub(backtrack_stackpointer(), Immediate(kPointerSize));
   1233   __ mov(Operand(backtrack_stackpointer(), 0), source);
   1234 }
   1235 
   1236 
   1237 void RegExpMacroAssemblerIA32::Push(Immediate value) {
   1238   // Notice: This updates flags, unlike normal Push.
   1239   __ sub(backtrack_stackpointer(), Immediate(kPointerSize));
   1240   __ mov(Operand(backtrack_stackpointer(), 0), value);
   1241 }
   1242 
   1243 
   1244 void RegExpMacroAssemblerIA32::Pop(Register target) {
   1245   DCHECK(!target.is(backtrack_stackpointer()));
   1246   __ mov(target, Operand(backtrack_stackpointer(), 0));
   1247   // Notice: This updates flags, unlike normal Pop.
   1248   __ add(backtrack_stackpointer(), Immediate(kPointerSize));
   1249 }
   1250 
   1251 
   1252 void RegExpMacroAssemblerIA32::CheckPreemption() {
   1253   // Check for preemption.
   1254   Label no_preempt;
   1255   ExternalReference stack_limit =
   1256       ExternalReference::address_of_stack_limit(isolate());
   1257   __ cmp(esp, Operand::StaticVariable(stack_limit));
   1258   __ j(above, &no_preempt);
   1259 
   1260   SafeCall(&check_preempt_label_);
   1261 
   1262   __ bind(&no_preempt);
   1263 }
   1264 
   1265 
   1266 void RegExpMacroAssemblerIA32::CheckStackLimit() {
   1267   Label no_stack_overflow;
   1268   ExternalReference stack_limit =
   1269       ExternalReference::address_of_regexp_stack_limit(isolate());
   1270   __ cmp(backtrack_stackpointer(), Operand::StaticVariable(stack_limit));
   1271   __ j(above, &no_stack_overflow);
   1272 
   1273   SafeCall(&stack_overflow_label_);
   1274 
   1275   __ bind(&no_stack_overflow);
   1276 }
   1277 
   1278 
   1279 void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset,
   1280                                                              int characters) {
   1281   if (mode_ == LATIN1) {
   1282     if (characters == 4) {
   1283       __ mov(current_character(), Operand(esi, edi, times_1, cp_offset));
   1284     } else if (characters == 2) {
   1285       __ movzx_w(current_character(), Operand(esi, edi, times_1, cp_offset));
   1286     } else {
   1287       DCHECK(characters == 1);
   1288       __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset));
   1289     }
   1290   } else {
   1291     DCHECK(mode_ == UC16);
   1292     if (characters == 2) {
   1293       __ mov(current_character(),
   1294              Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
   1295     } else {
   1296       DCHECK(characters == 1);
   1297       __ movzx_w(current_character(),
   1298                  Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
   1299     }
   1300   }
   1301 }
   1302 
   1303 
   1304 #undef __
   1305 
   1306 #endif  // V8_INTERPRETED_REGEXP
   1307 
   1308 }}  // namespace v8::internal
   1309 
   1310 #endif  // V8_TARGET_ARCH_IA32
   1311