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