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