v8  3.14.5(node0.10.28)
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 defined(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(Isolate::Current(), 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::CheckCharacters(Vector<const uc16> str,
239  int cp_offset,
240  Label* on_failure,
241  bool check_end_of_string) {
242  if (on_failure == NULL) {
243  // Instead of inlining a backtrack for each test, (re)use the global
244  // backtrack target.
245  on_failure = &backtrack_label_;
246  }
247 
248  if (check_end_of_string) {
249  // Is last character of required match inside string.
250  CheckPosition(cp_offset + str.length() - 1, on_failure);
251  }
252 
253  __ Addu(a0, end_of_input_address(), Operand(current_input_offset()));
254  if (cp_offset != 0) {
255  int byte_offset = cp_offset * char_size();
256  __ Addu(a0, a0, Operand(byte_offset));
257  }
258 
259  // a0 : Address of characters to match against str.
260  int stored_high_byte = 0;
261  for (int i = 0; i < str.length(); i++) {
262  if (mode_ == ASCII) {
263  __ lbu(a1, MemOperand(a0, 0));
264  __ addiu(a0, a0, char_size());
266  BranchOrBacktrack(on_failure, ne, a1, Operand(str[i]));
267  } else {
268  __ lhu(a1, MemOperand(a0, 0));
269  __ addiu(a0, a0, char_size());
270  uc16 match_char = str[i];
271  int match_high_byte = (match_char >> 8);
272  if (match_high_byte == 0) {
273  BranchOrBacktrack(on_failure, ne, a1, Operand(str[i]));
274  } else {
275  if (match_high_byte != stored_high_byte) {
276  __ li(a2, Operand(match_high_byte));
277  stored_high_byte = match_high_byte;
278  }
279  __ Addu(a3, a2, Operand(match_char & 0xff));
280  BranchOrBacktrack(on_failure, ne, a1, Operand(a3));
281  }
282  }
283  }
284 }
285 
286 
287 void RegExpMacroAssemblerMIPS::CheckGreedyLoop(Label* on_equal) {
288  Label backtrack_non_equal;
289  __ lw(a0, MemOperand(backtrack_stackpointer(), 0));
290  __ Branch(&backtrack_non_equal, ne, current_input_offset(), Operand(a0));
291  __ Addu(backtrack_stackpointer(),
292  backtrack_stackpointer(),
293  Operand(kPointerSize));
294  __ bind(&backtrack_non_equal);
295  BranchOrBacktrack(on_equal, eq, current_input_offset(), Operand(a0));
296 }
297 
298 
299 void RegExpMacroAssemblerMIPS::CheckNotBackReferenceIgnoreCase(
300  int start_reg,
301  Label* on_no_match) {
302  Label fallthrough;
303  __ lw(a0, register_location(start_reg)); // Index of start of capture.
304  __ lw(a1, register_location(start_reg + 1)); // Index of end of capture.
305  __ Subu(a1, a1, a0); // Length of capture.
306 
307  // If length is zero, either the capture is empty or it is not participating.
308  // In either case succeed immediately.
309  __ Branch(&fallthrough, eq, a1, Operand(zero_reg));
310 
311  __ Addu(t5, a1, current_input_offset());
312  // Check that there are enough characters left in the input.
313  BranchOrBacktrack(on_no_match, gt, t5, Operand(zero_reg));
314 
315  if (mode_ == ASCII) {
316  Label success;
317  Label fail;
318  Label loop_check;
319 
320  // a0 - offset of start of capture.
321  // a1 - length of capture.
322  __ Addu(a0, a0, Operand(end_of_input_address()));
323  __ Addu(a2, end_of_input_address(), Operand(current_input_offset()));
324  __ Addu(a1, a0, Operand(a1));
325 
326  // a0 - Address of start of capture.
327  // a1 - Address of end of capture.
328  // a2 - Address of current input position.
329 
330  Label loop;
331  __ bind(&loop);
332  __ lbu(a3, MemOperand(a0, 0));
333  __ addiu(a0, a0, char_size());
334  __ lbu(t0, MemOperand(a2, 0));
335  __ addiu(a2, a2, char_size());
336 
337  __ Branch(&loop_check, eq, t0, Operand(a3));
338 
339  // Mismatch, try case-insensitive match (converting letters to lower-case).
340  __ Or(a3, a3, Operand(0x20)); // Convert capture character to lower-case.
341  __ Or(t0, t0, Operand(0x20)); // Also convert input character.
342  __ Branch(&fail, ne, t0, Operand(a3));
343  __ Subu(a3, a3, Operand('a'));
344  __ Branch(&fail, hi, a3, Operand('z' - 'a')); // Is a3 a lowercase letter?
345 
346  __ bind(&loop_check);
347  __ Branch(&loop, lt, a0, Operand(a1));
348  __ jmp(&success);
349 
350  __ bind(&fail);
351  GoTo(on_no_match);
352 
353  __ bind(&success);
354  // Compute new value of character position after the matched part.
355  __ Subu(current_input_offset(), a2, end_of_input_address());
356  } else {
357  ASSERT(mode_ == UC16);
358  // Put regexp engine registers on stack.
359  RegList regexp_registers_to_retain = current_input_offset().bit() |
360  current_character().bit() | backtrack_stackpointer().bit();
361  __ MultiPush(regexp_registers_to_retain);
362 
363  int argument_count = 4;
364  __ PrepareCallCFunction(argument_count, a2);
365 
366  // a0 - offset of start of capture.
367  // a1 - length of capture.
368 
369  // Put arguments into arguments registers.
370  // Parameters are
371  // a0: Address byte_offset1 - Address captured substring's start.
372  // a1: Address byte_offset2 - Address of current character position.
373  // a2: size_t byte_length - length of capture in bytes(!).
374  // a3: Isolate* isolate.
375 
376  // Address of start of capture.
377  __ Addu(a0, a0, Operand(end_of_input_address()));
378  // Length of capture.
379  __ mov(a2, a1);
380  // Save length in callee-save register for use on return.
381  __ mov(s3, a1);
382  // Address of current input position.
383  __ Addu(a1, current_input_offset(), Operand(end_of_input_address()));
384  // Isolate.
385  __ li(a3, Operand(ExternalReference::isolate_address()));
386 
387  {
388  AllowExternalCallThatCantCauseGC scope(masm_);
389  ExternalReference function =
390  ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate());
391  __ CallCFunction(function, argument_count);
392  }
393 
394  // Restore regexp engine registers.
395  __ MultiPop(regexp_registers_to_retain);
396  __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
397  __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
398 
399  // Check if function returned non-zero for success or zero for failure.
400  BranchOrBacktrack(on_no_match, eq, v0, Operand(zero_reg));
401  // On success, increment position by length of capture.
402  __ Addu(current_input_offset(), current_input_offset(), Operand(s3));
403  }
404 
405  __ bind(&fallthrough);
406 }
407 
408 
409 void RegExpMacroAssemblerMIPS::CheckNotBackReference(
410  int start_reg,
411  Label* on_no_match) {
412  Label fallthrough;
413  Label success;
414 
415  // Find length of back-referenced capture.
416  __ lw(a0, register_location(start_reg));
417  __ lw(a1, register_location(start_reg + 1));
418  __ Subu(a1, a1, a0); // Length to check.
419  // Succeed on empty capture (including no capture).
420  __ Branch(&fallthrough, eq, a1, Operand(zero_reg));
421 
422  __ Addu(t5, a1, current_input_offset());
423  // Check that there are enough characters left in the input.
424  BranchOrBacktrack(on_no_match, gt, t5, Operand(zero_reg));
425 
426  // Compute pointers to match string and capture string.
427  __ Addu(a0, a0, Operand(end_of_input_address()));
428  __ Addu(a2, end_of_input_address(), Operand(current_input_offset()));
429  __ Addu(a1, a1, Operand(a0));
430 
431  Label loop;
432  __ bind(&loop);
433  if (mode_ == ASCII) {
434  __ lbu(a3, MemOperand(a0, 0));
435  __ addiu(a0, a0, char_size());
436  __ lbu(t0, MemOperand(a2, 0));
437  __ addiu(a2, a2, char_size());
438  } else {
439  ASSERT(mode_ == UC16);
440  __ lhu(a3, MemOperand(a0, 0));
441  __ addiu(a0, a0, char_size());
442  __ lhu(t0, MemOperand(a2, 0));
443  __ addiu(a2, a2, char_size());
444  }
445  BranchOrBacktrack(on_no_match, ne, a3, Operand(t0));
446  __ Branch(&loop, lt, a0, Operand(a1));
447 
448  // Move current character position to position after match.
449  __ Subu(current_input_offset(), a2, end_of_input_address());
450  __ bind(&fallthrough);
451 }
452 
453 
454 void RegExpMacroAssemblerMIPS::CheckNotCharacter(uint32_t c,
455  Label* on_not_equal) {
456  BranchOrBacktrack(on_not_equal, ne, current_character(), Operand(c));
457 }
458 
459 
460 void RegExpMacroAssemblerMIPS::CheckCharacterAfterAnd(uint32_t c,
461  uint32_t mask,
462  Label* on_equal) {
463  __ And(a0, current_character(), Operand(mask));
464  Operand rhs = (c == 0) ? Operand(zero_reg) : Operand(c);
465  BranchOrBacktrack(on_equal, eq, a0, rhs);
466 }
467 
468 
469 void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterAnd(uint32_t c,
470  uint32_t mask,
471  Label* on_not_equal) {
472  __ And(a0, current_character(), Operand(mask));
473  Operand rhs = (c == 0) ? Operand(zero_reg) : Operand(c);
474  BranchOrBacktrack(on_not_equal, ne, a0, rhs);
475 }
476 
477 
478 void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterMinusAnd(
479  uc16 c,
480  uc16 minus,
481  uc16 mask,
482  Label* on_not_equal) {
483  ASSERT(minus < String::kMaxUtf16CodeUnit);
484  __ Subu(a0, current_character(), Operand(minus));
485  __ And(a0, a0, Operand(mask));
486  BranchOrBacktrack(on_not_equal, ne, a0, Operand(c));
487 }
488 
489 
490 void RegExpMacroAssemblerMIPS::CheckCharacterInRange(
491  uc16 from,
492  uc16 to,
493  Label* on_in_range) {
494  __ Subu(a0, current_character(), Operand(from));
495  // Unsigned lower-or-same condition.
496  BranchOrBacktrack(on_in_range, ls, a0, Operand(to - from));
497 }
498 
499 
500 void RegExpMacroAssemblerMIPS::CheckCharacterNotInRange(
501  uc16 from,
502  uc16 to,
503  Label* on_not_in_range) {
504  __ Subu(a0, current_character(), Operand(from));
505  // Unsigned higher condition.
506  BranchOrBacktrack(on_not_in_range, hi, a0, Operand(to - from));
507 }
508 
509 
510 void RegExpMacroAssemblerMIPS::CheckBitInTable(
511  Handle<ByteArray> table,
512  Label* on_bit_set) {
513  __ li(a0, Operand(table));
514  if (mode_ != ASCII || kTableMask != String::kMaxAsciiCharCode) {
515  __ And(a1, current_character(), Operand(kTableSize - 1));
516  __ Addu(a0, a0, a1);
517  } else {
518  __ Addu(a0, a0, current_character());
519  }
520 
521  __ lbu(a0, FieldMemOperand(a0, ByteArray::kHeaderSize));
522  BranchOrBacktrack(on_bit_set, ne, a0, Operand(zero_reg));
523 }
524 
525 
526 bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(uc16 type,
527  Label* on_no_match) {
528  // Range checks (c in min..max) are generally implemented by an unsigned
529  // (c - min) <= (max - min) check.
530  switch (type) {
531  case 's':
532  // Match space-characters.
533  if (mode_ == ASCII) {
534  // ASCII space characters are '\t'..'\r' and ' '.
535  Label success;
536  __ Branch(&success, eq, current_character(), Operand(' '));
537  // Check range 0x09..0x0d.
538  __ Subu(a0, current_character(), Operand('\t'));
539  BranchOrBacktrack(on_no_match, hi, a0, Operand('\r' - '\t'));
540  __ bind(&success);
541  return true;
542  }
543  return false;
544  case 'S':
545  // Match non-space characters.
546  if (mode_ == ASCII) {
547  // ASCII space characters are '\t'..'\r' and ' '.
548  BranchOrBacktrack(on_no_match, eq, current_character(), Operand(' '));
549  __ Subu(a0, current_character(), Operand('\t'));
550  BranchOrBacktrack(on_no_match, ls, a0, Operand('\r' - '\t'));
551  return true;
552  }
553  return false;
554  case 'd':
555  // Match ASCII digits ('0'..'9').
556  __ Subu(a0, current_character(), Operand('0'));
557  BranchOrBacktrack(on_no_match, hi, a0, Operand('9' - '0'));
558  return true;
559  case 'D':
560  // Match non ASCII-digits.
561  __ Subu(a0, current_character(), Operand('0'));
562  BranchOrBacktrack(on_no_match, ls, a0, Operand('9' - '0'));
563  return true;
564  case '.': {
565  // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029).
566  __ Xor(a0, current_character(), Operand(0x01));
567  // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c.
568  __ Subu(a0, a0, Operand(0x0b));
569  BranchOrBacktrack(on_no_match, ls, a0, Operand(0x0c - 0x0b));
570  if (mode_ == UC16) {
571  // Compare original value to 0x2028 and 0x2029, using the already
572  // computed (current_char ^ 0x01 - 0x0b). I.e., check for
573  // 0x201d (0x2028 - 0x0b) or 0x201e.
574  __ Subu(a0, a0, Operand(0x2028 - 0x0b));
575  BranchOrBacktrack(on_no_match, ls, a0, Operand(1));
576  }
577  return true;
578  }
579  case 'n': {
580  // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029).
581  __ Xor(a0, current_character(), Operand(0x01));
582  // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c.
583  __ Subu(a0, a0, Operand(0x0b));
584  if (mode_ == ASCII) {
585  BranchOrBacktrack(on_no_match, hi, a0, Operand(0x0c - 0x0b));
586  } else {
587  Label done;
588  BranchOrBacktrack(&done, ls, a0, Operand(0x0c - 0x0b));
589  // Compare original value to 0x2028 and 0x2029, using the already
590  // computed (current_char ^ 0x01 - 0x0b). I.e., check for
591  // 0x201d (0x2028 - 0x0b) or 0x201e.
592  __ Subu(a0, a0, Operand(0x2028 - 0x0b));
593  BranchOrBacktrack(on_no_match, hi, a0, Operand(1));
594  __ bind(&done);
595  }
596  return true;
597  }
598  case 'w': {
599  if (mode_ != ASCII) {
600  // Table is 128 entries, so all ASCII characters can be tested.
601  BranchOrBacktrack(on_no_match, hi, current_character(), Operand('z'));
602  }
603  ExternalReference map = ExternalReference::re_word_character_map();
604  __ li(a0, Operand(map));
605  __ Addu(a0, a0, current_character());
606  __ lbu(a0, MemOperand(a0, 0));
607  BranchOrBacktrack(on_no_match, eq, a0, Operand(zero_reg));
608  return true;
609  }
610  case 'W': {
611  Label done;
612  if (mode_ != ASCII) {
613  // Table is 128 entries, so all ASCII characters can be tested.
614  __ Branch(&done, hi, current_character(), Operand('z'));
615  }
616  ExternalReference map = ExternalReference::re_word_character_map();
617  __ li(a0, Operand(map));
618  __ Addu(a0, a0, current_character());
619  __ lbu(a0, MemOperand(a0, 0));
620  BranchOrBacktrack(on_no_match, ne, a0, Operand(zero_reg));
621  if (mode_ != ASCII) {
622  __ bind(&done);
623  }
624  return true;
625  }
626  case '*':
627  // Match any character.
628  return true;
629  // No custom implementation (yet): s(UC16), S(UC16).
630  default:
631  return false;
632  }
633 }
634 
635 
637  __ li(v0, Operand(FAILURE));
638  __ jmp(&exit_label_);
639 }
640 
641 
642 Handle<HeapObject> RegExpMacroAssemblerMIPS::GetCode(Handle<String> source) {
643  Label return_v0;
644  if (masm_->has_exception()) {
645  // If the code gets corrupted due to long regular expressions and lack of
646  // space on trampolines, an internal exception flag is set. If this case
647  // is detected, we will jump into exit sequence right away.
648  __ bind_to(&entry_label_, internal_failure_label_.pos());
649  } else {
650  // Finalize code - write the entry point code now we know how many
651  // registers we need.
652 
653  // Entry code:
654  __ bind(&entry_label_);
655 
656  // Tell the system that we have a stack frame. Because the type is MANUAL,
657  // no is generated.
658  FrameScope scope(masm_, StackFrame::MANUAL);
659 
660  // Actually emit code to start a new stack frame.
661  // Push arguments
662  // Save callee-save registers.
663  // Start new stack frame.
664  // Store link register in existing stack-cell.
665  // Order here should correspond to order of offset constants in header file.
666  RegList registers_to_retain = s0.bit() | s1.bit() | s2.bit() |
667  s3.bit() | s4.bit() | s5.bit() | s6.bit() | s7.bit() | fp.bit();
668  RegList argument_registers = a0.bit() | a1.bit() | a2.bit() | a3.bit();
669  __ MultiPush(argument_registers | registers_to_retain | ra.bit());
670  // Set frame pointer in space for it if this is not a direct call
671  // from generated code.
672  __ Addu(frame_pointer(), sp, Operand(4 * kPointerSize));
673  __ mov(a0, zero_reg);
674  __ push(a0); // Make room for success counter and initialize it to 0.
675  __ push(a0); // Make room for "position - 1" constant (value irrelevant).
676 
677  // Check if we have space on the stack for registers.
678  Label stack_limit_hit;
679  Label stack_ok;
680 
681  ExternalReference stack_limit =
682  ExternalReference::address_of_stack_limit(masm_->isolate());
683  __ li(a0, Operand(stack_limit));
684  __ lw(a0, MemOperand(a0));
685  __ Subu(a0, sp, a0);
686  // Handle it if the stack pointer is already below the stack limit.
687  __ Branch(&stack_limit_hit, le, a0, Operand(zero_reg));
688  // Check if there is room for the variable number of registers above
689  // the stack limit.
690  __ Branch(&stack_ok, hs, a0, Operand(num_registers_ * kPointerSize));
691  // Exit with OutOfMemory exception. There is not enough space on the stack
692  // for our working registers.
693  __ li(v0, Operand(EXCEPTION));
694  __ jmp(&return_v0);
695 
696  __ bind(&stack_limit_hit);
697  CallCheckStackGuardState(a0);
698  // If returned value is non-zero, we exit with the returned value as result.
699  __ Branch(&return_v0, ne, v0, Operand(zero_reg));
700 
701  __ bind(&stack_ok);
702  // Allocate space on stack for registers.
703  __ Subu(sp, sp, Operand(num_registers_ * kPointerSize));
704  // Load string end.
705  __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
706  // Load input start.
707  __ lw(a0, MemOperand(frame_pointer(), kInputStart));
708  // Find negative length (offset of start relative to end).
709  __ Subu(current_input_offset(), a0, end_of_input_address());
710  // Set a0 to address of char before start of the input string
711  // (effectively string position -1).
712  __ lw(a1, MemOperand(frame_pointer(), kStartIndex));
713  __ Subu(a0, current_input_offset(), Operand(char_size()));
714  __ sll(t5, a1, (mode_ == UC16) ? 1 : 0);
715  __ Subu(a0, a0, t5);
716  // Store this value in a local variable, for use when clearing
717  // position registers.
718  __ sw(a0, MemOperand(frame_pointer(), kInputStartMinusOne));
719 
720  // Initialize code pointer register
721  __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
722 
723  Label load_char_start_regexp, start_regexp;
724  // Load newline if index is at start, previous character otherwise.
725  __ Branch(&load_char_start_regexp, ne, a1, Operand(zero_reg));
726  __ li(current_character(), Operand('\n'));
727  __ jmp(&start_regexp);
728 
729  // Global regexp restarts matching here.
730  __ bind(&load_char_start_regexp);
731  // Load previous char as initial value of current character register.
732  LoadCurrentCharacterUnchecked(-1, 1);
733  __ bind(&start_regexp);
734 
735  // Initialize on-stack registers.
736  if (num_saved_registers_ > 0) { // Always is, if generated from a regexp.
737  // Fill saved registers with initial value = start offset - 1.
738  if (num_saved_registers_ > 8) {
739  // Address of register 0.
740  __ Addu(a1, frame_pointer(), Operand(kRegisterZero));
741  __ li(a2, Operand(num_saved_registers_));
742  Label init_loop;
743  __ bind(&init_loop);
744  __ sw(a0, MemOperand(a1));
745  __ Addu(a1, a1, Operand(-kPointerSize));
746  __ Subu(a2, a2, Operand(1));
747  __ Branch(&init_loop, ne, a2, Operand(zero_reg));
748  } else {
749  for (int i = 0; i < num_saved_registers_; i++) {
750  __ sw(a0, register_location(i));
751  }
752  }
753  }
754 
755  // Initialize backtrack stack pointer.
756  __ lw(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd));
757 
758  __ jmp(&start_label_);
759 
760 
761  // Exit code:
762  if (success_label_.is_linked()) {
763  // Save captures when successful.
764  __ bind(&success_label_);
765  if (num_saved_registers_ > 0) {
766  // Copy captures to output.
767  __ lw(a1, MemOperand(frame_pointer(), kInputStart));
768  __ lw(a0, MemOperand(frame_pointer(), kRegisterOutput));
769  __ lw(a2, MemOperand(frame_pointer(), kStartIndex));
770  __ Subu(a1, end_of_input_address(), a1);
771  // a1 is length of input in bytes.
772  if (mode_ == UC16) {
773  __ srl(a1, a1, 1);
774  }
775  // a1 is length of input in characters.
776  __ Addu(a1, a1, Operand(a2));
777  // a1 is length of string in characters.
778 
779  ASSERT_EQ(0, num_saved_registers_ % 2);
780  // Always an even number of capture registers. This allows us to
781  // unroll the loop once to add an operation between a load of a register
782  // and the following use of that register.
783  for (int i = 0; i < num_saved_registers_; i += 2) {
784  __ lw(a2, register_location(i));
785  __ lw(a3, register_location(i + 1));
786  if (i == 0 && global_with_zero_length_check()) {
787  // Keep capture start in a4 for the zero-length check later.
788  __ mov(t7, a2);
789  }
790  if (mode_ == UC16) {
791  __ sra(a2, a2, 1);
792  __ Addu(a2, a2, a1);
793  __ sra(a3, a3, 1);
794  __ Addu(a3, a3, a1);
795  } else {
796  __ Addu(a2, a1, Operand(a2));
797  __ Addu(a3, a1, Operand(a3));
798  }
799  __ sw(a2, MemOperand(a0));
800  __ Addu(a0, a0, kPointerSize);
801  __ sw(a3, MemOperand(a0));
802  __ Addu(a0, a0, kPointerSize);
803  }
804  }
805 
806  if (global()) {
807  // Restart matching if the regular expression is flagged as global.
808  __ lw(a0, MemOperand(frame_pointer(), kSuccessfulCaptures));
809  __ lw(a1, MemOperand(frame_pointer(), kNumOutputRegisters));
810  __ lw(a2, MemOperand(frame_pointer(), kRegisterOutput));
811  // Increment success counter.
812  __ Addu(a0, a0, 1);
813  __ sw(a0, MemOperand(frame_pointer(), kSuccessfulCaptures));
814  // Capture results have been stored, so the number of remaining global
815  // output registers is reduced by the number of stored captures.
816  __ Subu(a1, a1, num_saved_registers_);
817  // Check whether we have enough room for another set of capture results.
818  __ mov(v0, a0);
819  __ Branch(&return_v0, lt, a1, Operand(num_saved_registers_));
820 
821  __ sw(a1, MemOperand(frame_pointer(), kNumOutputRegisters));
822  // Advance the location for output.
823  __ Addu(a2, a2, num_saved_registers_ * kPointerSize);
824  __ sw(a2, MemOperand(frame_pointer(), kRegisterOutput));
825 
826  // Prepare a0 to initialize registers with its value in the next run.
827  __ lw(a0, MemOperand(frame_pointer(), kInputStartMinusOne));
828 
829  if (global_with_zero_length_check()) {
830  // Special case for zero-length matches.
831  // t7: capture start index
832  // Not a zero-length match, restart.
833  __ Branch(
834  &load_char_start_regexp, ne, current_input_offset(), Operand(t7));
835  // Offset from the end is zero if we already reached the end.
836  __ Branch(&exit_label_, eq, current_input_offset(),
837  Operand(zero_reg));
838  // Advance current position after a zero-length match.
839  __ Addu(current_input_offset(),
840  current_input_offset(),
841  Operand((mode_ == UC16) ? 2 : 1));
842  }
843 
844  __ Branch(&load_char_start_regexp);
845  } else {
846  __ li(v0, Operand(SUCCESS));
847  }
848  }
849  // Exit and return v0.
850  __ bind(&exit_label_);
851  if (global()) {
852  __ lw(v0, MemOperand(frame_pointer(), kSuccessfulCaptures));
853  }
854 
855  __ bind(&return_v0);
856  // Skip sp past regexp registers and local variables..
857  __ mov(sp, frame_pointer());
858  // Restore registers s0..s7 and return (restoring ra to pc).
859  __ MultiPop(registers_to_retain | ra.bit());
860  __ Ret();
861 
862  // Backtrack code (branch target for conditional backtracks).
863  if (backtrack_label_.is_linked()) {
864  __ bind(&backtrack_label_);
865  Backtrack();
866  }
867 
868  Label exit_with_exception;
869 
870  // Preempt-code.
871  if (check_preempt_label_.is_linked()) {
872  SafeCallTarget(&check_preempt_label_);
873  // Put regexp engine registers on stack.
874  RegList regexp_registers_to_retain = current_input_offset().bit() |
875  current_character().bit() | backtrack_stackpointer().bit();
876  __ MultiPush(regexp_registers_to_retain);
877  CallCheckStackGuardState(a0);
878  __ MultiPop(regexp_registers_to_retain);
879  // If returning non-zero, we should end execution with the given
880  // result as return value.
881  __ Branch(&return_v0, ne, v0, Operand(zero_reg));
882 
883  // String might have moved: Reload end of string from frame.
884  __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
885  __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
886  SafeReturn();
887  }
888 
889  // Backtrack stack overflow code.
890  if (stack_overflow_label_.is_linked()) {
891  SafeCallTarget(&stack_overflow_label_);
892  // Reached if the backtrack-stack limit has been hit.
893  // Put regexp engine registers on stack first.
894  RegList regexp_registers = current_input_offset().bit() |
895  current_character().bit();
896  __ MultiPush(regexp_registers);
897  Label grow_failed;
898  // Call GrowStack(backtrack_stackpointer(), &stack_base)
899  static const int num_arguments = 3;
900  __ PrepareCallCFunction(num_arguments, a0);
901  __ mov(a0, backtrack_stackpointer());
902  __ Addu(a1, frame_pointer(), Operand(kStackHighEnd));
903  __ li(a2, Operand(ExternalReference::isolate_address()));
904  ExternalReference grow_stack =
905  ExternalReference::re_grow_stack(masm_->isolate());
906  __ CallCFunction(grow_stack, num_arguments);
907  // Restore regexp registers.
908  __ MultiPop(regexp_registers);
909  // If return NULL, we have failed to grow the stack, and
910  // must exit with a stack-overflow exception.
911  __ Branch(&exit_with_exception, eq, v0, Operand(zero_reg));
912  // Otherwise use return value as new stack pointer.
913  __ mov(backtrack_stackpointer(), v0);
914  // Restore saved registers and continue.
915  __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
916  __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd));
917  SafeReturn();
918  }
919 
920  if (exit_with_exception.is_linked()) {
921  // If any of the code above needed to exit with an exception.
922  __ bind(&exit_with_exception);
923  // Exit with Result EXCEPTION(-1) to signal thrown exception.
924  __ li(v0, Operand(EXCEPTION));
925  __ jmp(&return_v0);
926  }
927  }
928 
929  CodeDesc code_desc;
930  masm_->GetCode(&code_desc);
931  Handle<Code> code = FACTORY->NewCode(code_desc,
932  Code::ComputeFlags(Code::REGEXP),
933  masm_->CodeObject());
934  LOG(Isolate::Current(), RegExpCodeCreateEvent(*code, *source));
935  return Handle<HeapObject>::cast(code);
936 }
937 
938 
939 void RegExpMacroAssemblerMIPS::GoTo(Label* to) {
940  if (to == NULL) {
941  Backtrack();
942  return;
943  }
944  __ jmp(to);
945  return;
946 }
947 
948 
949 void RegExpMacroAssemblerMIPS::IfRegisterGE(int reg,
950  int comparand,
951  Label* if_ge) {
952  __ lw(a0, register_location(reg));
953  BranchOrBacktrack(if_ge, ge, a0, Operand(comparand));
954 }
955 
956 
957 void RegExpMacroAssemblerMIPS::IfRegisterLT(int reg,
958  int comparand,
959  Label* if_lt) {
960  __ lw(a0, register_location(reg));
961  BranchOrBacktrack(if_lt, lt, a0, Operand(comparand));
962 }
963 
964 
965 void RegExpMacroAssemblerMIPS::IfRegisterEqPos(int reg,
966  Label* if_eq) {
967  __ lw(a0, register_location(reg));
968  BranchOrBacktrack(if_eq, eq, a0, Operand(current_input_offset()));
969 }
970 
971 
972 RegExpMacroAssembler::IrregexpImplementation
973  RegExpMacroAssemblerMIPS::Implementation() {
974  return kMIPSImplementation;
975 }
976 
977 
978 void RegExpMacroAssemblerMIPS::LoadCurrentCharacter(int cp_offset,
979  Label* on_end_of_input,
980  bool check_bounds,
981  int characters) {
982  ASSERT(cp_offset >= -1); // ^ and \b can look behind one character.
983  ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works).
984  if (check_bounds) {
985  CheckPosition(cp_offset + characters - 1, on_end_of_input);
986  }
987  LoadCurrentCharacterUnchecked(cp_offset, characters);
988 }
989 
990 
991 void RegExpMacroAssemblerMIPS::PopCurrentPosition() {
992  Pop(current_input_offset());
993 }
994 
995 
996 void RegExpMacroAssemblerMIPS::PopRegister(int register_index) {
997  Pop(a0);
998  __ sw(a0, register_location(register_index));
999 }
1000 
1001 
1002 void RegExpMacroAssemblerMIPS::PushBacktrack(Label* label) {
1003  if (label->is_bound()) {
1004  int target = label->pos();
1005  __ li(a0, Operand(target + Code::kHeaderSize - kHeapObjectTag));
1006  } else {
1007  Label after_constant;
1008  __ Branch(&after_constant);
1009  int offset = masm_->pc_offset();
1010  int cp_offset = offset + Code::kHeaderSize - kHeapObjectTag;
1011  __ emit(0);
1012  masm_->label_at_put(label, offset);
1013  __ bind(&after_constant);
1014  if (is_int16(cp_offset)) {
1015  __ lw(a0, MemOperand(code_pointer(), cp_offset));
1016  } else {
1017  __ Addu(a0, code_pointer(), cp_offset);
1018  __ lw(a0, MemOperand(a0, 0));
1019  }
1020  }
1021  Push(a0);
1022  CheckStackLimit();
1023 }
1024 
1025 
1026 void RegExpMacroAssemblerMIPS::PushCurrentPosition() {
1027  Push(current_input_offset());
1028 }
1029 
1030 
1031 void RegExpMacroAssemblerMIPS::PushRegister(int register_index,
1032  StackCheckFlag check_stack_limit) {
1033  __ lw(a0, register_location(register_index));
1034  Push(a0);
1035  if (check_stack_limit) CheckStackLimit();
1036 }
1037 
1038 
1039 void RegExpMacroAssemblerMIPS::ReadCurrentPositionFromRegister(int reg) {
1040  __ lw(current_input_offset(), register_location(reg));
1041 }
1042 
1043 
1044 void RegExpMacroAssemblerMIPS::ReadStackPointerFromRegister(int reg) {
1045  __ lw(backtrack_stackpointer(), register_location(reg));
1046  __ lw(a0, MemOperand(frame_pointer(), kStackHighEnd));
1047  __ Addu(backtrack_stackpointer(), backtrack_stackpointer(), Operand(a0));
1048 }
1049 
1050 
1051 void RegExpMacroAssemblerMIPS::SetCurrentPositionFromEnd(int by) {
1052  Label after_position;
1053  __ Branch(&after_position,
1054  ge,
1055  current_input_offset(),
1056  Operand(-by * char_size()));
1057  __ li(current_input_offset(), -by * char_size());
1058  // On RegExp code entry (where this operation is used), the character before
1059  // the current position is expected to be already loaded.
1060  // We have advanced the position, so it's safe to read backwards.
1061  LoadCurrentCharacterUnchecked(-1, 1);
1062  __ bind(&after_position);
1063 }
1064 
1065 
1066 void RegExpMacroAssemblerMIPS::SetRegister(int register_index, int to) {
1067  ASSERT(register_index >= num_saved_registers_); // Reserved for positions!
1068  __ li(a0, Operand(to));
1069  __ sw(a0, register_location(register_index));
1070 }
1071 
1072 
1073 bool RegExpMacroAssemblerMIPS::Succeed() {
1074  __ jmp(&success_label_);
1075  return global();
1076 }
1077 
1078 
1079 void RegExpMacroAssemblerMIPS::WriteCurrentPositionToRegister(int reg,
1080  int cp_offset) {
1081  if (cp_offset == 0) {
1082  __ sw(current_input_offset(), register_location(reg));
1083  } else {
1084  __ Addu(a0, current_input_offset(), Operand(cp_offset * char_size()));
1085  __ sw(a0, register_location(reg));
1086  }
1087 }
1088 
1089 
1090 void RegExpMacroAssemblerMIPS::ClearRegisters(int reg_from, int reg_to) {
1091  ASSERT(reg_from <= reg_to);
1092  __ lw(a0, MemOperand(frame_pointer(), kInputStartMinusOne));
1093  for (int reg = reg_from; reg <= reg_to; reg++) {
1094  __ sw(a0, register_location(reg));
1095  }
1096 }
1097 
1098 
1099 void RegExpMacroAssemblerMIPS::WriteStackPointerToRegister(int reg) {
1100  __ lw(a1, MemOperand(frame_pointer(), kStackHighEnd));
1101  __ Subu(a0, backtrack_stackpointer(), a1);
1102  __ sw(a0, register_location(reg));
1103 }
1104 
1105 
1106 bool RegExpMacroAssemblerMIPS::CanReadUnaligned() {
1107  return false;
1108 }
1109 
1110 
1111 // Private methods:
1112 
1113 void RegExpMacroAssemblerMIPS::CallCheckStackGuardState(Register scratch) {
1114  static const int num_arguments = 3;
1115  __ PrepareCallCFunction(num_arguments, scratch);
1116  __ mov(a2, frame_pointer());
1117  // Code* of self.
1118  __ li(a1, Operand(masm_->CodeObject()), CONSTANT_SIZE);
1119  // a0 becomes return address pointer.
1120  ExternalReference stack_guard_check =
1121  ExternalReference::re_check_stack_guard_state(masm_->isolate());
1122  CallCFunctionUsingStub(stack_guard_check, num_arguments);
1123 }
1124 
1125 
1126 // Helper function for reading a value out of a stack frame.
1127 template <typename T>
1128 static T& frame_entry(Address re_frame, int frame_offset) {
1129  return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset));
1130 }
1131 
1132 
1133 int RegExpMacroAssemblerMIPS::CheckStackGuardState(Address* return_address,
1134  Code* re_code,
1135  Address re_frame) {
1136  Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
1137  ASSERT(isolate == Isolate::Current());
1138  if (isolate->stack_guard()->IsStackOverflow()) {
1139  isolate->StackOverflow();
1140  return EXCEPTION;
1141  }
1142 
1143  // If not real stack overflow the stack guard was used to interrupt
1144  // execution for another purpose.
1145 
1146  // If this is a direct call from JavaScript retry the RegExp forcing the call
1147  // through the runtime system. Currently the direct call cannot handle a GC.
1148  if (frame_entry<int>(re_frame, kDirectCall) == 1) {
1149  return RETRY;
1150  }
1151 
1152  // Prepare for possible GC.
1153  HandleScope handles(isolate);
1154  Handle<Code> code_handle(re_code);
1155 
1156  Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
1157  // Current string.
1158  bool is_ascii = subject->IsAsciiRepresentationUnderneath();
1159 
1160  ASSERT(re_code->instruction_start() <= *return_address);
1161  ASSERT(*return_address <=
1162  re_code->instruction_start() + re_code->instruction_size());
1163 
1164  MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
1165 
1166  if (*code_handle != re_code) { // Return address no longer valid.
1167  int delta = code_handle->address() - re_code->address();
1168  // Overwrite the return address on the stack.
1169  *return_address += delta;
1170  }
1171 
1172  if (result->IsException()) {
1173  return EXCEPTION;
1174  }
1175 
1176  Handle<String> subject_tmp = subject;
1177  int slice_offset = 0;
1178 
1179  // Extract the underlying string and the slice offset.
1180  if (StringShape(*subject_tmp).IsCons()) {
1181  subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
1182  } else if (StringShape(*subject_tmp).IsSliced()) {
1183  SlicedString* slice = SlicedString::cast(*subject_tmp);
1184  subject_tmp = Handle<String>(slice->parent());
1185  slice_offset = slice->offset();
1186  }
1187 
1188  // String might have changed.
1189  if (subject_tmp->IsAsciiRepresentation() != is_ascii) {
1190  // If we changed between an ASCII and an UC16 string, the specialized
1191  // code cannot be used, and we need to restart regexp matching from
1192  // scratch (including, potentially, compiling a new version of the code).
1193  return RETRY;
1194  }
1195 
1196  // Otherwise, the content of the string might have moved. It must still
1197  // be a sequential or external string with the same content.
1198  // Update the start and end pointers in the stack frame to the current
1199  // location (whether it has actually moved or not).
1200  ASSERT(StringShape(*subject_tmp).IsSequential() ||
1201  StringShape(*subject_tmp).IsExternal());
1202 
1203  // The original start address of the characters to match.
1204  const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
1205 
1206  // Find the current start address of the same character at the current string
1207  // position.
1208  int start_index = frame_entry<int>(re_frame, kStartIndex);
1209  const byte* new_address = StringCharacterPosition(*subject_tmp,
1210  start_index + slice_offset);
1211 
1212  if (start_address != new_address) {
1213  // If there is a difference, update the object pointer and start and end
1214  // addresses in the RegExp stack frame to match the new value.
1215  const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
1216  int byte_length = static_cast<int>(end_address - start_address);
1217  frame_entry<const String*>(re_frame, kInputString) = *subject;
1218  frame_entry<const byte*>(re_frame, kInputStart) = new_address;
1219  frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
1220  } else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
1221  // Subject string might have been a ConsString that underwent
1222  // short-circuiting during GC. That will not change start_address but
1223  // will change pointer inside the subject handle.
1224  frame_entry<const String*>(re_frame, kInputString) = *subject;
1225  }
1226 
1227  return 0;
1228 }
1229 
1230 
1231 MemOperand RegExpMacroAssemblerMIPS::register_location(int register_index) {
1232  ASSERT(register_index < (1<<30));
1233  if (num_registers_ <= register_index) {
1234  num_registers_ = register_index + 1;
1235  }
1236  return MemOperand(frame_pointer(),
1237  kRegisterZero - register_index * kPointerSize);
1238 }
1239 
1240 
1241 void RegExpMacroAssemblerMIPS::CheckPosition(int cp_offset,
1242  Label* on_outside_input) {
1243  BranchOrBacktrack(on_outside_input,
1244  ge,
1245  current_input_offset(),
1246  Operand(-cp_offset * char_size()));
1247 }
1248 
1249 
1250 void RegExpMacroAssemblerMIPS::BranchOrBacktrack(Label* to,
1251  Condition condition,
1252  Register rs,
1253  const Operand& rt) {
1254  if (condition == al) { // Unconditional.
1255  if (to == NULL) {
1256  Backtrack();
1257  return;
1258  }
1259  __ jmp(to);
1260  return;
1261  }
1262  if (to == NULL) {
1263  __ Branch(&backtrack_label_, condition, rs, rt);
1264  return;
1265  }
1266  __ Branch(to, condition, rs, rt);
1267 }
1268 
1269 
1270 void RegExpMacroAssemblerMIPS::SafeCall(Label* to,
1271  Condition cond,
1272  Register rs,
1273  const Operand& rt) {
1274  __ BranchAndLink(to, cond, rs, rt);
1275 }
1276 
1277 
1278 void RegExpMacroAssemblerMIPS::SafeReturn() {
1279  __ pop(ra);
1280  __ Addu(t5, ra, Operand(masm_->CodeObject()));
1281  __ Jump(t5);
1282 }
1283 
1284 
1285 void RegExpMacroAssemblerMIPS::SafeCallTarget(Label* name) {
1286  __ bind(name);
1287  __ Subu(ra, ra, Operand(masm_->CodeObject()));
1288  __ push(ra);
1289 }
1290 
1291 
1292 void RegExpMacroAssemblerMIPS::Push(Register source) {
1293  ASSERT(!source.is(backtrack_stackpointer()));
1294  __ Addu(backtrack_stackpointer(),
1295  backtrack_stackpointer(),
1296  Operand(-kPointerSize));
1297  __ sw(source, MemOperand(backtrack_stackpointer()));
1298 }
1299 
1300 
1301 void RegExpMacroAssemblerMIPS::Pop(Register target) {
1302  ASSERT(!target.is(backtrack_stackpointer()));
1303  __ lw(target, MemOperand(backtrack_stackpointer()));
1304  __ Addu(backtrack_stackpointer(), backtrack_stackpointer(), kPointerSize);
1305 }
1306 
1307 
1308 void RegExpMacroAssemblerMIPS::CheckPreemption() {
1309  // Check for preemption.
1310  ExternalReference stack_limit =
1311  ExternalReference::address_of_stack_limit(masm_->isolate());
1312  __ li(a0, Operand(stack_limit));
1313  __ lw(a0, MemOperand(a0));
1314  SafeCall(&check_preempt_label_, ls, sp, Operand(a0));
1315 }
1316 
1317 
1318 void RegExpMacroAssemblerMIPS::CheckStackLimit() {
1319  ExternalReference stack_limit =
1320  ExternalReference::address_of_regexp_stack_limit(masm_->isolate());
1321 
1322  __ li(a0, Operand(stack_limit));
1323  __ lw(a0, MemOperand(a0));
1324  SafeCall(&stack_overflow_label_, ls, backtrack_stackpointer(), Operand(a0));
1325 }
1326 
1327 
1328 void RegExpMacroAssemblerMIPS::CallCFunctionUsingStub(
1329  ExternalReference function,
1330  int num_arguments) {
1331  // Must pass all arguments in registers. The stub pushes on the stack.
1332  ASSERT(num_arguments <= 4);
1333  __ li(code_pointer(), Operand(function));
1334  RegExpCEntryStub stub;
1335  __ CallStub(&stub);
1336  if (OS::ActivationFrameAlignment() != 0) {
1337  __ lw(sp, MemOperand(sp, 16));
1338  }
1339  __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE);
1340 }
1341 
1342 
1343 void RegExpMacroAssemblerMIPS::LoadCurrentCharacterUnchecked(int cp_offset,
1344  int characters) {
1345  Register offset = current_input_offset();
1346  if (cp_offset != 0) {
1347  // t7 is not being used to store the capture start index at this point.
1348  __ Addu(t7, current_input_offset(), Operand(cp_offset * char_size()));
1349  offset = t7;
1350  }
1351  // We assume that we cannot do unaligned loads on MIPS, so this function
1352  // must only be used to load a single character at a time.
1353  ASSERT(characters == 1);
1354  __ Addu(t5, end_of_input_address(), Operand(offset));
1355  if (mode_ == ASCII) {
1356  __ lbu(current_character(), MemOperand(t5, 0));
1357  } else {
1358  ASSERT(mode_ == UC16);
1359  __ lhu(current_character(), MemOperand(t5, 0));
1360  }
1361 }
1362 
1363 
1364 void RegExpCEntryStub::Generate(MacroAssembler* masm_) {
1365  int stack_alignment = OS::ActivationFrameAlignment();
1366  if (stack_alignment < kPointerSize) stack_alignment = kPointerSize;
1367  // Stack is already aligned for call, so decrement by alignment
1368  // to make room for storing the return address.
1369  __ Subu(sp, sp, Operand(stack_alignment + kCArgsSlotsSize));
1370  const int return_address_offset = kCArgsSlotsSize;
1371  __ Addu(a0, sp, return_address_offset);
1372  __ sw(ra, MemOperand(a0, 0));
1373  __ mov(t9, t1);
1374  __ Call(t9);
1375  __ lw(ra, MemOperand(sp, return_address_offset));
1376  __ Addu(sp, sp, Operand(stack_alignment + kCArgsSlotsSize));
1377  __ Jump(ra);
1378 }
1379 
1380 
1381 #undef __
1382 
1383 #endif // V8_INTERPRETED_REGEXP
1384 
1385 }} // namespace v8::internal
1386 
1387 #endif // V8_TARGET_ARCH_MIPS
byte * Address
Definition: globals.h:157
const SwVfpRegister s2
const int kCArgsSlotsSize
unsigned char byte
Definition: disasm.h:33
RegExpMacroAssemblerMIPS(Mode mode, int registers_to_save, Zone *zone)
v8::Handle< v8::Value > Fail(const v8::Arguments &args)
const SwVfpRegister s7
#define LOG(isolate, Call)
Definition: log.h:81
uint32_t RegList
Definition: frames.h:38
#define ASSERT(condition)
Definition: checks.h:270
const SwVfpRegister s6
const Register sp
const SwVfpRegister s3
const int kPointerSize
Definition: globals.h:220
const int kHeapObjectTag
Definition: v8.h:4009
#define __
const SwVfpRegister s0
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
const SwVfpRegister s5
#define T(name, string, precedence)
Definition: token.cc:48
const SwVfpRegister s1
MemOperand FieldMemOperand(Register object, int offset)
bool is_int16(int x)
Definition: assembler.h:837
uint16_t uc16
Definition: globals.h:259
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
const SwVfpRegister s4
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit 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 SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available 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 MIPS FPU instructions if NULL
#define FACTORY
Definition: isolate.h:1434
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit 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 SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available 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 MIPS FPU instructions if NULL
Definition: flags.cc:301
const Register fp
const uc32 kMaxAsciiCharCode
Definition: globals.h:263