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