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