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