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