| 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 // The length of the capture can only be negative if the end of the |
| 296 // capture is not yet recorded. If the length is zero, the capture is |
| 297 // either empty or uncaptured. In either of those cases, succeed. |
| 298 __ CompareAndBranch(capture_length, Operand(0), le, &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 __ Sub(w12, current_input_offset(), capture_length); |
| 303 __ Cmp(w12, string_start_minus_one()); |
| 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 19 matching lines...) Expand all Loading... |
| 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()); |
| 358 if (masm_->emit_debug_code()) { | 366 if (masm_->emit_debug_code()) { |
| 359 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); | 367 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); |
| 360 __ Ccmp(current_input_offset(), 0, NoFlag, eq); | 368 __ Ccmp(current_input_offset(), 0, NoFlag, eq); |
| 361 // The current input offset should be <= 0, and fit in a W register. | 369 // The current input offset should be <= 0, and fit in a W register. |
| 362 __ Check(le, kOffsetOutOfRange); | 370 __ Check(le, kOffsetOutOfRange); |
| 363 } | 371 } |
| 372 if (read_backward) { |
| 373 __ Sub(current_input_offset(), current_input_offset(), |
| 374 Operand(capture_length, SXTW)); |
| 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 // The length of the capture can only be negative if the end of the |
| 430 __ Cbz(capture_length, &fallthrough); | 449 // capture is not yet recorded. If the length is zero, the capture is |
| 450 // either empty or uncaptured. In either of those cases, succeed. |
| 451 __ CompareAndBranch(capture_length, Operand(0), le, &fallthrough); |
| 431 | 452 |
| 432 // Check that there are enough characters left in the input. | 453 // Check that there are enough characters left in the input. |
| 433 __ Cmn(capture_length, current_input_offset()); | 454 if (read_backward) { |
| 434 BranchOrBacktrack(gt, on_no_match); | 455 __ Sub(w12, current_input_offset(), capture_length); |
| 456 __ Cmp(w12, string_start_minus_one()); |
| 457 BranchOrBacktrack(le, on_no_match); |
| 458 } else { |
| 459 __ Cmn(capture_length, current_input_offset()); |
| 460 BranchOrBacktrack(gt, on_no_match); |
| 461 } |
| 435 | 462 |
| 436 // Compute pointers to match string and capture string | 463 // Compute pointers to match string and capture string |
| 437 __ Add(capture_start_address, input_end(), Operand(w10, SXTW)); | 464 __ Add(capture_start_address, input_end(), Operand(w10, SXTW)); |
| 438 __ Add(capture_end_address, | 465 __ Add(capture_end_address, |
| 439 capture_start_address, | 466 capture_start_address, |
| 440 Operand(capture_length, SXTW)); | 467 Operand(capture_length, SXTW)); |
| 441 __ Add(current_position_address, | 468 __ Add(current_position_address, |
| 442 input_end(), | 469 input_end(), |
| 443 Operand(current_input_offset(), SXTW)); | 470 Operand(current_input_offset(), SXTW)); |
| 471 if (read_backward) { |
| 472 // Offset by length when matching backwards. |
| 473 __ Sub(current_position_address, current_position_address, |
| 474 Operand(capture_length, SXTW)); |
| 475 } |
| 444 | 476 |
| 445 Label loop; | 477 Label loop; |
| 446 __ Bind(&loop); | 478 __ Bind(&loop); |
| 447 if (mode_ == LATIN1) { | 479 if (mode_ == LATIN1) { |
| 448 __ Ldrb(w10, MemOperand(capture_start_address, 1, PostIndex)); | 480 __ Ldrb(w10, MemOperand(capture_start_address, 1, PostIndex)); |
| 449 __ Ldrb(w11, MemOperand(current_position_address, 1, PostIndex)); | 481 __ Ldrb(w11, MemOperand(current_position_address, 1, PostIndex)); |
| 450 } else { | 482 } else { |
| 451 DCHECK(mode_ == UC16); | 483 DCHECK(mode_ == UC16); |
| 452 __ Ldrh(w10, MemOperand(capture_start_address, 2, PostIndex)); | 484 __ Ldrh(w10, MemOperand(capture_start_address, 2, PostIndex)); |
| 453 __ Ldrh(w11, MemOperand(current_position_address, 2, PostIndex)); | 485 __ Ldrh(w11, MemOperand(current_position_address, 2, PostIndex)); |
| 454 } | 486 } |
| 455 __ Cmp(w10, w11); | 487 __ Cmp(w10, w11); |
| 456 BranchOrBacktrack(ne, on_no_match); | 488 BranchOrBacktrack(ne, on_no_match); |
| 457 __ Cmp(capture_start_address, capture_end_address); | 489 __ Cmp(capture_start_address, capture_end_address); |
| 458 __ B(lt, &loop); | 490 __ B(lt, &loop); |
| 459 | 491 |
| 460 // Move current character position to position after match. | 492 // Move current character position to position after match. |
| 461 __ Sub(current_input_offset().X(), current_position_address, input_end()); | 493 __ Sub(current_input_offset().X(), current_position_address, input_end()); |
| 494 if (read_backward) { |
| 495 __ Sub(current_input_offset(), current_input_offset(), |
| 496 Operand(capture_length, SXTW)); |
| 497 } |
| 498 |
| 462 if (masm_->emit_debug_code()) { | 499 if (masm_->emit_debug_code()) { |
| 463 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); | 500 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); |
| 464 __ Ccmp(current_input_offset(), 0, NoFlag, eq); | 501 __ Ccmp(current_input_offset(), 0, NoFlag, eq); |
| 465 // The current input offset should be <= 0, and fit in a W register. | 502 // The current input offset should be <= 0, and fit in a W register. |
| 466 __ Check(le, kOffsetOutOfRange); | 503 __ Check(le, kOffsetOutOfRange); |
| 467 } | 504 } |
| 468 __ Bind(&fallthrough); | 505 __ Bind(&fallthrough); |
| 469 } | 506 } |
| 470 | 507 |
| 471 | 508 |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 751 // Check that the input string length is < 2^30. | 788 // Check that the input string length is < 2^30. |
| 752 __ Neg(x11, x10); | 789 __ Neg(x11, x10); |
| 753 __ Cmp(x11, (1<<30) - 1); | 790 __ Cmp(x11, (1<<30) - 1); |
| 754 __ Check(ls, kInputStringTooLong); | 791 __ Check(ls, kInputStringTooLong); |
| 755 } | 792 } |
| 756 __ Mov(current_input_offset(), w10); | 793 __ Mov(current_input_offset(), w10); |
| 757 | 794 |
| 758 // The non-position value is used as a clearing value for the | 795 // The non-position value is used as a clearing value for the |
| 759 // capture registers, it corresponds to the position of the first character | 796 // capture registers, it corresponds to the position of the first character |
| 760 // minus one. | 797 // minus one. |
| 761 __ Sub(non_position_value(), current_input_offset(), char_size()); | 798 __ Sub(string_start_minus_one(), current_input_offset(), char_size()); |
| 762 __ Sub(non_position_value(), non_position_value(), | 799 __ Sub(string_start_minus_one(), string_start_minus_one(), |
| 763 Operand(start_offset(), LSL, (mode_ == UC16) ? 1 : 0)); | 800 Operand(start_offset(), LSL, (mode_ == UC16) ? 1 : 0)); |
| 764 // We can store this value twice in an X register for initializing | 801 // We can store this value twice in an X register for initializing |
| 765 // on-stack registers later. | 802 // on-stack registers later. |
| 766 __ Orr(twice_non_position_value(), | 803 __ Orr(twice_non_position_value(), string_start_minus_one().X(), |
| 767 non_position_value().X(), | 804 Operand(string_start_minus_one().X(), LSL, kWRegSizeInBits)); |
| 768 Operand(non_position_value().X(), LSL, kWRegSizeInBits)); | |
| 769 | 805 |
| 770 // Initialize code pointer register. | 806 // Initialize code pointer register. |
| 771 __ Mov(code_pointer(), Operand(masm_->CodeObject())); | 807 __ Mov(code_pointer(), Operand(masm_->CodeObject())); |
| 772 | 808 |
| 773 Label load_char_start_regexp, start_regexp; | 809 Label load_char_start_regexp, start_regexp; |
| 774 // Load newline if index is at start, previous character otherwise. | 810 // Load newline if index is at start, previous character otherwise. |
| 775 __ Cbnz(start_offset(), &load_char_start_regexp); | 811 __ Cbnz(start_offset(), &load_char_start_regexp); |
| 776 __ Mov(current_character(), '\n'); | 812 __ Mov(current_character(), '\n'); |
| 777 __ B(&start_regexp); | 813 __ B(&start_regexp); |
| 778 | 814 |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1074 return kARM64Implementation; | 1110 return kARM64Implementation; |
| 1075 } | 1111 } |
| 1076 | 1112 |
| 1077 | 1113 |
| 1078 void RegExpMacroAssemblerARM64::LoadCurrentCharacter(int cp_offset, | 1114 void RegExpMacroAssemblerARM64::LoadCurrentCharacter(int cp_offset, |
| 1079 Label* on_end_of_input, | 1115 Label* on_end_of_input, |
| 1080 bool check_bounds, | 1116 bool check_bounds, |
| 1081 int characters) { | 1117 int characters) { |
| 1082 // TODO(pielan): Make sure long strings are caught before this, and not | 1118 // TODO(pielan): Make sure long strings are caught before this, and not |
| 1083 // just asserted in debug mode. | 1119 // 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) | 1120 // Be sane! (And ensure that an int32_t can be used to index the string) |
| 1086 DCHECK(cp_offset < (1<<30)); | 1121 DCHECK(cp_offset < (1<<30)); |
| 1087 if (check_bounds) { | 1122 if (check_bounds) { |
| 1088 CheckPosition(cp_offset + characters - 1, on_end_of_input); | 1123 if (cp_offset >= 0) { |
| 1124 CheckPosition(cp_offset + characters - 1, on_end_of_input); |
| 1125 } else { |
| 1126 CheckPosition(cp_offset, on_end_of_input); |
| 1127 } |
| 1089 } | 1128 } |
| 1090 LoadCurrentCharacterUnchecked(cp_offset, characters); | 1129 LoadCurrentCharacterUnchecked(cp_offset, characters); |
| 1091 } | 1130 } |
| 1092 | 1131 |
| 1093 | 1132 |
| 1094 void RegExpMacroAssemblerARM64::PopCurrentPosition() { | 1133 void RegExpMacroAssemblerARM64::PopCurrentPosition() { |
| 1095 Pop(current_input_offset()); | 1134 Pop(current_input_offset()); |
| 1096 } | 1135 } |
| 1097 | 1136 |
| 1098 | 1137 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 } | 1242 } |
| 1204 | 1243 |
| 1205 | 1244 |
| 1206 void RegExpMacroAssemblerARM64::ClearRegisters(int reg_from, int reg_to) { | 1245 void RegExpMacroAssemblerARM64::ClearRegisters(int reg_from, int reg_to) { |
| 1207 DCHECK(reg_from <= reg_to); | 1246 DCHECK(reg_from <= reg_to); |
| 1208 int num_registers = reg_to - reg_from + 1; | 1247 int num_registers = reg_to - reg_from + 1; |
| 1209 | 1248 |
| 1210 // If the first capture register is cached in a hardware register but not | 1249 // 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. | 1250 // aligned on a 64-bit one, we need to clear the first one specifically. |
| 1212 if ((reg_from < kNumCachedRegisters) && ((reg_from % 2) != 0)) { | 1251 if ((reg_from < kNumCachedRegisters) && ((reg_from % 2) != 0)) { |
| 1213 StoreRegister(reg_from, non_position_value()); | 1252 StoreRegister(reg_from, string_start_minus_one()); |
| 1214 num_registers--; | 1253 num_registers--; |
| 1215 reg_from++; | 1254 reg_from++; |
| 1216 } | 1255 } |
| 1217 | 1256 |
| 1218 // Clear cached registers in pairs as far as possible. | 1257 // Clear cached registers in pairs as far as possible. |
| 1219 while ((num_registers >= 2) && (reg_from < kNumCachedRegisters)) { | 1258 while ((num_registers >= 2) && (reg_from < kNumCachedRegisters)) { |
| 1220 DCHECK(GetRegisterState(reg_from) == CACHED_LSW); | 1259 DCHECK(GetRegisterState(reg_from) == CACHED_LSW); |
| 1221 __ Mov(GetCachedRegister(reg_from), twice_non_position_value()); | 1260 __ Mov(GetCachedRegister(reg_from), twice_non_position_value()); |
| 1222 reg_from += 2; | 1261 reg_from += 2; |
| 1223 num_registers -= 2; | 1262 num_registers -= 2; |
| 1224 } | 1263 } |
| 1225 | 1264 |
| 1226 if ((num_registers % 2) == 1) { | 1265 if ((num_registers % 2) == 1) { |
| 1227 StoreRegister(reg_from, non_position_value()); | 1266 StoreRegister(reg_from, string_start_minus_one()); |
| 1228 num_registers--; | 1267 num_registers--; |
| 1229 reg_from++; | 1268 reg_from++; |
| 1230 } | 1269 } |
| 1231 | 1270 |
| 1232 if (num_registers > 0) { | 1271 if (num_registers > 0) { |
| 1233 // If there are some remaining registers, they are stored on the stack. | 1272 // If there are some remaining registers, they are stored on the stack. |
| 1234 DCHECK(reg_from >= kNumCachedRegisters); | 1273 DCHECK(reg_from >= kNumCachedRegisters); |
| 1235 | 1274 |
| 1236 // Move down the indexes of the registers on stack to get the correct offset | 1275 // Move down the indexes of the registers on stack to get the correct offset |
| 1237 // in memory. | 1276 // in memory. |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1294 const byte** input_start, const byte** input_end) { | 1333 const byte** input_start, const byte** input_end) { |
| 1295 return NativeRegExpMacroAssembler::CheckStackGuardState( | 1334 return NativeRegExpMacroAssembler::CheckStackGuardState( |
| 1296 frame_entry<Isolate*>(re_frame, kIsolate), start_index, | 1335 frame_entry<Isolate*>(re_frame, kIsolate), start_index, |
| 1297 frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code, | 1336 frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code, |
| 1298 frame_entry_address<String*>(re_frame, kInput), input_start, input_end); | 1337 frame_entry_address<String*>(re_frame, kInput), input_start, input_end); |
| 1299 } | 1338 } |
| 1300 | 1339 |
| 1301 | 1340 |
| 1302 void RegExpMacroAssemblerARM64::CheckPosition(int cp_offset, | 1341 void RegExpMacroAssemblerARM64::CheckPosition(int cp_offset, |
| 1303 Label* on_outside_input) { | 1342 Label* on_outside_input) { |
| 1304 CompareAndBranchOrBacktrack(current_input_offset(), | 1343 if (cp_offset >= 0) { |
| 1305 -cp_offset * char_size(), | 1344 CompareAndBranchOrBacktrack(current_input_offset(), |
| 1306 ge, | 1345 -cp_offset * char_size(), ge, on_outside_input); |
| 1307 on_outside_input); | 1346 } else { |
| 1347 __ Add(w12, current_input_offset(), Operand(cp_offset * char_size())); |
| 1348 __ Cmp(w12, string_start_minus_one()); |
| 1349 BranchOrBacktrack(le, on_outside_input); |
| 1350 } |
| 1308 } | 1351 } |
| 1309 | 1352 |
| 1310 | 1353 |
| 1311 bool RegExpMacroAssemblerARM64::CanReadUnaligned() { | 1354 bool RegExpMacroAssemblerARM64::CanReadUnaligned() { |
| 1312 // TODO(pielan): See whether or not we should disable unaligned accesses. | 1355 // TODO(pielan): See whether or not we should disable unaligned accesses. |
| 1313 return !slow_safe(); | 1356 return !slow_safe(); |
| 1314 } | 1357 } |
| 1315 | 1358 |
| 1316 | 1359 |
| 1317 // Private methods: | 1360 // Private methods: |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1606 } | 1649 } |
| 1607 } | 1650 } |
| 1608 } | 1651 } |
| 1609 | 1652 |
| 1610 #endif // V8_INTERPRETED_REGEXP | 1653 #endif // V8_INTERPRETED_REGEXP |
| 1611 | 1654 |
| 1612 } // namespace internal | 1655 } // namespace internal |
| 1613 } // namespace v8 | 1656 } // namespace v8 |
| 1614 | 1657 |
| 1615 #endif // V8_TARGET_ARCH_ARM64 | 1658 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |