OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
6 | 6 |
7 #include "src/regexp/arm64/regexp-macro-assembler-arm64.h" | 7 #include "src/regexp/arm64/regexp-macro-assembler-arm64.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 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
203 } | 203 } |
204 | 204 |
205 | 205 |
206 void RegExpMacroAssemblerARM64::CheckCharacterGT(uc16 limit, | 206 void RegExpMacroAssemblerARM64::CheckCharacterGT(uc16 limit, |
207 Label* on_greater) { | 207 Label* on_greater) { |
208 CompareAndBranchOrBacktrack(current_character(), limit, hi, on_greater); | 208 CompareAndBranchOrBacktrack(current_character(), limit, hi, on_greater); |
209 } | 209 } |
210 | 210 |
211 | 211 |
212 void RegExpMacroAssemblerARM64::CheckAtStart(Label* on_at_start) { | 212 void RegExpMacroAssemblerARM64::CheckAtStart(Label* on_at_start) { |
213 __ Add(w10, current_input_offset(), Operand(-char_size())); | 213 Label not_at_start; |
214 __ Cmp(w10, string_start_minus_one()); | 214 // Did we start the match at the start of the input string? |
| 215 CompareAndBranchOrBacktrack(start_offset(), 0, ne, ¬_at_start); |
| 216 // If we did, are we still at the start of the input string? |
| 217 __ Add(x10, input_end(), Operand(current_input_offset(), SXTW)); |
| 218 __ Cmp(x10, input_start()); |
215 BranchOrBacktrack(eq, on_at_start); | 219 BranchOrBacktrack(eq, on_at_start); |
| 220 __ Bind(¬_at_start); |
216 } | 221 } |
217 | 222 |
218 | 223 |
219 void RegExpMacroAssemblerARM64::CheckNotAtStart(int cp_offset, | 224 void RegExpMacroAssemblerARM64::CheckNotAtStart(Label* on_not_at_start) { |
220 Label* on_not_at_start) { | 225 // Did we start the match at the start of the input string? |
221 __ Add(w10, current_input_offset(), | 226 CompareAndBranchOrBacktrack(start_offset(), 0, ne, on_not_at_start); |
222 Operand(-char_size() + cp_offset * char_size())); | 227 // If we did, are we still at the start of the input string? |
223 __ Cmp(w10, string_start_minus_one()); | 228 __ Add(x10, input_end(), Operand(current_input_offset(), SXTW)); |
| 229 __ Cmp(x10, input_start()); |
224 BranchOrBacktrack(ne, on_not_at_start); | 230 BranchOrBacktrack(ne, on_not_at_start); |
225 } | 231 } |
226 | 232 |
227 | 233 |
228 void RegExpMacroAssemblerARM64::CheckCharacterLT(uc16 limit, Label* on_less) { | 234 void RegExpMacroAssemblerARM64::CheckCharacterLT(uc16 limit, Label* on_less) { |
229 CompareAndBranchOrBacktrack(current_character(), limit, lo, on_less); | 235 CompareAndBranchOrBacktrack(current_character(), limit, lo, on_less); |
230 } | 236 } |
231 | 237 |
232 | 238 |
233 void RegExpMacroAssemblerARM64::CheckCharacters(Vector<const uc16> str, | 239 void RegExpMacroAssemblerARM64::CheckCharacters(Vector<const uc16> str, |
(...skipping 30 matching lines...) Expand all Loading... |
264 | 270 |
265 void RegExpMacroAssemblerARM64::CheckGreedyLoop(Label* on_equal) { | 271 void RegExpMacroAssemblerARM64::CheckGreedyLoop(Label* on_equal) { |
266 __ Ldr(w10, MemOperand(backtrack_stackpointer())); | 272 __ Ldr(w10, MemOperand(backtrack_stackpointer())); |
267 __ Cmp(current_input_offset(), w10); | 273 __ Cmp(current_input_offset(), w10); |
268 __ Cset(x11, eq); | 274 __ Cset(x11, eq); |
269 __ Add(backtrack_stackpointer(), | 275 __ Add(backtrack_stackpointer(), |
270 backtrack_stackpointer(), Operand(x11, LSL, kWRegSizeLog2)); | 276 backtrack_stackpointer(), Operand(x11, LSL, kWRegSizeLog2)); |
271 BranchOrBacktrack(eq, on_equal); | 277 BranchOrBacktrack(eq, on_equal); |
272 } | 278 } |
273 | 279 |
274 | |
275 void RegExpMacroAssemblerARM64::CheckNotBackReferenceIgnoreCase( | 280 void RegExpMacroAssemblerARM64::CheckNotBackReferenceIgnoreCase( |
276 int start_reg, bool read_backward, Label* on_no_match) { | 281 int start_reg, |
| 282 Label* on_no_match) { |
277 Label fallthrough; | 283 Label fallthrough; |
278 | 284 |
279 Register capture_start_offset = w10; | 285 Register capture_start_offset = w10; |
280 // Save the capture length in a callee-saved register so it will | 286 // Save the capture length in a callee-saved register so it will |
281 // be preserved if we call a C helper. | 287 // be preserved if we call a C helper. |
282 Register capture_length = w19; | 288 Register capture_length = w19; |
283 DCHECK(kCalleeSaved.IncludesAliasOf(capture_length)); | 289 DCHECK(kCalleeSaved.IncludesAliasOf(capture_length)); |
284 | 290 |
285 // Find length of back-referenced capture. | 291 // Find length of back-referenced capture. |
286 DCHECK((start_reg % 2) == 0); | 292 DCHECK((start_reg % 2) == 0); |
287 if (start_reg < kNumCachedRegisters) { | 293 if (start_reg < kNumCachedRegisters) { |
288 __ Mov(capture_start_offset.X(), GetCachedRegister(start_reg)); | 294 __ Mov(capture_start_offset.X(), GetCachedRegister(start_reg)); |
289 __ Lsr(x11, GetCachedRegister(start_reg), kWRegSizeInBits); | 295 __ Lsr(x11, GetCachedRegister(start_reg), kWRegSizeInBits); |
290 } else { | 296 } else { |
291 __ Ldp(w11, capture_start_offset, capture_location(start_reg, x10)); | 297 __ Ldp(w11, capture_start_offset, capture_location(start_reg, x10)); |
292 } | 298 } |
293 __ Sub(capture_length, w11, capture_start_offset); // Length to check. | 299 __ Sub(capture_length, w11, capture_start_offset); // Length to check. |
294 | 300 // Succeed on empty capture (including no capture). |
295 // At this point, the capture registers are either both set or both cleared. | 301 __ Cbz(capture_length, &fallthrough); |
296 // If the capture length is zero, then the capture is either empty or cleared. | |
297 // Fall through in both cases. | |
298 __ CompareAndBranch(capture_length, Operand(0), eq, &fallthrough); | |
299 | 302 |
300 // Check that there are enough characters left in the input. | 303 // Check that there are enough characters left in the input. |
301 if (read_backward) { | 304 __ Cmn(capture_length, current_input_offset()); |
302 __ Add(w12, string_start_minus_one(), capture_length); | 305 BranchOrBacktrack(gt, on_no_match); |
303 __ Cmp(current_input_offset(), w12); | |
304 BranchOrBacktrack(le, on_no_match); | |
305 } else { | |
306 __ Cmn(capture_length, current_input_offset()); | |
307 BranchOrBacktrack(gt, on_no_match); | |
308 } | |
309 | 306 |
310 if (mode_ == LATIN1) { | 307 if (mode_ == LATIN1) { |
311 Label success; | 308 Label success; |
312 Label fail; | 309 Label fail; |
313 Label loop_check; | 310 Label loop_check; |
314 | 311 |
315 Register capture_start_address = x12; | 312 Register capture_start_address = x12; |
316 Register capture_end_addresss = x13; | 313 Register capture_end_addresss = x13; |
317 Register current_position_address = x14; | 314 Register current_position_address = x14; |
318 | 315 |
319 __ Add(capture_start_address, | 316 __ Add(capture_start_address, |
320 input_end(), | 317 input_end(), |
321 Operand(capture_start_offset, SXTW)); | 318 Operand(capture_start_offset, SXTW)); |
322 __ Add(capture_end_addresss, | 319 __ Add(capture_end_addresss, |
323 capture_start_address, | 320 capture_start_address, |
324 Operand(capture_length, SXTW)); | 321 Operand(capture_length, SXTW)); |
325 __ Add(current_position_address, | 322 __ Add(current_position_address, |
326 input_end(), | 323 input_end(), |
327 Operand(current_input_offset(), SXTW)); | 324 Operand(current_input_offset(), SXTW)); |
328 if (read_backward) { | |
329 // Offset by length when matching backwards. | |
330 __ Sub(current_position_address, current_position_address, | |
331 Operand(capture_length, SXTW)); | |
332 } | |
333 | 325 |
334 Label loop; | 326 Label loop; |
335 __ Bind(&loop); | 327 __ Bind(&loop); |
336 __ Ldrb(w10, MemOperand(capture_start_address, 1, PostIndex)); | 328 __ Ldrb(w10, MemOperand(capture_start_address, 1, PostIndex)); |
337 __ Ldrb(w11, MemOperand(current_position_address, 1, PostIndex)); | 329 __ Ldrb(w11, MemOperand(current_position_address, 1, PostIndex)); |
338 __ Cmp(w10, w11); | 330 __ Cmp(w10, w11); |
339 __ B(eq, &loop_check); | 331 __ B(eq, &loop_check); |
340 | 332 |
341 // Mismatch, try case-insensitive match (converting letters to lower-case). | 333 // Mismatch, try case-insensitive match (converting letters to lower-case). |
342 __ Orr(w10, w10, 0x20); // Convert capture character to lower-case. | 334 __ Orr(w10, w10, 0x20); // Convert capture character to lower-case. |
(...skipping 19 matching lines...) Expand all Loading... |
362 | 354 |
363 __ Bind(&success); | 355 __ Bind(&success); |
364 // Compute new value of character position after the matched part. | 356 // Compute new value of character position after the matched part. |
365 __ Sub(current_input_offset().X(), current_position_address, input_end()); | 357 __ Sub(current_input_offset().X(), current_position_address, input_end()); |
366 if (masm_->emit_debug_code()) { | 358 if (masm_->emit_debug_code()) { |
367 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); | 359 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); |
368 __ Ccmp(current_input_offset(), 0, NoFlag, eq); | 360 __ Ccmp(current_input_offset(), 0, NoFlag, eq); |
369 // The current input offset should be <= 0, and fit in a W register. | 361 // The current input offset should be <= 0, and fit in a W register. |
370 __ Check(le, kOffsetOutOfRange); | 362 __ Check(le, kOffsetOutOfRange); |
371 } | 363 } |
372 if (read_backward) { | |
373 __ Sub(current_input_offset(), current_input_offset(), | |
374 Operand(capture_length, SXTW)); | |
375 } | |
376 } else { | 364 } else { |
377 DCHECK(mode_ == UC16); | 365 DCHECK(mode_ == UC16); |
378 int argument_count = 4; | 366 int argument_count = 4; |
379 | 367 |
380 // The cached registers need to be retained. | 368 // The cached registers need to be retained. |
381 CPURegList cached_registers(CPURegister::kRegister, kXRegSizeInBits, 0, 7); | 369 CPURegList cached_registers(CPURegister::kRegister, kXRegSizeInBits, 0, 7); |
382 DCHECK((cached_registers.Count() * 2) == kNumCachedRegisters); | 370 DCHECK((cached_registers.Count() * 2) == kNumCachedRegisters); |
383 __ PushCPURegList(cached_registers); | 371 __ PushCPURegList(cached_registers); |
384 | 372 |
385 // Put arguments into arguments registers. | 373 // Put arguments into arguments registers. |
386 // Parameters are | 374 // Parameters are |
387 // x0: Address byte_offset1 - Address captured substring's start. | 375 // x0: Address byte_offset1 - Address captured substring's start. |
388 // x1: Address byte_offset2 - Address of current character position. | 376 // x1: Address byte_offset2 - Address of current character position. |
389 // w2: size_t byte_length - length of capture in bytes(!) | 377 // w2: size_t byte_length - length of capture in bytes(!) |
390 // x3: Isolate* isolate | 378 // x3: Isolate* isolate |
391 | 379 |
392 // Address of start of capture. | 380 // Address of start of capture. |
393 __ Add(x0, input_end(), Operand(capture_start_offset, SXTW)); | 381 __ Add(x0, input_end(), Operand(capture_start_offset, SXTW)); |
394 // Length of capture. | 382 // Length of capture. |
395 __ Mov(w2, capture_length); | 383 __ Mov(w2, capture_length); |
396 // Address of current input position. | 384 // Address of current input position. |
397 __ Add(x1, input_end(), Operand(current_input_offset(), SXTW)); | 385 __ Add(x1, input_end(), Operand(current_input_offset(), SXTW)); |
398 if (read_backward) { | |
399 __ Sub(x1, x1, Operand(capture_length, SXTW)); | |
400 } | |
401 // Isolate. | 386 // Isolate. |
402 __ Mov(x3, ExternalReference::isolate_address(isolate())); | 387 __ Mov(x3, ExternalReference::isolate_address(isolate())); |
403 | 388 |
404 { | 389 { |
405 AllowExternalCallThatCantCauseGC scope(masm_); | 390 AllowExternalCallThatCantCauseGC scope(masm_); |
406 ExternalReference function = | 391 ExternalReference function = |
407 ExternalReference::re_case_insensitive_compare_uc16(isolate()); | 392 ExternalReference::re_case_insensitive_compare_uc16(isolate()); |
408 __ CallCFunction(function, argument_count); | 393 __ CallCFunction(function, argument_count); |
409 } | 394 } |
410 | 395 |
411 // Check if function returned non-zero for success or zero for failure. | 396 // Check if function returned non-zero for success or zero for failure. |
412 // x0 is one of the registers used as a cache so it must be tested before | 397 // x0 is one of the registers used as a cache so it must be tested before |
413 // the cache is restored. | 398 // the cache is restored. |
414 __ Cmp(x0, 0); | 399 __ Cmp(x0, 0); |
415 __ PopCPURegList(cached_registers); | 400 __ PopCPURegList(cached_registers); |
416 BranchOrBacktrack(eq, on_no_match); | 401 BranchOrBacktrack(eq, on_no_match); |
417 | 402 |
418 // On success, advance position by length of capture. | 403 // On success, increment position by length of capture. |
419 if (read_backward) { | 404 __ Add(current_input_offset(), current_input_offset(), capture_length); |
420 __ Sub(current_input_offset(), current_input_offset(), capture_length); | |
421 } else { | |
422 __ Add(current_input_offset(), current_input_offset(), capture_length); | |
423 } | |
424 } | 405 } |
425 | 406 |
426 __ Bind(&fallthrough); | 407 __ Bind(&fallthrough); |
427 } | 408 } |
428 | 409 |
429 void RegExpMacroAssemblerARM64::CheckNotBackReference(int start_reg, | 410 void RegExpMacroAssemblerARM64::CheckNotBackReference( |
430 bool read_backward, | 411 int start_reg, |
431 Label* on_no_match) { | 412 Label* on_no_match) { |
432 Label fallthrough; | 413 Label fallthrough; |
433 | 414 |
434 Register capture_start_address = x12; | 415 Register capture_start_address = x12; |
435 Register capture_end_address = x13; | 416 Register capture_end_address = x13; |
436 Register current_position_address = x14; | 417 Register current_position_address = x14; |
437 Register capture_length = w15; | 418 Register capture_length = w15; |
438 | 419 |
439 // Find length of back-referenced capture. | 420 // Find length of back-referenced capture. |
440 DCHECK((start_reg % 2) == 0); | 421 DCHECK((start_reg % 2) == 0); |
441 if (start_reg < kNumCachedRegisters) { | 422 if (start_reg < kNumCachedRegisters) { |
442 __ Mov(x10, GetCachedRegister(start_reg)); | 423 __ Mov(x10, GetCachedRegister(start_reg)); |
443 __ Lsr(x11, GetCachedRegister(start_reg), kWRegSizeInBits); | 424 __ Lsr(x11, GetCachedRegister(start_reg), kWRegSizeInBits); |
444 } else { | 425 } else { |
445 __ Ldp(w11, w10, capture_location(start_reg, x10)); | 426 __ Ldp(w11, w10, capture_location(start_reg, x10)); |
446 } | 427 } |
447 __ Sub(capture_length, w11, w10); // Length to check. | 428 __ Sub(capture_length, w11, w10); // Length to check. |
448 | 429 // Succeed on empty capture (including no capture). |
449 // At this point, the capture registers are either both set or both cleared. | 430 __ Cbz(capture_length, &fallthrough); |
450 // If the capture length is zero, then the capture is either empty or cleared. | |
451 // Fall through in both cases. | |
452 __ CompareAndBranch(capture_length, Operand(0), eq, &fallthrough); | |
453 | 431 |
454 // Check that there are enough characters left in the input. | 432 // Check that there are enough characters left in the input. |
455 if (read_backward) { | 433 __ Cmn(capture_length, current_input_offset()); |
456 __ Add(w12, string_start_minus_one(), capture_length); | 434 BranchOrBacktrack(gt, on_no_match); |
457 __ Cmp(current_input_offset(), w12); | |
458 BranchOrBacktrack(le, on_no_match); | |
459 } else { | |
460 __ Cmn(capture_length, current_input_offset()); | |
461 BranchOrBacktrack(gt, on_no_match); | |
462 } | |
463 | 435 |
464 // Compute pointers to match string and capture string | 436 // Compute pointers to match string and capture string |
465 __ Add(capture_start_address, input_end(), Operand(w10, SXTW)); | 437 __ Add(capture_start_address, input_end(), Operand(w10, SXTW)); |
466 __ Add(capture_end_address, | 438 __ Add(capture_end_address, |
467 capture_start_address, | 439 capture_start_address, |
468 Operand(capture_length, SXTW)); | 440 Operand(capture_length, SXTW)); |
469 __ Add(current_position_address, | 441 __ Add(current_position_address, |
470 input_end(), | 442 input_end(), |
471 Operand(current_input_offset(), SXTW)); | 443 Operand(current_input_offset(), SXTW)); |
472 if (read_backward) { | |
473 // Offset by length when matching backwards. | |
474 __ Sub(current_position_address, current_position_address, | |
475 Operand(capture_length, SXTW)); | |
476 } | |
477 | 444 |
478 Label loop; | 445 Label loop; |
479 __ Bind(&loop); | 446 __ Bind(&loop); |
480 if (mode_ == LATIN1) { | 447 if (mode_ == LATIN1) { |
481 __ Ldrb(w10, MemOperand(capture_start_address, 1, PostIndex)); | 448 __ Ldrb(w10, MemOperand(capture_start_address, 1, PostIndex)); |
482 __ Ldrb(w11, MemOperand(current_position_address, 1, PostIndex)); | 449 __ Ldrb(w11, MemOperand(current_position_address, 1, PostIndex)); |
483 } else { | 450 } else { |
484 DCHECK(mode_ == UC16); | 451 DCHECK(mode_ == UC16); |
485 __ Ldrh(w10, MemOperand(capture_start_address, 2, PostIndex)); | 452 __ Ldrh(w10, MemOperand(capture_start_address, 2, PostIndex)); |
486 __ Ldrh(w11, MemOperand(current_position_address, 2, PostIndex)); | 453 __ Ldrh(w11, MemOperand(current_position_address, 2, PostIndex)); |
487 } | 454 } |
488 __ Cmp(w10, w11); | 455 __ Cmp(w10, w11); |
489 BranchOrBacktrack(ne, on_no_match); | 456 BranchOrBacktrack(ne, on_no_match); |
490 __ Cmp(capture_start_address, capture_end_address); | 457 __ Cmp(capture_start_address, capture_end_address); |
491 __ B(lt, &loop); | 458 __ B(lt, &loop); |
492 | 459 |
493 // Move current character position to position after match. | 460 // Move current character position to position after match. |
494 __ Sub(current_input_offset().X(), current_position_address, input_end()); | 461 __ Sub(current_input_offset().X(), current_position_address, input_end()); |
495 if (read_backward) { | |
496 __ Sub(current_input_offset(), current_input_offset(), | |
497 Operand(capture_length, SXTW)); | |
498 } | |
499 | |
500 if (masm_->emit_debug_code()) { | 462 if (masm_->emit_debug_code()) { |
501 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); | 463 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); |
502 __ Ccmp(current_input_offset(), 0, NoFlag, eq); | 464 __ Ccmp(current_input_offset(), 0, NoFlag, eq); |
503 // The current input offset should be <= 0, and fit in a W register. | 465 // The current input offset should be <= 0, and fit in a W register. |
504 __ Check(le, kOffsetOutOfRange); | 466 __ Check(le, kOffsetOutOfRange); |
505 } | 467 } |
506 __ Bind(&fallthrough); | 468 __ Bind(&fallthrough); |
507 } | 469 } |
508 | 470 |
509 | 471 |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 // Check that the input string length is < 2^30. | 751 // Check that the input string length is < 2^30. |
790 __ Neg(x11, x10); | 752 __ Neg(x11, x10); |
791 __ Cmp(x11, (1<<30) - 1); | 753 __ Cmp(x11, (1<<30) - 1); |
792 __ Check(ls, kInputStringTooLong); | 754 __ Check(ls, kInputStringTooLong); |
793 } | 755 } |
794 __ Mov(current_input_offset(), w10); | 756 __ Mov(current_input_offset(), w10); |
795 | 757 |
796 // The non-position value is used as a clearing value for the | 758 // The non-position value is used as a clearing value for the |
797 // capture registers, it corresponds to the position of the first character | 759 // capture registers, it corresponds to the position of the first character |
798 // minus one. | 760 // minus one. |
799 __ Sub(string_start_minus_one(), current_input_offset(), char_size()); | 761 __ Sub(non_position_value(), current_input_offset(), char_size()); |
800 __ Sub(string_start_minus_one(), string_start_minus_one(), | 762 __ Sub(non_position_value(), non_position_value(), |
801 Operand(start_offset(), LSL, (mode_ == UC16) ? 1 : 0)); | 763 Operand(start_offset(), LSL, (mode_ == UC16) ? 1 : 0)); |
802 // We can store this value twice in an X register for initializing | 764 // We can store this value twice in an X register for initializing |
803 // on-stack registers later. | 765 // on-stack registers later. |
804 __ Orr(twice_non_position_value(), string_start_minus_one().X(), | 766 __ Orr(twice_non_position_value(), |
805 Operand(string_start_minus_one().X(), LSL, kWRegSizeInBits)); | 767 non_position_value().X(), |
| 768 Operand(non_position_value().X(), LSL, kWRegSizeInBits)); |
806 | 769 |
807 // Initialize code pointer register. | 770 // Initialize code pointer register. |
808 __ Mov(code_pointer(), Operand(masm_->CodeObject())); | 771 __ Mov(code_pointer(), Operand(masm_->CodeObject())); |
809 | 772 |
810 Label load_char_start_regexp, start_regexp; | 773 Label load_char_start_regexp, start_regexp; |
811 // Load newline if index is at start, previous character otherwise. | 774 // Load newline if index is at start, previous character otherwise. |
812 __ Cbnz(start_offset(), &load_char_start_regexp); | 775 __ Cbnz(start_offset(), &load_char_start_regexp); |
813 __ Mov(current_character(), '\n'); | 776 __ Mov(current_character(), '\n'); |
814 __ B(&start_regexp); | 777 __ B(&start_regexp); |
815 | 778 |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1111 return kARM64Implementation; | 1074 return kARM64Implementation; |
1112 } | 1075 } |
1113 | 1076 |
1114 | 1077 |
1115 void RegExpMacroAssemblerARM64::LoadCurrentCharacter(int cp_offset, | 1078 void RegExpMacroAssemblerARM64::LoadCurrentCharacter(int cp_offset, |
1116 Label* on_end_of_input, | 1079 Label* on_end_of_input, |
1117 bool check_bounds, | 1080 bool check_bounds, |
1118 int characters) { | 1081 int characters) { |
1119 // TODO(pielan): Make sure long strings are caught before this, and not | 1082 // TODO(pielan): Make sure long strings are caught before this, and not |
1120 // just asserted in debug mode. | 1083 // just asserted in debug mode. |
| 1084 DCHECK(cp_offset >= -1); // ^ and \b can look behind one character. |
1121 // Be sane! (And ensure that an int32_t can be used to index the string) | 1085 // Be sane! (And ensure that an int32_t can be used to index the string) |
1122 DCHECK(cp_offset < (1<<30)); | 1086 DCHECK(cp_offset < (1<<30)); |
1123 if (check_bounds) { | 1087 if (check_bounds) { |
1124 if (cp_offset >= 0) { | 1088 CheckPosition(cp_offset + characters - 1, on_end_of_input); |
1125 CheckPosition(cp_offset + characters - 1, on_end_of_input); | |
1126 } else { | |
1127 CheckPosition(cp_offset, on_end_of_input); | |
1128 } | |
1129 } | 1089 } |
1130 LoadCurrentCharacterUnchecked(cp_offset, characters); | 1090 LoadCurrentCharacterUnchecked(cp_offset, characters); |
1131 } | 1091 } |
1132 | 1092 |
1133 | 1093 |
1134 void RegExpMacroAssemblerARM64::PopCurrentPosition() { | 1094 void RegExpMacroAssemblerARM64::PopCurrentPosition() { |
1135 Pop(current_input_offset()); | 1095 Pop(current_input_offset()); |
1136 } | 1096 } |
1137 | 1097 |
1138 | 1098 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1243 } | 1203 } |
1244 | 1204 |
1245 | 1205 |
1246 void RegExpMacroAssemblerARM64::ClearRegisters(int reg_from, int reg_to) { | 1206 void RegExpMacroAssemblerARM64::ClearRegisters(int reg_from, int reg_to) { |
1247 DCHECK(reg_from <= reg_to); | 1207 DCHECK(reg_from <= reg_to); |
1248 int num_registers = reg_to - reg_from + 1; | 1208 int num_registers = reg_to - reg_from + 1; |
1249 | 1209 |
1250 // If the first capture register is cached in a hardware register but not | 1210 // If the first capture register is cached in a hardware register but not |
1251 // aligned on a 64-bit one, we need to clear the first one specifically. | 1211 // aligned on a 64-bit one, we need to clear the first one specifically. |
1252 if ((reg_from < kNumCachedRegisters) && ((reg_from % 2) != 0)) { | 1212 if ((reg_from < kNumCachedRegisters) && ((reg_from % 2) != 0)) { |
1253 StoreRegister(reg_from, string_start_minus_one()); | 1213 StoreRegister(reg_from, non_position_value()); |
1254 num_registers--; | 1214 num_registers--; |
1255 reg_from++; | 1215 reg_from++; |
1256 } | 1216 } |
1257 | 1217 |
1258 // Clear cached registers in pairs as far as possible. | 1218 // Clear cached registers in pairs as far as possible. |
1259 while ((num_registers >= 2) && (reg_from < kNumCachedRegisters)) { | 1219 while ((num_registers >= 2) && (reg_from < kNumCachedRegisters)) { |
1260 DCHECK(GetRegisterState(reg_from) == CACHED_LSW); | 1220 DCHECK(GetRegisterState(reg_from) == CACHED_LSW); |
1261 __ Mov(GetCachedRegister(reg_from), twice_non_position_value()); | 1221 __ Mov(GetCachedRegister(reg_from), twice_non_position_value()); |
1262 reg_from += 2; | 1222 reg_from += 2; |
1263 num_registers -= 2; | 1223 num_registers -= 2; |
1264 } | 1224 } |
1265 | 1225 |
1266 if ((num_registers % 2) == 1) { | 1226 if ((num_registers % 2) == 1) { |
1267 StoreRegister(reg_from, string_start_minus_one()); | 1227 StoreRegister(reg_from, non_position_value()); |
1268 num_registers--; | 1228 num_registers--; |
1269 reg_from++; | 1229 reg_from++; |
1270 } | 1230 } |
1271 | 1231 |
1272 if (num_registers > 0) { | 1232 if (num_registers > 0) { |
1273 // If there are some remaining registers, they are stored on the stack. | 1233 // If there are some remaining registers, they are stored on the stack. |
1274 DCHECK(reg_from >= kNumCachedRegisters); | 1234 DCHECK(reg_from >= kNumCachedRegisters); |
1275 | 1235 |
1276 // Move down the indexes of the registers on stack to get the correct offset | 1236 // Move down the indexes of the registers on stack to get the correct offset |
1277 // in memory. | 1237 // in memory. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1334 const byte** input_start, const byte** input_end) { | 1294 const byte** input_start, const byte** input_end) { |
1335 return NativeRegExpMacroAssembler::CheckStackGuardState( | 1295 return NativeRegExpMacroAssembler::CheckStackGuardState( |
1336 frame_entry<Isolate*>(re_frame, kIsolate), start_index, | 1296 frame_entry<Isolate*>(re_frame, kIsolate), start_index, |
1337 frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code, | 1297 frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code, |
1338 frame_entry_address<String*>(re_frame, kInput), input_start, input_end); | 1298 frame_entry_address<String*>(re_frame, kInput), input_start, input_end); |
1339 } | 1299 } |
1340 | 1300 |
1341 | 1301 |
1342 void RegExpMacroAssemblerARM64::CheckPosition(int cp_offset, | 1302 void RegExpMacroAssemblerARM64::CheckPosition(int cp_offset, |
1343 Label* on_outside_input) { | 1303 Label* on_outside_input) { |
1344 if (cp_offset >= 0) { | 1304 CompareAndBranchOrBacktrack(current_input_offset(), |
1345 CompareAndBranchOrBacktrack(current_input_offset(), | 1305 -cp_offset * char_size(), |
1346 -cp_offset * char_size(), ge, on_outside_input); | 1306 ge, |
1347 } else { | 1307 on_outside_input); |
1348 __ Add(w12, current_input_offset(), Operand(cp_offset * char_size())); | |
1349 __ Cmp(w12, string_start_minus_one()); | |
1350 BranchOrBacktrack(le, on_outside_input); | |
1351 } | |
1352 } | 1308 } |
1353 | 1309 |
1354 | 1310 |
1355 bool RegExpMacroAssemblerARM64::CanReadUnaligned() { | 1311 bool RegExpMacroAssemblerARM64::CanReadUnaligned() { |
1356 // TODO(pielan): See whether or not we should disable unaligned accesses. | 1312 // TODO(pielan): See whether or not we should disable unaligned accesses. |
1357 return !slow_safe(); | 1313 return !slow_safe(); |
1358 } | 1314 } |
1359 | 1315 |
1360 | 1316 |
1361 // Private methods: | 1317 // Private methods: |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1650 } | 1606 } |
1651 } | 1607 } |
1652 } | 1608 } |
1653 | 1609 |
1654 #endif // V8_INTERPRETED_REGEXP | 1610 #endif // V8_INTERPRETED_REGEXP |
1655 | 1611 |
1656 } // namespace internal | 1612 } // namespace internal |
1657 } // namespace v8 | 1613 } // namespace v8 |
1658 | 1614 |
1659 #endif // V8_TARGET_ARCH_ARM64 | 1615 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |