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