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