V8 Project
regexp-macro-assembler-arm.cc
Go to the documentation of this file.
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"
14 #include "src/regexp-stack.h"
15 #include "src/unicode.h"
16 
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 
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);
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  }
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
RegExpMacroAssemblerARM(Mode mode, int registers_to_save, Zone *zone)
#define PROFILE(IsolateGetter, Call)
Definition: cpu-profiler.h:181
#define __
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes to(mksnapshot only)") DEFINE_STRING(raw_context_file
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
static int Push(SpecialRPOStackFrame *stack, int depth, BasicBlock *child, int unvisited)
Definition: scheduler.cc:773
const int kPointerSize
Definition: globals.h:129
const Register r2
@ UNALIGNED_ACCESSES
Definition: globals.h:621
const Register r10
const Register r6
const Register r0
const Register ip
const Register r3
const Register fp
kSerializedDataOffset Object
Definition: objects-inl.h:5322
const Register sp
const Register r4
const Register r9
const Register pc
const Register r5
uint32_t RegList
Definition: frames.h:18
const Register lr
byte * Address
Definition: globals.h:101
const Register r8
const Register r1
const int kHeapObjectTag
Definition: v8.h:5737
uint16_t uc16
Definition: globals.h:184
bool IsAligned(T value, U alignment)
Definition: utils.h:123
const Register r7
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
#define T(name, string, precedence)
Definition: token.cc:25
Definitions and convenience functions for working with unicode.