OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_MIPS64 | 5 #if V8_TARGET_ARCH_MIPS64 |
6 | 6 |
7 #include "src/regexp/mips64/regexp-macro-assembler-mips64.h" | 7 #include "src/regexp/mips64/regexp-macro-assembler-mips64.h" |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/log.h" | 10 #include "src/log.h" |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 * - fp[36] return address (lr). | 54 * - fp[36] return address (lr). |
55 * - fp[32] old frame pointer (r11). | 55 * - fp[32] old frame pointer (r11). |
56 * - fp[0..31] backup of registers s0..s7. | 56 * - fp[0..31] backup of registers s0..s7. |
57 * --- frame pointer ---- | 57 * --- frame pointer ---- |
58 * - fp[-4] end of input (address of end of string). | 58 * - fp[-4] end of input (address of end of string). |
59 * - fp[-8] start of input (address of first character in string). | 59 * - fp[-8] start of input (address of first character in string). |
60 * - fp[-12] start index (character index of start). | 60 * - fp[-12] start index (character index of start). |
61 * - fp[-16] void* input_string (location of a handle containing the string). | 61 * - fp[-16] void* input_string (location of a handle containing the string). |
62 * - fp[-20] success counter (only for global regexps to count matches). | 62 * - fp[-20] success counter (only for global regexps to count matches). |
63 * - fp[-24] Offset of location before start of input (effectively character | 63 * - fp[-24] Offset of location before start of input (effectively character |
64 * string start - 1). Used to initialize capture registers to a | 64 * position -1). Used to initialize capture registers to a |
65 * non-position. | 65 * non-position. |
66 * - fp[-28] At start (if 1, we are starting at the start of the | 66 * - fp[-28] At start (if 1, we are starting at the start of the |
67 * string, otherwise 0) | 67 * string, otherwise 0) |
68 * - fp[-32] register 0 (Only positions must be stored in the first | 68 * - fp[-32] register 0 (Only positions must be stored in the first |
69 * - register 1 num_saved_registers_ registers) | 69 * - register 1 num_saved_registers_ registers) |
70 * - ... | 70 * - ... |
71 * - register num_registers-1 | 71 * - register num_registers-1 |
72 * --- sp --- | 72 * --- sp --- |
73 * | 73 * |
74 * | 74 * |
75 * The N64 stack will have the following structure: | 75 * The N64 stack will have the following structure: |
76 * | 76 * |
77 * - fp[88] Isolate* isolate (address of the current isolate)
kIsolate | 77 * - fp[88] Isolate* isolate (address of the current isolate)
kIsolate |
78 * - fp[80] secondary link/return address used by exit frame on native call.
kSecondaryReturnAddress | 78 * - fp[80] secondary link/return address used by exit frame on native call.
kSecondaryReturnAddress |
79
kStackFrameHeader | 79
kStackFrameHeader |
80 * --- sp when called --- | 80 * --- sp when called --- |
81 * - fp[72] ra Return from RegExp code (ra).
kReturnAddress | 81 * - fp[72] ra Return from RegExp code (ra).
kReturnAddress |
82 * - fp[64] s9, old-fp Old fp, callee saved(s9). | 82 * - fp[64] s9, old-fp Old fp, callee saved(s9). |
83 * - fp[0..63] s0..s7 Callee-saved registers s0..s7. | 83 * - fp[0..63] s0..s7 Callee-saved registers s0..s7. |
84 * --- frame pointer ---- | 84 * --- frame pointer ---- |
85 * - fp[-8] direct_call (1 = direct call from JS, 0 = from runtime)
kDirectCall | 85 * - fp[-8] direct_call (1 = direct call from JS, 0 = from runtime)
kDirectCall |
86 * - fp[-16] stack_base (Top of backtracking stack).
kStackHighEnd | 86 * - fp[-16] stack_base (Top of backtracking stack).
kStackHighEnd |
87 * - fp[-24] capture array size (may fit multiple sets of matches)
kNumOutputRegisters | 87 * - fp[-24] capture array size (may fit multiple sets of matches)
kNumOutputRegisters |
88 * - fp[-32] int* capture_array (int[num_saved_registers_], for output).
kRegisterOutput | 88 * - fp[-32] int* capture_array (int[num_saved_registers_], for output).
kRegisterOutput |
89 * - fp[-40] end of input (address of end of string).
kInputEnd | 89 * - fp[-40] end of input (address of end of string).
kInputEnd |
90 * - fp[-48] start of input (address of first character in string).
kInputStart | 90 * - fp[-48] start of input (address of first character in string).
kInputStart |
91 * - fp[-56] start index (character index of start).
kStartIndex | 91 * - fp[-56] start index (character index of start).
kStartIndex |
92 * - fp[-64] void* input_string (location of a handle containing the string).
kInputString | 92 * - fp[-64] void* input_string (location of a handle containing the string).
kInputString |
93 * - fp[-72] success counter (only for global regexps to count matches).
kSuccessfulCaptures | 93 * - fp[-72] success counter (only for global regexps to count matches).
kSuccessfulCaptures |
94 * - fp[-80] Offset of location before start of input (effectively character
kStringStartMinusOne | 94 * - fp[-80] Offset of location before start of input (effectively character
kInputStartMinusOne |
95 * position -1). Used to initialize capture registers to a | 95 * position -1). Used to initialize capture registers to a |
96 * non-position. | 96 * non-position. |
97 * --------- The following output registers are 32-bit values. --------- | 97 * --------- The following output registers are 32-bit values. --------- |
98 * - fp[-88] register 0 (Only positions must be stored in the first
kRegisterZero | 98 * - fp[-88] register 0 (Only positions must be stored in the first
kRegisterZero |
99 * - register 1 num_saved_registers_ registers) | 99 * - register 1 num_saved_registers_ registers) |
100 * - ... | 100 * - ... |
101 * - register num_registers-1 | 101 * - register num_registers-1 |
102 * --- sp --- | 102 * --- sp --- |
103 * | 103 * |
104 * The first num_saved_registers_ registers are initialized to point to | 104 * The first num_saved_registers_ registers are initialized to point to |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 BranchOrBacktrack(on_equal, eq, current_character(), Operand(c)); | 210 BranchOrBacktrack(on_equal, eq, current_character(), Operand(c)); |
211 } | 211 } |
212 | 212 |
213 | 213 |
214 void RegExpMacroAssemblerMIPS::CheckCharacterGT(uc16 limit, Label* on_greater) { | 214 void RegExpMacroAssemblerMIPS::CheckCharacterGT(uc16 limit, Label* on_greater) { |
215 BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit)); | 215 BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit)); |
216 } | 216 } |
217 | 217 |
218 | 218 |
219 void RegExpMacroAssemblerMIPS::CheckAtStart(Label* on_at_start) { | 219 void RegExpMacroAssemblerMIPS::CheckAtStart(Label* on_at_start) { |
220 __ ld(a1, MemOperand(frame_pointer(), kStringStartMinusOne)); | 220 Label not_at_start; |
221 __ Daddu(a0, current_input_offset(), Operand(-char_size())); | 221 // Did we start the match at the start of the string at all? |
| 222 __ ld(a0, MemOperand(frame_pointer(), kStartIndex)); |
| 223 BranchOrBacktrack(¬_at_start, ne, a0, Operand(zero_reg)); |
| 224 |
| 225 // If we did, are we still at the start of the input? |
| 226 __ ld(a1, MemOperand(frame_pointer(), kInputStart)); |
| 227 __ Daddu(a0, end_of_input_address(), Operand(current_input_offset())); |
222 BranchOrBacktrack(on_at_start, eq, a0, Operand(a1)); | 228 BranchOrBacktrack(on_at_start, eq, a0, Operand(a1)); |
| 229 __ bind(¬_at_start); |
223 } | 230 } |
224 | 231 |
225 | 232 |
226 void RegExpMacroAssemblerMIPS::CheckNotAtStart(int cp_offset, | 233 void RegExpMacroAssemblerMIPS::CheckNotAtStart(Label* on_not_at_start) { |
227 Label* on_not_at_start) { | 234 // Did we start the match at the start of the string at all? |
228 __ ld(a1, MemOperand(frame_pointer(), kStringStartMinusOne)); | 235 __ ld(a0, MemOperand(frame_pointer(), kStartIndex)); |
229 __ Daddu(a0, current_input_offset(), | 236 BranchOrBacktrack(on_not_at_start, ne, a0, Operand(zero_reg)); |
230 Operand(-char_size() + cp_offset * char_size())); | 237 // If we did, are we still at the start of the input? |
| 238 __ ld(a1, MemOperand(frame_pointer(), kInputStart)); |
| 239 __ Daddu(a0, end_of_input_address(), Operand(current_input_offset())); |
231 BranchOrBacktrack(on_not_at_start, ne, a0, Operand(a1)); | 240 BranchOrBacktrack(on_not_at_start, ne, a0, Operand(a1)); |
232 } | 241 } |
233 | 242 |
234 | 243 |
235 void RegExpMacroAssemblerMIPS::CheckCharacterLT(uc16 limit, Label* on_less) { | 244 void RegExpMacroAssemblerMIPS::CheckCharacterLT(uc16 limit, Label* on_less) { |
236 BranchOrBacktrack(on_less, lt, current_character(), Operand(limit)); | 245 BranchOrBacktrack(on_less, lt, current_character(), Operand(limit)); |
237 } | 246 } |
238 | 247 |
239 | 248 |
240 void RegExpMacroAssemblerMIPS::CheckGreedyLoop(Label* on_equal) { | 249 void RegExpMacroAssemblerMIPS::CheckGreedyLoop(Label* on_equal) { |
241 Label backtrack_non_equal; | 250 Label backtrack_non_equal; |
242 __ lw(a0, MemOperand(backtrack_stackpointer(), 0)); | 251 __ lw(a0, MemOperand(backtrack_stackpointer(), 0)); |
243 __ Branch(&backtrack_non_equal, ne, current_input_offset(), Operand(a0)); | 252 __ Branch(&backtrack_non_equal, ne, current_input_offset(), Operand(a0)); |
244 __ Daddu(backtrack_stackpointer(), | 253 __ Daddu(backtrack_stackpointer(), |
245 backtrack_stackpointer(), | 254 backtrack_stackpointer(), |
246 Operand(kIntSize)); | 255 Operand(kIntSize)); |
247 __ bind(&backtrack_non_equal); | 256 __ bind(&backtrack_non_equal); |
248 BranchOrBacktrack(on_equal, eq, current_input_offset(), Operand(a0)); | 257 BranchOrBacktrack(on_equal, eq, current_input_offset(), Operand(a0)); |
249 } | 258 } |
250 | 259 |
251 | 260 |
252 void RegExpMacroAssemblerMIPS::CheckNotBackReferenceIgnoreCase( | 261 void RegExpMacroAssemblerMIPS::CheckNotBackReferenceIgnoreCase( |
253 int start_reg, bool read_backward, Label* on_no_match) { | 262 int start_reg, |
| 263 Label* on_no_match) { |
254 Label fallthrough; | 264 Label fallthrough; |
255 __ ld(a0, register_location(start_reg)); // Index of start of capture. | 265 __ ld(a0, register_location(start_reg)); // Index of start of capture. |
256 __ ld(a1, register_location(start_reg + 1)); // Index of end of capture. | 266 __ ld(a1, register_location(start_reg + 1)); // Index of end of capture. |
257 __ Dsubu(a1, a1, a0); // Length of capture. | 267 __ Dsubu(a1, a1, a0); // Length of capture. |
258 | 268 |
259 // At this point, the capture registers are either both set or both cleared. | 269 // If length is zero, either the capture is empty or it is not participating. |
260 // If the capture length is zero, then the capture is either empty or cleared. | 270 // In either case succeed immediately. |
261 // Fall through in both cases. | |
262 __ Branch(&fallthrough, eq, a1, Operand(zero_reg)); | 271 __ Branch(&fallthrough, eq, a1, Operand(zero_reg)); |
263 | 272 |
264 if (read_backward) { | 273 __ Daddu(t1, a1, current_input_offset()); |
265 __ ld(t1, MemOperand(frame_pointer(), kStringStartMinusOne)); | 274 // Check that there are enough characters left in the input. |
266 __ Daddu(t1, t1, a1); | 275 BranchOrBacktrack(on_no_match, gt, t1, Operand(zero_reg)); |
267 BranchOrBacktrack(on_no_match, le, current_input_offset(), Operand(t1)); | |
268 } else { | |
269 __ Daddu(t1, a1, current_input_offset()); | |
270 // Check that there are enough characters left in the input. | |
271 BranchOrBacktrack(on_no_match, gt, t1, Operand(zero_reg)); | |
272 } | |
273 | 276 |
274 if (mode_ == LATIN1) { | 277 if (mode_ == LATIN1) { |
275 Label success; | 278 Label success; |
276 Label fail; | 279 Label fail; |
277 Label loop_check; | 280 Label loop_check; |
278 | 281 |
279 // a0 - offset of start of capture. | 282 // a0 - offset of start of capture. |
280 // a1 - length of capture. | 283 // a1 - length of capture. |
281 __ Daddu(a0, a0, Operand(end_of_input_address())); | 284 __ Daddu(a0, a0, Operand(end_of_input_address())); |
282 __ Daddu(a2, end_of_input_address(), Operand(current_input_offset())); | 285 __ Daddu(a2, end_of_input_address(), Operand(current_input_offset())); |
283 if (read_backward) { | |
284 __ Dsubu(a2, a2, Operand(a1)); | |
285 } | |
286 __ Daddu(a1, a0, Operand(a1)); | 286 __ Daddu(a1, a0, Operand(a1)); |
287 | 287 |
288 // a0 - Address of start of capture. | 288 // a0 - Address of start of capture. |
289 // a1 - Address of end of capture. | 289 // a1 - Address of end of capture. |
290 // a2 - Address of current input position. | 290 // a2 - Address of current input position. |
291 | 291 |
292 Label loop; | 292 Label loop; |
293 __ bind(&loop); | 293 __ bind(&loop); |
294 __ lbu(a3, MemOperand(a0, 0)); | 294 __ lbu(a3, MemOperand(a0, 0)); |
295 __ daddiu(a0, a0, char_size()); | 295 __ daddiu(a0, a0, char_size()); |
(...skipping 18 matching lines...) Expand all Loading... |
314 __ bind(&loop_check); | 314 __ bind(&loop_check); |
315 __ Branch(&loop, lt, a0, Operand(a1)); | 315 __ Branch(&loop, lt, a0, Operand(a1)); |
316 __ jmp(&success); | 316 __ jmp(&success); |
317 | 317 |
318 __ bind(&fail); | 318 __ bind(&fail); |
319 GoTo(on_no_match); | 319 GoTo(on_no_match); |
320 | 320 |
321 __ bind(&success); | 321 __ bind(&success); |
322 // Compute new value of character position after the matched part. | 322 // Compute new value of character position after the matched part. |
323 __ Dsubu(current_input_offset(), a2, end_of_input_address()); | 323 __ Dsubu(current_input_offset(), a2, end_of_input_address()); |
324 if (read_backward) { | |
325 __ ld(t1, register_location(start_reg)); // Index of start of capture. | |
326 __ ld(a2, register_location(start_reg + 1)); // Index of end of capture. | |
327 __ Daddu(current_input_offset(), current_input_offset(), Operand(t1)); | |
328 __ Dsubu(current_input_offset(), current_input_offset(), Operand(a2)); | |
329 } | |
330 } else { | 324 } else { |
331 DCHECK(mode_ == UC16); | 325 DCHECK(mode_ == UC16); |
332 // Put regexp engine registers on stack. | 326 // Put regexp engine registers on stack. |
333 RegList regexp_registers_to_retain = current_input_offset().bit() | | 327 RegList regexp_registers_to_retain = current_input_offset().bit() | |
334 current_character().bit() | backtrack_stackpointer().bit(); | 328 current_character().bit() | backtrack_stackpointer().bit(); |
335 __ MultiPush(regexp_registers_to_retain); | 329 __ MultiPush(regexp_registers_to_retain); |
336 | 330 |
337 int argument_count = 4; | 331 int argument_count = 4; |
338 __ PrepareCallCFunction(argument_count, a2); | 332 __ PrepareCallCFunction(argument_count, a2); |
339 | 333 |
340 // a0 - offset of start of capture. | 334 // a0 - offset of start of capture. |
341 // a1 - length of capture. | 335 // a1 - length of capture. |
342 | 336 |
343 // Put arguments into arguments registers. | 337 // Put arguments into arguments registers. |
344 // Parameters are | 338 // Parameters are |
345 // a0: Address byte_offset1 - Address captured substring's start. | 339 // a0: Address byte_offset1 - Address captured substring's start. |
346 // a1: Address byte_offset2 - Address of current character position. | 340 // a1: Address byte_offset2 - Address of current character position. |
347 // a2: size_t byte_length - length of capture in bytes(!). | 341 // a2: size_t byte_length - length of capture in bytes(!). |
348 // a3: Isolate* isolate. | 342 // a3: Isolate* isolate. |
349 | 343 |
350 // Address of start of capture. | 344 // Address of start of capture. |
351 __ Daddu(a0, a0, Operand(end_of_input_address())); | 345 __ Daddu(a0, a0, Operand(end_of_input_address())); |
352 // Length of capture. | 346 // Length of capture. |
353 __ mov(a2, a1); | 347 __ mov(a2, a1); |
354 // Save length in callee-save register for use on return. | 348 // Save length in callee-save register for use on return. |
355 __ mov(s3, a1); | 349 __ mov(s3, a1); |
356 // Address of current input position. | 350 // Address of current input position. |
357 __ Daddu(a1, current_input_offset(), Operand(end_of_input_address())); | 351 __ Daddu(a1, current_input_offset(), Operand(end_of_input_address())); |
358 if (read_backward) { | |
359 __ Dsubu(a1, a1, Operand(s3)); | |
360 } | |
361 // Isolate. | 352 // Isolate. |
362 __ li(a3, Operand(ExternalReference::isolate_address(masm_->isolate()))); | 353 __ li(a3, Operand(ExternalReference::isolate_address(masm_->isolate()))); |
363 | 354 |
364 { | 355 { |
365 AllowExternalCallThatCantCauseGC scope(masm_); | 356 AllowExternalCallThatCantCauseGC scope(masm_); |
366 ExternalReference function = | 357 ExternalReference function = |
367 ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate()); | 358 ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate()); |
368 __ CallCFunction(function, argument_count); | 359 __ CallCFunction(function, argument_count); |
369 } | 360 } |
370 | 361 |
371 // Restore regexp engine registers. | 362 // Restore regexp engine registers. |
372 __ MultiPop(regexp_registers_to_retain); | 363 __ MultiPop(regexp_registers_to_retain); |
373 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); | 364 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); |
374 __ ld(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); | 365 __ ld(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); |
375 | 366 |
376 // Check if function returned non-zero for success or zero for failure. | 367 // Check if function returned non-zero for success or zero for failure. |
377 BranchOrBacktrack(on_no_match, eq, v0, Operand(zero_reg)); | 368 BranchOrBacktrack(on_no_match, eq, v0, Operand(zero_reg)); |
378 // On success, increment position by length of capture. | 369 // On success, increment position by length of capture. |
379 if (read_backward) { | 370 __ Daddu(current_input_offset(), current_input_offset(), Operand(s3)); |
380 __ Dsubu(current_input_offset(), current_input_offset(), Operand(s3)); | |
381 } else { | |
382 __ Daddu(current_input_offset(), current_input_offset(), Operand(s3)); | |
383 } | |
384 } | 371 } |
385 | 372 |
386 __ bind(&fallthrough); | 373 __ bind(&fallthrough); |
387 } | 374 } |
388 | 375 |
389 | 376 |
390 void RegExpMacroAssemblerMIPS::CheckNotBackReference(int start_reg, | 377 void RegExpMacroAssemblerMIPS::CheckNotBackReference( |
391 bool read_backward, | 378 int start_reg, |
392 Label* on_no_match) { | 379 Label* on_no_match) { |
393 Label fallthrough; | 380 Label fallthrough; |
394 Label success; | 381 Label success; |
395 | 382 |
396 // Find length of back-referenced capture. | 383 // Find length of back-referenced capture. |
397 __ ld(a0, register_location(start_reg)); | 384 __ ld(a0, register_location(start_reg)); |
398 __ ld(a1, register_location(start_reg + 1)); | 385 __ ld(a1, register_location(start_reg + 1)); |
399 __ Dsubu(a1, a1, a0); // Length to check. | 386 __ Dsubu(a1, a1, a0); // Length to check. |
400 | 387 // Succeed on empty capture (including no capture). |
401 // At this point, the capture registers are either both set or both cleared. | |
402 // If the capture length is zero, then the capture is either empty or cleared. | |
403 // Fall through in both cases. | |
404 __ Branch(&fallthrough, eq, a1, Operand(zero_reg)); | 388 __ Branch(&fallthrough, eq, a1, Operand(zero_reg)); |
405 | 389 |
406 if (read_backward) { | 390 __ Daddu(t1, a1, current_input_offset()); |
407 __ ld(t1, MemOperand(frame_pointer(), kStringStartMinusOne)); | 391 // Check that there are enough characters left in the input. |
408 __ Daddu(t1, t1, a1); | 392 BranchOrBacktrack(on_no_match, gt, t1, Operand(zero_reg)); |
409 BranchOrBacktrack(on_no_match, le, current_input_offset(), Operand(t1)); | |
410 } else { | |
411 __ Daddu(t1, a1, current_input_offset()); | |
412 // Check that there are enough characters left in the input. | |
413 BranchOrBacktrack(on_no_match, gt, t1, Operand(zero_reg)); | |
414 } | |
415 | 393 |
416 // Compute pointers to match string and capture string. | 394 // Compute pointers to match string and capture string. |
417 __ Daddu(a0, a0, Operand(end_of_input_address())); | 395 __ Daddu(a0, a0, Operand(end_of_input_address())); |
418 __ Daddu(a2, end_of_input_address(), Operand(current_input_offset())); | 396 __ Daddu(a2, end_of_input_address(), Operand(current_input_offset())); |
419 if (read_backward) { | |
420 __ Dsubu(a2, a2, Operand(a1)); | |
421 } | |
422 __ Daddu(a1, a1, Operand(a0)); | 397 __ Daddu(a1, a1, Operand(a0)); |
423 | 398 |
424 Label loop; | 399 Label loop; |
425 __ bind(&loop); | 400 __ bind(&loop); |
426 if (mode_ == LATIN1) { | 401 if (mode_ == LATIN1) { |
427 __ lbu(a3, MemOperand(a0, 0)); | 402 __ lbu(a3, MemOperand(a0, 0)); |
428 __ daddiu(a0, a0, char_size()); | 403 __ daddiu(a0, a0, char_size()); |
429 __ lbu(a4, MemOperand(a2, 0)); | 404 __ lbu(a4, MemOperand(a2, 0)); |
430 __ daddiu(a2, a2, char_size()); | 405 __ daddiu(a2, a2, char_size()); |
431 } else { | 406 } else { |
432 DCHECK(mode_ == UC16); | 407 DCHECK(mode_ == UC16); |
433 __ lhu(a3, MemOperand(a0, 0)); | 408 __ lhu(a3, MemOperand(a0, 0)); |
434 __ daddiu(a0, a0, char_size()); | 409 __ daddiu(a0, a0, char_size()); |
435 __ lhu(a4, MemOperand(a2, 0)); | 410 __ lhu(a4, MemOperand(a2, 0)); |
436 __ daddiu(a2, a2, char_size()); | 411 __ daddiu(a2, a2, char_size()); |
437 } | 412 } |
438 BranchOrBacktrack(on_no_match, ne, a3, Operand(a4)); | 413 BranchOrBacktrack(on_no_match, ne, a3, Operand(a4)); |
439 __ Branch(&loop, lt, a0, Operand(a1)); | 414 __ Branch(&loop, lt, a0, Operand(a1)); |
440 | 415 |
441 // Move current character position to position after match. | 416 // Move current character position to position after match. |
442 __ Dsubu(current_input_offset(), a2, end_of_input_address()); | 417 __ Dsubu(current_input_offset(), a2, end_of_input_address()); |
443 if (read_backward) { | |
444 __ ld(t1, register_location(start_reg)); // Index of start of capture. | |
445 __ ld(a2, register_location(start_reg + 1)); // Index of end of capture. | |
446 __ Daddu(current_input_offset(), current_input_offset(), Operand(t1)); | |
447 __ Dsubu(current_input_offset(), current_input_offset(), Operand(a2)); | |
448 } | |
449 __ bind(&fallthrough); | 418 __ bind(&fallthrough); |
450 } | 419 } |
451 | 420 |
452 | 421 |
453 void RegExpMacroAssemblerMIPS::CheckNotCharacter(uint32_t c, | 422 void RegExpMacroAssemblerMIPS::CheckNotCharacter(uint32_t c, |
454 Label* on_not_equal) { | 423 Label* on_not_equal) { |
455 BranchOrBacktrack(on_not_equal, ne, current_character(), Operand(c)); | 424 BranchOrBacktrack(on_not_equal, ne, current_character(), Operand(c)); |
456 } | 425 } |
457 | 426 |
458 | 427 |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 argument_registers |= a4.bit() | a5.bit() | a6.bit() | a7.bit(); | 637 argument_registers |= a4.bit() | a5.bit() | a6.bit() | a7.bit(); |
669 } | 638 } |
670 | 639 |
671 __ MultiPush(argument_registers | registers_to_retain | ra.bit()); | 640 __ MultiPush(argument_registers | registers_to_retain | ra.bit()); |
672 // Set frame pointer in space for it if this is not a direct call | 641 // Set frame pointer in space for it if this is not a direct call |
673 // from generated code. | 642 // from generated code. |
674 // TODO(plind): this 8 is the # of argument regs, should have definition. | 643 // TODO(plind): this 8 is the # of argument regs, should have definition. |
675 __ Daddu(frame_pointer(), sp, Operand(8 * kPointerSize)); | 644 __ Daddu(frame_pointer(), sp, Operand(8 * kPointerSize)); |
676 __ mov(a0, zero_reg); | 645 __ mov(a0, zero_reg); |
677 __ push(a0); // Make room for success counter and initialize it to 0. | 646 __ push(a0); // Make room for success counter and initialize it to 0. |
678 __ push(a0); // Make room for "string start - 1" constant. | 647 __ push(a0); // Make room for "position - 1" constant (value irrelevant). |
679 | 648 |
680 // Check if we have space on the stack for registers. | 649 // Check if we have space on the stack for registers. |
681 Label stack_limit_hit; | 650 Label stack_limit_hit; |
682 Label stack_ok; | 651 Label stack_ok; |
683 | 652 |
684 ExternalReference stack_limit = | 653 ExternalReference stack_limit = |
685 ExternalReference::address_of_stack_limit(masm_->isolate()); | 654 ExternalReference::address_of_stack_limit(masm_->isolate()); |
686 __ li(a0, Operand(stack_limit)); | 655 __ li(a0, Operand(stack_limit)); |
687 __ ld(a0, MemOperand(a0)); | 656 __ ld(a0, MemOperand(a0)); |
688 __ Dsubu(a0, sp, a0); | 657 __ Dsubu(a0, sp, a0); |
(...skipping 22 matching lines...) Expand all Loading... |
711 // Find negative length (offset of start relative to end). | 680 // Find negative length (offset of start relative to end). |
712 __ Dsubu(current_input_offset(), a0, end_of_input_address()); | 681 __ Dsubu(current_input_offset(), a0, end_of_input_address()); |
713 // Set a0 to address of char before start of the input string | 682 // Set a0 to address of char before start of the input string |
714 // (effectively string position -1). | 683 // (effectively string position -1). |
715 __ ld(a1, MemOperand(frame_pointer(), kStartIndex)); | 684 __ ld(a1, MemOperand(frame_pointer(), kStartIndex)); |
716 __ Dsubu(a0, current_input_offset(), Operand(char_size())); | 685 __ Dsubu(a0, current_input_offset(), Operand(char_size())); |
717 __ dsll(t1, a1, (mode_ == UC16) ? 1 : 0); | 686 __ dsll(t1, a1, (mode_ == UC16) ? 1 : 0); |
718 __ Dsubu(a0, a0, t1); | 687 __ Dsubu(a0, a0, t1); |
719 // Store this value in a local variable, for use when clearing | 688 // Store this value in a local variable, for use when clearing |
720 // position registers. | 689 // position registers. |
721 __ sd(a0, MemOperand(frame_pointer(), kStringStartMinusOne)); | 690 __ sd(a0, MemOperand(frame_pointer(), kInputStartMinusOne)); |
722 | 691 |
723 // Initialize code pointer register | 692 // Initialize code pointer register |
724 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); | 693 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); |
725 | 694 |
726 Label load_char_start_regexp, start_regexp; | 695 Label load_char_start_regexp, start_regexp; |
727 // Load newline if index is at start, previous character otherwise. | 696 // Load newline if index is at start, previous character otherwise. |
728 __ Branch(&load_char_start_regexp, ne, a1, Operand(zero_reg)); | 697 __ Branch(&load_char_start_regexp, ne, a1, Operand(zero_reg)); |
729 __ li(current_character(), Operand('\n')); | 698 __ li(current_character(), Operand('\n')); |
730 __ jmp(&start_regexp); | 699 __ jmp(&start_regexp); |
731 | 700 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
821 // Check whether we have enough room for another set of capture results. | 790 // Check whether we have enough room for another set of capture results. |
822 __ mov(v0, a0); | 791 __ mov(v0, a0); |
823 __ Branch(&return_v0, lt, a1, Operand(num_saved_registers_)); | 792 __ Branch(&return_v0, lt, a1, Operand(num_saved_registers_)); |
824 | 793 |
825 __ sd(a1, MemOperand(frame_pointer(), kNumOutputRegisters)); | 794 __ sd(a1, MemOperand(frame_pointer(), kNumOutputRegisters)); |
826 // Advance the location for output. | 795 // Advance the location for output. |
827 __ Daddu(a2, a2, num_saved_registers_ * kIntSize); | 796 __ Daddu(a2, a2, num_saved_registers_ * kIntSize); |
828 __ sd(a2, MemOperand(frame_pointer(), kRegisterOutput)); | 797 __ sd(a2, MemOperand(frame_pointer(), kRegisterOutput)); |
829 | 798 |
830 // Prepare a0 to initialize registers with its value in the next run. | 799 // Prepare a0 to initialize registers with its value in the next run. |
831 __ ld(a0, MemOperand(frame_pointer(), kStringStartMinusOne)); | 800 __ ld(a0, MemOperand(frame_pointer(), kInputStartMinusOne)); |
832 | 801 |
833 if (global_with_zero_length_check()) { | 802 if (global_with_zero_length_check()) { |
834 // Special case for zero-length matches. | 803 // Special case for zero-length matches. |
835 // t3: capture start index | 804 // t3: capture start index |
836 // Not a zero-length match, restart. | 805 // Not a zero-length match, restart. |
837 __ Branch( | 806 __ Branch( |
838 &load_char_start_regexp, ne, current_input_offset(), Operand(t3)); | 807 &load_char_start_regexp, ne, current_input_offset(), Operand(t3)); |
839 // Offset from the end is zero if we already reached the end. | 808 // Offset from the end is zero if we already reached the end. |
840 __ Branch(&exit_label_, eq, current_input_offset(), | 809 __ Branch(&exit_label_, eq, current_input_offset(), |
841 Operand(zero_reg)); | 810 Operand(zero_reg)); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
975 RegExpMacroAssembler::IrregexpImplementation | 944 RegExpMacroAssembler::IrregexpImplementation |
976 RegExpMacroAssemblerMIPS::Implementation() { | 945 RegExpMacroAssemblerMIPS::Implementation() { |
977 return kMIPSImplementation; | 946 return kMIPSImplementation; |
978 } | 947 } |
979 | 948 |
980 | 949 |
981 void RegExpMacroAssemblerMIPS::LoadCurrentCharacter(int cp_offset, | 950 void RegExpMacroAssemblerMIPS::LoadCurrentCharacter(int cp_offset, |
982 Label* on_end_of_input, | 951 Label* on_end_of_input, |
983 bool check_bounds, | 952 bool check_bounds, |
984 int characters) { | 953 int characters) { |
| 954 DCHECK(cp_offset >= -1); // ^ and \b can look behind one character. |
985 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works). | 955 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works). |
986 if (check_bounds) { | 956 if (check_bounds) { |
987 if (cp_offset >= 0) { | 957 CheckPosition(cp_offset + characters - 1, on_end_of_input); |
988 CheckPosition(cp_offset + characters - 1, on_end_of_input); | |
989 } else { | |
990 CheckPosition(cp_offset, on_end_of_input); | |
991 } | |
992 } | 958 } |
993 LoadCurrentCharacterUnchecked(cp_offset, characters); | 959 LoadCurrentCharacterUnchecked(cp_offset, characters); |
994 } | 960 } |
995 | 961 |
996 | 962 |
997 void RegExpMacroAssemblerMIPS::PopCurrentPosition() { | 963 void RegExpMacroAssemblerMIPS::PopCurrentPosition() { |
998 Pop(current_input_offset()); | 964 Pop(current_input_offset()); |
999 } | 965 } |
1000 | 966 |
1001 | 967 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1089 __ sd(current_input_offset(), register_location(reg)); | 1055 __ sd(current_input_offset(), register_location(reg)); |
1090 } else { | 1056 } else { |
1091 __ Daddu(a0, current_input_offset(), Operand(cp_offset * char_size())); | 1057 __ Daddu(a0, current_input_offset(), Operand(cp_offset * char_size())); |
1092 __ sd(a0, register_location(reg)); | 1058 __ sd(a0, register_location(reg)); |
1093 } | 1059 } |
1094 } | 1060 } |
1095 | 1061 |
1096 | 1062 |
1097 void RegExpMacroAssemblerMIPS::ClearRegisters(int reg_from, int reg_to) { | 1063 void RegExpMacroAssemblerMIPS::ClearRegisters(int reg_from, int reg_to) { |
1098 DCHECK(reg_from <= reg_to); | 1064 DCHECK(reg_from <= reg_to); |
1099 __ ld(a0, MemOperand(frame_pointer(), kStringStartMinusOne)); | 1065 __ ld(a0, MemOperand(frame_pointer(), kInputStartMinusOne)); |
1100 for (int reg = reg_from; reg <= reg_to; reg++) { | 1066 for (int reg = reg_from; reg <= reg_to; reg++) { |
1101 __ sd(a0, register_location(reg)); | 1067 __ sd(a0, register_location(reg)); |
1102 } | 1068 } |
1103 } | 1069 } |
1104 | 1070 |
1105 | 1071 |
1106 void RegExpMacroAssemblerMIPS::WriteStackPointerToRegister(int reg) { | 1072 void RegExpMacroAssemblerMIPS::WriteStackPointerToRegister(int reg) { |
1107 __ ld(a1, MemOperand(frame_pointer(), kStackHighEnd)); | 1073 __ ld(a1, MemOperand(frame_pointer(), kStackHighEnd)); |
1108 __ Dsubu(a0, backtrack_stackpointer(), a1); | 1074 __ Dsubu(a0, backtrack_stackpointer(), a1); |
1109 __ sd(a0, register_location(reg)); | 1075 __ sd(a0, register_location(reg)); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1202 if (num_registers_ <= register_index) { | 1168 if (num_registers_ <= register_index) { |
1203 num_registers_ = register_index + 1; | 1169 num_registers_ = register_index + 1; |
1204 } | 1170 } |
1205 return MemOperand(frame_pointer(), | 1171 return MemOperand(frame_pointer(), |
1206 kRegisterZero - register_index * kPointerSize); | 1172 kRegisterZero - register_index * kPointerSize); |
1207 } | 1173 } |
1208 | 1174 |
1209 | 1175 |
1210 void RegExpMacroAssemblerMIPS::CheckPosition(int cp_offset, | 1176 void RegExpMacroAssemblerMIPS::CheckPosition(int cp_offset, |
1211 Label* on_outside_input) { | 1177 Label* on_outside_input) { |
1212 if (cp_offset >= 0) { | 1178 BranchOrBacktrack(on_outside_input, |
1213 BranchOrBacktrack(on_outside_input, ge, current_input_offset(), | 1179 ge, |
1214 Operand(-cp_offset * char_size())); | 1180 current_input_offset(), |
1215 } else { | 1181 Operand(-cp_offset * char_size())); |
1216 __ ld(a1, MemOperand(frame_pointer(), kStringStartMinusOne)); | |
1217 __ Daddu(a0, current_input_offset(), Operand(cp_offset * char_size())); | |
1218 BranchOrBacktrack(on_outside_input, le, a0, Operand(a1)); | |
1219 } | |
1220 } | 1182 } |
1221 | 1183 |
1222 | 1184 |
1223 void RegExpMacroAssemblerMIPS::BranchOrBacktrack(Label* to, | 1185 void RegExpMacroAssemblerMIPS::BranchOrBacktrack(Label* to, |
1224 Condition condition, | 1186 Condition condition, |
1225 Register rs, | 1187 Register rs, |
1226 const Operand& rt) { | 1188 const Operand& rt) { |
1227 if (condition == al) { // Unconditional. | 1189 if (condition == al) { // Unconditional. |
1228 if (to == NULL) { | 1190 if (to == NULL) { |
1229 Backtrack(); | 1191 Backtrack(); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1319 } | 1281 } |
1320 | 1282 |
1321 #undef __ | 1283 #undef __ |
1322 | 1284 |
1323 #endif // V8_INTERPRETED_REGEXP | 1285 #endif // V8_INTERPRETED_REGEXP |
1324 | 1286 |
1325 } // namespace internal | 1287 } // namespace internal |
1326 } // namespace v8 | 1288 } // namespace v8 |
1327 | 1289 |
1328 #endif // V8_TARGET_ARCH_MIPS64 | 1290 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |