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