Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/mips/regexp-macro-assembler-mips.cc

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

Powered by Google App Engine
This is Rietveld 408576698