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