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