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