| 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 |