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