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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/cpu-profiler.h" | 10 #include "src/cpu-profiler.h" |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 masm_(new MacroAssembler(zone->isolate(), NULL, kRegExpCodeSize)), | 119 masm_(new MacroAssembler(zone->isolate(), NULL, kRegExpCodeSize)), |
120 mode_(mode), | 120 mode_(mode), |
121 num_registers_(registers_to_save), | 121 num_registers_(registers_to_save), |
122 num_saved_registers_(registers_to_save), | 122 num_saved_registers_(registers_to_save), |
123 entry_label_(), | 123 entry_label_(), |
124 start_label_(), | 124 start_label_(), |
125 success_label_(), | 125 success_label_(), |
126 backtrack_label_(), | 126 backtrack_label_(), |
127 exit_label_() { | 127 exit_label_() { |
128 __ SetStackPointer(csp); | 128 __ SetStackPointer(csp); |
129 ASSERT_EQ(0, registers_to_save % 2); | 129 DCHECK_EQ(0, registers_to_save % 2); |
130 // We can cache at most 16 W registers in x0-x7. | 130 // We can cache at most 16 W registers in x0-x7. |
131 STATIC_ASSERT(kNumCachedRegisters <= 16); | 131 STATIC_ASSERT(kNumCachedRegisters <= 16); |
132 STATIC_ASSERT((kNumCachedRegisters % 2) == 0); | 132 STATIC_ASSERT((kNumCachedRegisters % 2) == 0); |
133 __ B(&entry_label_); // We'll write the entry code later. | 133 __ B(&entry_label_); // We'll write the entry code later. |
134 __ Bind(&start_label_); // And then continue from here. | 134 __ Bind(&start_label_); // And then continue from here. |
135 } | 135 } |
136 | 136 |
137 | 137 |
138 RegExpMacroAssemblerARM64::~RegExpMacroAssemblerARM64() { | 138 RegExpMacroAssemblerARM64::~RegExpMacroAssemblerARM64() { |
139 delete masm_; | 139 delete masm_; |
(...skipping 14 matching lines...) Expand all Loading... |
154 | 154 |
155 void RegExpMacroAssemblerARM64::AdvanceCurrentPosition(int by) { | 155 void RegExpMacroAssemblerARM64::AdvanceCurrentPosition(int by) { |
156 if (by != 0) { | 156 if (by != 0) { |
157 __ Add(current_input_offset(), | 157 __ Add(current_input_offset(), |
158 current_input_offset(), by * char_size()); | 158 current_input_offset(), by * char_size()); |
159 } | 159 } |
160 } | 160 } |
161 | 161 |
162 | 162 |
163 void RegExpMacroAssemblerARM64::AdvanceRegister(int reg, int by) { | 163 void RegExpMacroAssemblerARM64::AdvanceRegister(int reg, int by) { |
164 ASSERT((reg >= 0) && (reg < num_registers_)); | 164 DCHECK((reg >= 0) && (reg < num_registers_)); |
165 if (by != 0) { | 165 if (by != 0) { |
166 Register to_advance; | 166 Register to_advance; |
167 RegisterState register_state = GetRegisterState(reg); | 167 RegisterState register_state = GetRegisterState(reg); |
168 switch (register_state) { | 168 switch (register_state) { |
169 case STACKED: | 169 case STACKED: |
170 __ Ldr(w10, register_location(reg)); | 170 __ Ldr(w10, register_location(reg)); |
171 __ Add(w10, w10, by); | 171 __ Add(w10, w10, by); |
172 __ Str(w10, register_location(reg)); | 172 __ Str(w10, register_location(reg)); |
173 break; | 173 break; |
174 case CACHED_LSW: | 174 case CACHED_LSW: |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 __ Add(characters_address, | 255 __ Add(characters_address, |
256 input_end(), | 256 input_end(), |
257 Operand(current_input_offset(), SXTW)); | 257 Operand(current_input_offset(), SXTW)); |
258 if (cp_offset != 0) { | 258 if (cp_offset != 0) { |
259 __ Add(characters_address, characters_address, cp_offset * char_size()); | 259 __ Add(characters_address, characters_address, cp_offset * char_size()); |
260 } | 260 } |
261 | 261 |
262 for (int i = 0; i < str.length(); i++) { | 262 for (int i = 0; i < str.length(); i++) { |
263 if (mode_ == ASCII) { | 263 if (mode_ == ASCII) { |
264 __ Ldrb(w10, MemOperand(characters_address, 1, PostIndex)); | 264 __ Ldrb(w10, MemOperand(characters_address, 1, PostIndex)); |
265 ASSERT(str[i] <= String::kMaxOneByteCharCode); | 265 DCHECK(str[i] <= String::kMaxOneByteCharCode); |
266 } else { | 266 } else { |
267 __ Ldrh(w10, MemOperand(characters_address, 2, PostIndex)); | 267 __ Ldrh(w10, MemOperand(characters_address, 2, PostIndex)); |
268 } | 268 } |
269 CompareAndBranchOrBacktrack(w10, str[i], ne, on_failure); | 269 CompareAndBranchOrBacktrack(w10, str[i], ne, on_failure); |
270 } | 270 } |
271 } | 271 } |
272 | 272 |
273 | 273 |
274 void RegExpMacroAssemblerARM64::CheckGreedyLoop(Label* on_equal) { | 274 void RegExpMacroAssemblerARM64::CheckGreedyLoop(Label* on_equal) { |
275 __ Ldr(w10, MemOperand(backtrack_stackpointer())); | 275 __ Ldr(w10, MemOperand(backtrack_stackpointer())); |
276 __ Cmp(current_input_offset(), w10); | 276 __ Cmp(current_input_offset(), w10); |
277 __ Cset(x11, eq); | 277 __ Cset(x11, eq); |
278 __ Add(backtrack_stackpointer(), | 278 __ Add(backtrack_stackpointer(), |
279 backtrack_stackpointer(), Operand(x11, LSL, kWRegSizeLog2)); | 279 backtrack_stackpointer(), Operand(x11, LSL, kWRegSizeLog2)); |
280 BranchOrBacktrack(eq, on_equal); | 280 BranchOrBacktrack(eq, on_equal); |
281 } | 281 } |
282 | 282 |
283 void RegExpMacroAssemblerARM64::CheckNotBackReferenceIgnoreCase( | 283 void RegExpMacroAssemblerARM64::CheckNotBackReferenceIgnoreCase( |
284 int start_reg, | 284 int start_reg, |
285 Label* on_no_match) { | 285 Label* on_no_match) { |
286 Label fallthrough; | 286 Label fallthrough; |
287 | 287 |
288 Register capture_start_offset = w10; | 288 Register capture_start_offset = w10; |
289 // Save the capture length in a callee-saved register so it will | 289 // Save the capture length in a callee-saved register so it will |
290 // be preserved if we call a C helper. | 290 // be preserved if we call a C helper. |
291 Register capture_length = w19; | 291 Register capture_length = w19; |
292 ASSERT(kCalleeSaved.IncludesAliasOf(capture_length)); | 292 DCHECK(kCalleeSaved.IncludesAliasOf(capture_length)); |
293 | 293 |
294 // Find length of back-referenced capture. | 294 // Find length of back-referenced capture. |
295 ASSERT((start_reg % 2) == 0); | 295 DCHECK((start_reg % 2) == 0); |
296 if (start_reg < kNumCachedRegisters) { | 296 if (start_reg < kNumCachedRegisters) { |
297 __ Mov(capture_start_offset.X(), GetCachedRegister(start_reg)); | 297 __ Mov(capture_start_offset.X(), GetCachedRegister(start_reg)); |
298 __ Lsr(x11, GetCachedRegister(start_reg), kWRegSizeInBits); | 298 __ Lsr(x11, GetCachedRegister(start_reg), kWRegSizeInBits); |
299 } else { | 299 } else { |
300 __ Ldp(w11, capture_start_offset, capture_location(start_reg, x10)); | 300 __ Ldp(w11, capture_start_offset, capture_location(start_reg, x10)); |
301 } | 301 } |
302 __ Sub(capture_length, w11, capture_start_offset); // Length to check. | 302 __ Sub(capture_length, w11, capture_start_offset); // Length to check. |
303 // Succeed on empty capture (including no capture). | 303 // Succeed on empty capture (including no capture). |
304 __ Cbz(capture_length, &fallthrough); | 304 __ Cbz(capture_length, &fallthrough); |
305 | 305 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 __ Bind(&success); | 358 __ Bind(&success); |
359 // Compute new value of character position after the matched part. | 359 // Compute new value of character position after the matched part. |
360 __ Sub(current_input_offset().X(), current_position_address, input_end()); | 360 __ Sub(current_input_offset().X(), current_position_address, input_end()); |
361 if (masm_->emit_debug_code()) { | 361 if (masm_->emit_debug_code()) { |
362 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); | 362 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); |
363 __ Ccmp(current_input_offset(), 0, NoFlag, eq); | 363 __ Ccmp(current_input_offset(), 0, NoFlag, eq); |
364 // The current input offset should be <= 0, and fit in a W register. | 364 // The current input offset should be <= 0, and fit in a W register. |
365 __ Check(le, kOffsetOutOfRange); | 365 __ Check(le, kOffsetOutOfRange); |
366 } | 366 } |
367 } else { | 367 } else { |
368 ASSERT(mode_ == UC16); | 368 DCHECK(mode_ == UC16); |
369 int argument_count = 4; | 369 int argument_count = 4; |
370 | 370 |
371 // The cached registers need to be retained. | 371 // The cached registers need to be retained. |
372 CPURegList cached_registers(CPURegister::kRegister, kXRegSizeInBits, 0, 7); | 372 CPURegList cached_registers(CPURegister::kRegister, kXRegSizeInBits, 0, 7); |
373 ASSERT((cached_registers.Count() * 2) == kNumCachedRegisters); | 373 DCHECK((cached_registers.Count() * 2) == kNumCachedRegisters); |
374 __ PushCPURegList(cached_registers); | 374 __ PushCPURegList(cached_registers); |
375 | 375 |
376 // Put arguments into arguments registers. | 376 // Put arguments into arguments registers. |
377 // Parameters are | 377 // Parameters are |
378 // x0: Address byte_offset1 - Address captured substring's start. | 378 // x0: Address byte_offset1 - Address captured substring's start. |
379 // x1: Address byte_offset2 - Address of current character position. | 379 // x1: Address byte_offset2 - Address of current character position. |
380 // w2: size_t byte_length - length of capture in bytes(!) | 380 // w2: size_t byte_length - length of capture in bytes(!) |
381 // x3: Isolate* isolate | 381 // x3: Isolate* isolate |
382 | 382 |
383 // Address of start of capture. | 383 // Address of start of capture. |
(...skipping 30 matching lines...) Expand all Loading... |
414 int start_reg, | 414 int start_reg, |
415 Label* on_no_match) { | 415 Label* on_no_match) { |
416 Label fallthrough; | 416 Label fallthrough; |
417 | 417 |
418 Register capture_start_address = x12; | 418 Register capture_start_address = x12; |
419 Register capture_end_address = x13; | 419 Register capture_end_address = x13; |
420 Register current_position_address = x14; | 420 Register current_position_address = x14; |
421 Register capture_length = w15; | 421 Register capture_length = w15; |
422 | 422 |
423 // Find length of back-referenced capture. | 423 // Find length of back-referenced capture. |
424 ASSERT((start_reg % 2) == 0); | 424 DCHECK((start_reg % 2) == 0); |
425 if (start_reg < kNumCachedRegisters) { | 425 if (start_reg < kNumCachedRegisters) { |
426 __ Mov(x10, GetCachedRegister(start_reg)); | 426 __ Mov(x10, GetCachedRegister(start_reg)); |
427 __ Lsr(x11, GetCachedRegister(start_reg), kWRegSizeInBits); | 427 __ Lsr(x11, GetCachedRegister(start_reg), kWRegSizeInBits); |
428 } else { | 428 } else { |
429 __ Ldp(w11, w10, capture_location(start_reg, x10)); | 429 __ Ldp(w11, w10, capture_location(start_reg, x10)); |
430 } | 430 } |
431 __ Sub(capture_length, w11, w10); // Length to check. | 431 __ Sub(capture_length, w11, w10); // Length to check. |
432 // Succeed on empty capture (including no capture). | 432 // Succeed on empty capture (including no capture). |
433 __ Cbz(capture_length, &fallthrough); | 433 __ Cbz(capture_length, &fallthrough); |
434 | 434 |
435 // Check that there are enough characters left in the input. | 435 // Check that there are enough characters left in the input. |
436 __ Cmn(capture_length, current_input_offset()); | 436 __ Cmn(capture_length, current_input_offset()); |
437 BranchOrBacktrack(gt, on_no_match); | 437 BranchOrBacktrack(gt, on_no_match); |
438 | 438 |
439 // Compute pointers to match string and capture string | 439 // Compute pointers to match string and capture string |
440 __ Add(capture_start_address, input_end(), Operand(w10, SXTW)); | 440 __ Add(capture_start_address, input_end(), Operand(w10, SXTW)); |
441 __ Add(capture_end_address, | 441 __ Add(capture_end_address, |
442 capture_start_address, | 442 capture_start_address, |
443 Operand(capture_length, SXTW)); | 443 Operand(capture_length, SXTW)); |
444 __ Add(current_position_address, | 444 __ Add(current_position_address, |
445 input_end(), | 445 input_end(), |
446 Operand(current_input_offset(), SXTW)); | 446 Operand(current_input_offset(), SXTW)); |
447 | 447 |
448 Label loop; | 448 Label loop; |
449 __ Bind(&loop); | 449 __ Bind(&loop); |
450 if (mode_ == ASCII) { | 450 if (mode_ == ASCII) { |
451 __ Ldrb(w10, MemOperand(capture_start_address, 1, PostIndex)); | 451 __ Ldrb(w10, MemOperand(capture_start_address, 1, PostIndex)); |
452 __ Ldrb(w11, MemOperand(current_position_address, 1, PostIndex)); | 452 __ Ldrb(w11, MemOperand(current_position_address, 1, PostIndex)); |
453 } else { | 453 } else { |
454 ASSERT(mode_ == UC16); | 454 DCHECK(mode_ == UC16); |
455 __ Ldrh(w10, MemOperand(capture_start_address, 2, PostIndex)); | 455 __ Ldrh(w10, MemOperand(capture_start_address, 2, PostIndex)); |
456 __ Ldrh(w11, MemOperand(current_position_address, 2, PostIndex)); | 456 __ Ldrh(w11, MemOperand(current_position_address, 2, PostIndex)); |
457 } | 457 } |
458 __ Cmp(w10, w11); | 458 __ Cmp(w10, w11); |
459 BranchOrBacktrack(ne, on_no_match); | 459 BranchOrBacktrack(ne, on_no_match); |
460 __ Cmp(capture_start_address, capture_end_address); | 460 __ Cmp(capture_start_address, capture_end_address); |
461 __ B(lt, &loop); | 461 __ B(lt, &loop); |
462 | 462 |
463 // Move current character position to position after match. | 463 // Move current character position to position after match. |
464 __ Sub(current_input_offset().X(), current_position_address, input_end()); | 464 __ Sub(current_input_offset().X(), current_position_address, input_end()); |
(...skipping 27 matching lines...) Expand all Loading... |
492 __ And(w10, current_character(), mask); | 492 __ And(w10, current_character(), mask); |
493 CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal); | 493 CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal); |
494 } | 494 } |
495 | 495 |
496 | 496 |
497 void RegExpMacroAssemblerARM64::CheckNotCharacterAfterMinusAnd( | 497 void RegExpMacroAssemblerARM64::CheckNotCharacterAfterMinusAnd( |
498 uc16 c, | 498 uc16 c, |
499 uc16 minus, | 499 uc16 minus, |
500 uc16 mask, | 500 uc16 mask, |
501 Label* on_not_equal) { | 501 Label* on_not_equal) { |
502 ASSERT(minus < String::kMaxUtf16CodeUnit); | 502 DCHECK(minus < String::kMaxUtf16CodeUnit); |
503 __ Sub(w10, current_character(), minus); | 503 __ Sub(w10, current_character(), minus); |
504 __ And(w10, w10, mask); | 504 __ And(w10, w10, mask); |
505 CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal); | 505 CompareAndBranchOrBacktrack(w10, c, ne, on_not_equal); |
506 } | 506 } |
507 | 507 |
508 | 508 |
509 void RegExpMacroAssemblerARM64::CheckCharacterInRange( | 509 void RegExpMacroAssemblerARM64::CheckCharacterInRange( |
510 uc16 from, | 510 uc16 from, |
511 uc16 to, | 511 uc16 to, |
512 Label* on_in_range) { | 512 Label* on_in_range) { |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 // csp[0]: secondary link/return address used by native call | 674 // csp[0]: secondary link/return address used by native call |
675 | 675 |
676 // Tell the system that we have a stack frame. Because the type is MANUAL, no | 676 // Tell the system that we have a stack frame. Because the type is MANUAL, no |
677 // code is generated. | 677 // code is generated. |
678 FrameScope scope(masm_, StackFrame::MANUAL); | 678 FrameScope scope(masm_, StackFrame::MANUAL); |
679 | 679 |
680 // Push registers on the stack, only push the argument registers that we need. | 680 // Push registers on the stack, only push the argument registers that we need. |
681 CPURegList argument_registers(x0, x5, x6, x7); | 681 CPURegList argument_registers(x0, x5, x6, x7); |
682 | 682 |
683 CPURegList registers_to_retain = kCalleeSaved; | 683 CPURegList registers_to_retain = kCalleeSaved; |
684 ASSERT(kCalleeSaved.Count() == 11); | 684 DCHECK(kCalleeSaved.Count() == 11); |
685 registers_to_retain.Combine(lr); | 685 registers_to_retain.Combine(lr); |
686 | 686 |
687 ASSERT(csp.Is(__ StackPointer())); | 687 DCHECK(csp.Is(__ StackPointer())); |
688 __ PushCPURegList(registers_to_retain); | 688 __ PushCPURegList(registers_to_retain); |
689 __ PushCPURegList(argument_registers); | 689 __ PushCPURegList(argument_registers); |
690 | 690 |
691 // Set frame pointer in place. | 691 // Set frame pointer in place. |
692 __ Add(frame_pointer(), csp, argument_registers.Count() * kPointerSize); | 692 __ Add(frame_pointer(), csp, argument_registers.Count() * kPointerSize); |
693 | 693 |
694 // Initialize callee-saved registers. | 694 // Initialize callee-saved registers. |
695 __ Mov(start_offset(), w1); | 695 __ Mov(start_offset(), w1); |
696 __ Mov(input_start(), x2); | 696 __ Mov(input_start(), x2); |
697 __ Mov(input_end(), x3); | 697 __ Mov(input_end(), x3); |
698 __ Mov(output_array(), x4); | 698 __ Mov(output_array(), x4); |
699 | 699 |
700 // Set the number of registers we will need to allocate, that is: | 700 // Set the number of registers we will need to allocate, that is: |
701 // - success_counter (X register) | 701 // - success_counter (X register) |
702 // - (num_registers_ - kNumCachedRegisters) (W registers) | 702 // - (num_registers_ - kNumCachedRegisters) (W registers) |
703 int num_wreg_to_allocate = num_registers_ - kNumCachedRegisters; | 703 int num_wreg_to_allocate = num_registers_ - kNumCachedRegisters; |
704 // Do not allocate registers on the stack if they can all be cached. | 704 // Do not allocate registers on the stack if they can all be cached. |
705 if (num_wreg_to_allocate < 0) { num_wreg_to_allocate = 0; } | 705 if (num_wreg_to_allocate < 0) { num_wreg_to_allocate = 0; } |
706 // Make room for the success_counter. | 706 // Make room for the success_counter. |
707 num_wreg_to_allocate += 2; | 707 num_wreg_to_allocate += 2; |
708 | 708 |
709 // Make sure the stack alignment will be respected. | 709 // Make sure the stack alignment will be respected. |
710 int alignment = masm_->ActivationFrameAlignment(); | 710 int alignment = masm_->ActivationFrameAlignment(); |
711 ASSERT_EQ(alignment % 16, 0); | 711 DCHECK_EQ(alignment % 16, 0); |
712 int align_mask = (alignment / kWRegSize) - 1; | 712 int align_mask = (alignment / kWRegSize) - 1; |
713 num_wreg_to_allocate = (num_wreg_to_allocate + align_mask) & ~align_mask; | 713 num_wreg_to_allocate = (num_wreg_to_allocate + align_mask) & ~align_mask; |
714 | 714 |
715 // Check if we have space on the stack. | 715 // Check if we have space on the stack. |
716 Label stack_limit_hit; | 716 Label stack_limit_hit; |
717 Label stack_ok; | 717 Label stack_ok; |
718 | 718 |
719 ExternalReference stack_limit = | 719 ExternalReference stack_limit = |
720 ExternalReference::address_of_stack_limit(isolate()); | 720 ExternalReference::address_of_stack_limit(isolate()); |
721 __ Mov(x10, stack_limit); | 721 __ Mov(x10, stack_limit); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
854 } | 854 } |
855 | 855 |
856 // Only carry on if there are more than kNumCachedRegisters capture | 856 // Only carry on if there are more than kNumCachedRegisters capture |
857 // registers. | 857 // registers. |
858 int num_registers_left_on_stack = | 858 int num_registers_left_on_stack = |
859 num_saved_registers_ - kNumCachedRegisters; | 859 num_saved_registers_ - kNumCachedRegisters; |
860 if (num_registers_left_on_stack > 0) { | 860 if (num_registers_left_on_stack > 0) { |
861 Register base = x10; | 861 Register base = x10; |
862 // There are always an even number of capture registers. A couple of | 862 // There are always an even number of capture registers. A couple of |
863 // registers determine one match with two offsets. | 863 // registers determine one match with two offsets. |
864 ASSERT_EQ(0, num_registers_left_on_stack % 2); | 864 DCHECK_EQ(0, num_registers_left_on_stack % 2); |
865 __ Add(base, frame_pointer(), kFirstCaptureOnStack); | 865 __ Add(base, frame_pointer(), kFirstCaptureOnStack); |
866 | 866 |
867 // We can unroll the loop here, we should not unroll for less than 2 | 867 // We can unroll the loop here, we should not unroll for less than 2 |
868 // registers. | 868 // registers. |
869 STATIC_ASSERT(kNumRegistersToUnroll > 2); | 869 STATIC_ASSERT(kNumRegistersToUnroll > 2); |
870 if (num_registers_left_on_stack <= kNumRegistersToUnroll) { | 870 if (num_registers_left_on_stack <= kNumRegistersToUnroll) { |
871 for (int i = 0; i < num_registers_left_on_stack / 2; i++) { | 871 for (int i = 0; i < num_registers_left_on_stack / 2; i++) { |
872 __ Ldp(capture_end, | 872 __ Ldp(capture_end, |
873 capture_start, | 873 capture_start, |
874 MemOperand(base, -kPointerSize, PostIndex)); | 874 MemOperand(base, -kPointerSize, PostIndex)); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
971 // Exit and return w0 | 971 // Exit and return w0 |
972 __ Bind(&exit_label_); | 972 __ Bind(&exit_label_); |
973 if (global()) { | 973 if (global()) { |
974 __ Ldr(w0, MemOperand(frame_pointer(), kSuccessCounter)); | 974 __ Ldr(w0, MemOperand(frame_pointer(), kSuccessCounter)); |
975 } | 975 } |
976 } | 976 } |
977 | 977 |
978 __ Bind(&return_w0); | 978 __ Bind(&return_w0); |
979 | 979 |
980 // Set stack pointer back to first register to retain | 980 // Set stack pointer back to first register to retain |
981 ASSERT(csp.Is(__ StackPointer())); | 981 DCHECK(csp.Is(__ StackPointer())); |
982 __ Mov(csp, fp); | 982 __ Mov(csp, fp); |
983 __ AssertStackConsistency(); | 983 __ AssertStackConsistency(); |
984 | 984 |
985 // Restore registers. | 985 // Restore registers. |
986 __ PopCPURegList(registers_to_retain); | 986 __ PopCPURegList(registers_to_retain); |
987 | 987 |
988 __ Ret(); | 988 __ Ret(); |
989 | 989 |
990 Label exit_with_exception; | 990 Label exit_with_exception; |
991 // Registers x0 to x7 are used to store the first captures, they need to be | 991 // Registers x0 to x7 are used to store the first captures, they need to be |
992 // retained over calls to C++ code. | 992 // retained over calls to C++ code. |
993 CPURegList cached_registers(CPURegister::kRegister, kXRegSizeInBits, 0, 7); | 993 CPURegList cached_registers(CPURegister::kRegister, kXRegSizeInBits, 0, 7); |
994 ASSERT((cached_registers.Count() * 2) == kNumCachedRegisters); | 994 DCHECK((cached_registers.Count() * 2) == kNumCachedRegisters); |
995 | 995 |
996 if (check_preempt_label_.is_linked()) { | 996 if (check_preempt_label_.is_linked()) { |
997 __ Bind(&check_preempt_label_); | 997 __ Bind(&check_preempt_label_); |
998 SaveLinkRegister(); | 998 SaveLinkRegister(); |
999 // The cached registers need to be retained. | 999 // The cached registers need to be retained. |
1000 __ PushCPURegList(cached_registers); | 1000 __ PushCPURegList(cached_registers); |
1001 CallCheckStackGuardState(x10); | 1001 CallCheckStackGuardState(x10); |
1002 // Returning from the regexp code restores the stack (csp <- fp) | 1002 // Returning from the regexp code restores the stack (csp <- fp) |
1003 // so we don't need to drop the link register from it before exiting. | 1003 // so we don't need to drop the link register from it before exiting. |
1004 __ Cbnz(w0, &return_w0); | 1004 __ Cbnz(w0, &return_w0); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1077 return kARM64Implementation; | 1077 return kARM64Implementation; |
1078 } | 1078 } |
1079 | 1079 |
1080 | 1080 |
1081 void RegExpMacroAssemblerARM64::LoadCurrentCharacter(int cp_offset, | 1081 void RegExpMacroAssemblerARM64::LoadCurrentCharacter(int cp_offset, |
1082 Label* on_end_of_input, | 1082 Label* on_end_of_input, |
1083 bool check_bounds, | 1083 bool check_bounds, |
1084 int characters) { | 1084 int characters) { |
1085 // TODO(pielan): Make sure long strings are caught before this, and not | 1085 // TODO(pielan): Make sure long strings are caught before this, and not |
1086 // just asserted in debug mode. | 1086 // just asserted in debug mode. |
1087 ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. | 1087 DCHECK(cp_offset >= -1); // ^ and \b can look behind one character. |
1088 // Be sane! (And ensure that an int32_t can be used to index the string) | 1088 // Be sane! (And ensure that an int32_t can be used to index the string) |
1089 ASSERT(cp_offset < (1<<30)); | 1089 DCHECK(cp_offset < (1<<30)); |
1090 if (check_bounds) { | 1090 if (check_bounds) { |
1091 CheckPosition(cp_offset + characters - 1, on_end_of_input); | 1091 CheckPosition(cp_offset + characters - 1, on_end_of_input); |
1092 } | 1092 } |
1093 LoadCurrentCharacterUnchecked(cp_offset, characters); | 1093 LoadCurrentCharacterUnchecked(cp_offset, characters); |
1094 } | 1094 } |
1095 | 1095 |
1096 | 1096 |
1097 void RegExpMacroAssemblerARM64::PopCurrentPosition() { | 1097 void RegExpMacroAssemblerARM64::PopCurrentPosition() { |
1098 Pop(current_input_offset()); | 1098 Pop(current_input_offset()); |
1099 } | 1099 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1172 __ Mov(current_input_offset(), -by * char_size()); | 1172 __ Mov(current_input_offset(), -by * char_size()); |
1173 // On RegExp code entry (where this operation is used), the character before | 1173 // On RegExp code entry (where this operation is used), the character before |
1174 // the current position is expected to be already loaded. | 1174 // the current position is expected to be already loaded. |
1175 // We have advanced the position, so it's safe to read backwards. | 1175 // We have advanced the position, so it's safe to read backwards. |
1176 LoadCurrentCharacterUnchecked(-1, 1); | 1176 LoadCurrentCharacterUnchecked(-1, 1); |
1177 __ Bind(&after_position); | 1177 __ Bind(&after_position); |
1178 } | 1178 } |
1179 | 1179 |
1180 | 1180 |
1181 void RegExpMacroAssemblerARM64::SetRegister(int register_index, int to) { | 1181 void RegExpMacroAssemblerARM64::SetRegister(int register_index, int to) { |
1182 ASSERT(register_index >= num_saved_registers_); // Reserved for positions! | 1182 DCHECK(register_index >= num_saved_registers_); // Reserved for positions! |
1183 Register set_to = wzr; | 1183 Register set_to = wzr; |
1184 if (to != 0) { | 1184 if (to != 0) { |
1185 set_to = w10; | 1185 set_to = w10; |
1186 __ Mov(set_to, to); | 1186 __ Mov(set_to, to); |
1187 } | 1187 } |
1188 StoreRegister(register_index, set_to); | 1188 StoreRegister(register_index, set_to); |
1189 } | 1189 } |
1190 | 1190 |
1191 | 1191 |
1192 bool RegExpMacroAssemblerARM64::Succeed() { | 1192 bool RegExpMacroAssemblerARM64::Succeed() { |
1193 __ B(&success_label_); | 1193 __ B(&success_label_); |
1194 return global(); | 1194 return global(); |
1195 } | 1195 } |
1196 | 1196 |
1197 | 1197 |
1198 void RegExpMacroAssemblerARM64::WriteCurrentPositionToRegister(int reg, | 1198 void RegExpMacroAssemblerARM64::WriteCurrentPositionToRegister(int reg, |
1199 int cp_offset) { | 1199 int cp_offset) { |
1200 Register position = current_input_offset(); | 1200 Register position = current_input_offset(); |
1201 if (cp_offset != 0) { | 1201 if (cp_offset != 0) { |
1202 position = w10; | 1202 position = w10; |
1203 __ Add(position, current_input_offset(), cp_offset * char_size()); | 1203 __ Add(position, current_input_offset(), cp_offset * char_size()); |
1204 } | 1204 } |
1205 StoreRegister(reg, position); | 1205 StoreRegister(reg, position); |
1206 } | 1206 } |
1207 | 1207 |
1208 | 1208 |
1209 void RegExpMacroAssemblerARM64::ClearRegisters(int reg_from, int reg_to) { | 1209 void RegExpMacroAssemblerARM64::ClearRegisters(int reg_from, int reg_to) { |
1210 ASSERT(reg_from <= reg_to); | 1210 DCHECK(reg_from <= reg_to); |
1211 int num_registers = reg_to - reg_from + 1; | 1211 int num_registers = reg_to - reg_from + 1; |
1212 | 1212 |
1213 // If the first capture register is cached in a hardware register but not | 1213 // If the first capture register is cached in a hardware register but not |
1214 // aligned on a 64-bit one, we need to clear the first one specifically. | 1214 // aligned on a 64-bit one, we need to clear the first one specifically. |
1215 if ((reg_from < kNumCachedRegisters) && ((reg_from % 2) != 0)) { | 1215 if ((reg_from < kNumCachedRegisters) && ((reg_from % 2) != 0)) { |
1216 StoreRegister(reg_from, non_position_value()); | 1216 StoreRegister(reg_from, non_position_value()); |
1217 num_registers--; | 1217 num_registers--; |
1218 reg_from++; | 1218 reg_from++; |
1219 } | 1219 } |
1220 | 1220 |
1221 // Clear cached registers in pairs as far as possible. | 1221 // Clear cached registers in pairs as far as possible. |
1222 while ((num_registers >= 2) && (reg_from < kNumCachedRegisters)) { | 1222 while ((num_registers >= 2) && (reg_from < kNumCachedRegisters)) { |
1223 ASSERT(GetRegisterState(reg_from) == CACHED_LSW); | 1223 DCHECK(GetRegisterState(reg_from) == CACHED_LSW); |
1224 __ Mov(GetCachedRegister(reg_from), twice_non_position_value()); | 1224 __ Mov(GetCachedRegister(reg_from), twice_non_position_value()); |
1225 reg_from += 2; | 1225 reg_from += 2; |
1226 num_registers -= 2; | 1226 num_registers -= 2; |
1227 } | 1227 } |
1228 | 1228 |
1229 if ((num_registers % 2) == 1) { | 1229 if ((num_registers % 2) == 1) { |
1230 StoreRegister(reg_from, non_position_value()); | 1230 StoreRegister(reg_from, non_position_value()); |
1231 num_registers--; | 1231 num_registers--; |
1232 reg_from++; | 1232 reg_from++; |
1233 } | 1233 } |
1234 | 1234 |
1235 if (num_registers > 0) { | 1235 if (num_registers > 0) { |
1236 // If there are some remaining registers, they are stored on the stack. | 1236 // If there are some remaining registers, they are stored on the stack. |
1237 ASSERT(reg_from >= kNumCachedRegisters); | 1237 DCHECK(reg_from >= kNumCachedRegisters); |
1238 | 1238 |
1239 // Move down the indexes of the registers on stack to get the correct offset | 1239 // Move down the indexes of the registers on stack to get the correct offset |
1240 // in memory. | 1240 // in memory. |
1241 reg_from -= kNumCachedRegisters; | 1241 reg_from -= kNumCachedRegisters; |
1242 reg_to -= kNumCachedRegisters; | 1242 reg_to -= kNumCachedRegisters; |
1243 // We should not unroll the loop for less than 2 registers. | 1243 // We should not unroll the loop for less than 2 registers. |
1244 STATIC_ASSERT(kNumRegistersToUnroll > 2); | 1244 STATIC_ASSERT(kNumRegistersToUnroll > 2); |
1245 // We position the base pointer to (reg_from + 1). | 1245 // We position the base pointer to (reg_from + 1). |
1246 int base_offset = kFirstRegisterOnStack - | 1246 int base_offset = kFirstRegisterOnStack - |
1247 kWRegSize - (kWRegSize * reg_from); | 1247 kWRegSize - (kWRegSize * reg_from); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1310 | 1310 |
1311 // Prepare for possible GC. | 1311 // Prepare for possible GC. |
1312 HandleScope handles(isolate); | 1312 HandleScope handles(isolate); |
1313 Handle<Code> code_handle(re_code); | 1313 Handle<Code> code_handle(re_code); |
1314 | 1314 |
1315 Handle<String> subject(frame_entry<String*>(re_frame, kInput)); | 1315 Handle<String> subject(frame_entry<String*>(re_frame, kInput)); |
1316 | 1316 |
1317 // Current string. | 1317 // Current string. |
1318 bool is_ascii = subject->IsOneByteRepresentationUnderneath(); | 1318 bool is_ascii = subject->IsOneByteRepresentationUnderneath(); |
1319 | 1319 |
1320 ASSERT(re_code->instruction_start() <= *return_address); | 1320 DCHECK(re_code->instruction_start() <= *return_address); |
1321 ASSERT(*return_address <= | 1321 DCHECK(*return_address <= |
1322 re_code->instruction_start() + re_code->instruction_size()); | 1322 re_code->instruction_start() + re_code->instruction_size()); |
1323 | 1323 |
1324 Object* result = isolate->stack_guard()->HandleInterrupts(); | 1324 Object* result = isolate->stack_guard()->HandleInterrupts(); |
1325 | 1325 |
1326 if (*code_handle != re_code) { // Return address no longer valid | 1326 if (*code_handle != re_code) { // Return address no longer valid |
1327 int delta = code_handle->address() - re_code->address(); | 1327 int delta = code_handle->address() - re_code->address(); |
1328 // Overwrite the return address on the stack. | 1328 // Overwrite the return address on the stack. |
1329 *return_address += delta; | 1329 *return_address += delta; |
1330 } | 1330 } |
1331 | 1331 |
(...skipping 18 matching lines...) Expand all Loading... |
1350 // If we changed between an ASCII and an UC16 string, the specialized | 1350 // If we changed between an ASCII and an UC16 string, the specialized |
1351 // code cannot be used, and we need to restart regexp matching from | 1351 // code cannot be used, and we need to restart regexp matching from |
1352 // scratch (including, potentially, compiling a new version of the code). | 1352 // scratch (including, potentially, compiling a new version of the code). |
1353 return RETRY; | 1353 return RETRY; |
1354 } | 1354 } |
1355 | 1355 |
1356 // Otherwise, the content of the string might have moved. It must still | 1356 // Otherwise, the content of the string might have moved. It must still |
1357 // be a sequential or external string with the same content. | 1357 // be a sequential or external string with the same content. |
1358 // Update the start and end pointers in the stack frame to the current | 1358 // Update the start and end pointers in the stack frame to the current |
1359 // location (whether it has actually moved or not). | 1359 // location (whether it has actually moved or not). |
1360 ASSERT(StringShape(*subject_tmp).IsSequential() || | 1360 DCHECK(StringShape(*subject_tmp).IsSequential() || |
1361 StringShape(*subject_tmp).IsExternal()); | 1361 StringShape(*subject_tmp).IsExternal()); |
1362 | 1362 |
1363 // The original start address of the characters to match. | 1363 // The original start address of the characters to match. |
1364 const byte* start_address = *input_start; | 1364 const byte* start_address = *input_start; |
1365 | 1365 |
1366 // Find the current start address of the same character at the current string | 1366 // Find the current start address of the same character at the current string |
1367 // position. | 1367 // position. |
1368 const byte* new_address = StringCharacterPosition(*subject_tmp, | 1368 const byte* new_address = StringCharacterPosition(*subject_tmp, |
1369 start_offset + slice_offset); | 1369 start_offset + slice_offset); |
1370 | 1370 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1403 | 1403 |
1404 | 1404 |
1405 // Private methods: | 1405 // Private methods: |
1406 | 1406 |
1407 void RegExpMacroAssemblerARM64::CallCheckStackGuardState(Register scratch) { | 1407 void RegExpMacroAssemblerARM64::CallCheckStackGuardState(Register scratch) { |
1408 // Allocate space on the stack to store the return address. The | 1408 // Allocate space on the stack to store the return address. The |
1409 // CheckStackGuardState C++ function will override it if the code | 1409 // CheckStackGuardState C++ function will override it if the code |
1410 // moved. Allocate extra space for 2 arguments passed by pointers. | 1410 // moved. Allocate extra space for 2 arguments passed by pointers. |
1411 // AAPCS64 requires the stack to be 16 byte aligned. | 1411 // AAPCS64 requires the stack to be 16 byte aligned. |
1412 int alignment = masm_->ActivationFrameAlignment(); | 1412 int alignment = masm_->ActivationFrameAlignment(); |
1413 ASSERT_EQ(alignment % 16, 0); | 1413 DCHECK_EQ(alignment % 16, 0); |
1414 int align_mask = (alignment / kXRegSize) - 1; | 1414 int align_mask = (alignment / kXRegSize) - 1; |
1415 int xreg_to_claim = (3 + align_mask) & ~align_mask; | 1415 int xreg_to_claim = (3 + align_mask) & ~align_mask; |
1416 | 1416 |
1417 ASSERT(csp.Is(__ StackPointer())); | 1417 DCHECK(csp.Is(__ StackPointer())); |
1418 __ Claim(xreg_to_claim); | 1418 __ Claim(xreg_to_claim); |
1419 | 1419 |
1420 // CheckStackGuardState needs the end and start addresses of the input string. | 1420 // CheckStackGuardState needs the end and start addresses of the input string. |
1421 __ Poke(input_end(), 2 * kPointerSize); | 1421 __ Poke(input_end(), 2 * kPointerSize); |
1422 __ Add(x5, csp, 2 * kPointerSize); | 1422 __ Add(x5, csp, 2 * kPointerSize); |
1423 __ Poke(input_start(), kPointerSize); | 1423 __ Poke(input_start(), kPointerSize); |
1424 __ Add(x4, csp, kPointerSize); | 1424 __ Add(x4, csp, kPointerSize); |
1425 | 1425 |
1426 __ Mov(w3, start_offset()); | 1426 __ Mov(w3, start_offset()); |
1427 // RegExp code frame pointer. | 1427 // RegExp code frame pointer. |
1428 __ Mov(x2, frame_pointer()); | 1428 __ Mov(x2, frame_pointer()); |
1429 // Code* of self. | 1429 // Code* of self. |
1430 __ Mov(x1, Operand(masm_->CodeObject())); | 1430 __ Mov(x1, Operand(masm_->CodeObject())); |
1431 | 1431 |
1432 // We need to pass a pointer to the return address as first argument. | 1432 // We need to pass a pointer to the return address as first argument. |
1433 // The DirectCEntry stub will place the return address on the stack before | 1433 // The DirectCEntry stub will place the return address on the stack before |
1434 // calling so the stack pointer will point to it. | 1434 // calling so the stack pointer will point to it. |
1435 __ Mov(x0, csp); | 1435 __ Mov(x0, csp); |
1436 | 1436 |
1437 ExternalReference check_stack_guard_state = | 1437 ExternalReference check_stack_guard_state = |
1438 ExternalReference::re_check_stack_guard_state(isolate()); | 1438 ExternalReference::re_check_stack_guard_state(isolate()); |
1439 __ Mov(scratch, check_stack_guard_state); | 1439 __ Mov(scratch, check_stack_guard_state); |
1440 DirectCEntryStub stub(isolate()); | 1440 DirectCEntryStub stub(isolate()); |
1441 stub.GenerateCall(masm_, scratch); | 1441 stub.GenerateCall(masm_, scratch); |
1442 | 1442 |
1443 // The input string may have been moved in memory, we need to reload it. | 1443 // The input string may have been moved in memory, we need to reload it. |
1444 __ Peek(input_start(), kPointerSize); | 1444 __ Peek(input_start(), kPointerSize); |
1445 __ Peek(input_end(), 2 * kPointerSize); | 1445 __ Peek(input_end(), 2 * kPointerSize); |
1446 | 1446 |
1447 ASSERT(csp.Is(__ StackPointer())); | 1447 DCHECK(csp.Is(__ StackPointer())); |
1448 __ Drop(xreg_to_claim); | 1448 __ Drop(xreg_to_claim); |
1449 | 1449 |
1450 // Reload the Code pointer. | 1450 // Reload the Code pointer. |
1451 __ Mov(code_pointer(), Operand(masm_->CodeObject())); | 1451 __ Mov(code_pointer(), Operand(masm_->CodeObject())); |
1452 } | 1452 } |
1453 | 1453 |
1454 void RegExpMacroAssemblerARM64::BranchOrBacktrack(Condition condition, | 1454 void RegExpMacroAssemblerARM64::BranchOrBacktrack(Condition condition, |
1455 Label* to) { | 1455 Label* to) { |
1456 if (condition == al) { // Unconditional. | 1456 if (condition == al) { // Unconditional. |
1457 if (to == NULL) { | 1457 if (to == NULL) { |
(...skipping 28 matching lines...) Expand all Loading... |
1486 } | 1486 } |
1487 } | 1487 } |
1488 | 1488 |
1489 | 1489 |
1490 void RegExpMacroAssemblerARM64::CheckPreemption() { | 1490 void RegExpMacroAssemblerARM64::CheckPreemption() { |
1491 // Check for preemption. | 1491 // Check for preemption. |
1492 ExternalReference stack_limit = | 1492 ExternalReference stack_limit = |
1493 ExternalReference::address_of_stack_limit(isolate()); | 1493 ExternalReference::address_of_stack_limit(isolate()); |
1494 __ Mov(x10, stack_limit); | 1494 __ Mov(x10, stack_limit); |
1495 __ Ldr(x10, MemOperand(x10)); | 1495 __ Ldr(x10, MemOperand(x10)); |
1496 ASSERT(csp.Is(__ StackPointer())); | 1496 DCHECK(csp.Is(__ StackPointer())); |
1497 __ Cmp(csp, x10); | 1497 __ Cmp(csp, x10); |
1498 CallIf(&check_preempt_label_, ls); | 1498 CallIf(&check_preempt_label_, ls); |
1499 } | 1499 } |
1500 | 1500 |
1501 | 1501 |
1502 void RegExpMacroAssemblerARM64::CheckStackLimit() { | 1502 void RegExpMacroAssemblerARM64::CheckStackLimit() { |
1503 ExternalReference stack_limit = | 1503 ExternalReference stack_limit = |
1504 ExternalReference::address_of_regexp_stack_limit(isolate()); | 1504 ExternalReference::address_of_regexp_stack_limit(isolate()); |
1505 __ Mov(x10, stack_limit); | 1505 __ Mov(x10, stack_limit); |
1506 __ Ldr(x10, MemOperand(x10)); | 1506 __ Ldr(x10, MemOperand(x10)); |
1507 __ Cmp(backtrack_stackpointer(), x10); | 1507 __ Cmp(backtrack_stackpointer(), x10); |
1508 CallIf(&stack_overflow_label_, ls); | 1508 CallIf(&stack_overflow_label_, ls); |
1509 } | 1509 } |
1510 | 1510 |
1511 | 1511 |
1512 void RegExpMacroAssemblerARM64::Push(Register source) { | 1512 void RegExpMacroAssemblerARM64::Push(Register source) { |
1513 ASSERT(source.Is32Bits()); | 1513 DCHECK(source.Is32Bits()); |
1514 ASSERT(!source.is(backtrack_stackpointer())); | 1514 DCHECK(!source.is(backtrack_stackpointer())); |
1515 __ Str(source, | 1515 __ Str(source, |
1516 MemOperand(backtrack_stackpointer(), | 1516 MemOperand(backtrack_stackpointer(), |
1517 -static_cast<int>(kWRegSize), | 1517 -static_cast<int>(kWRegSize), |
1518 PreIndex)); | 1518 PreIndex)); |
1519 } | 1519 } |
1520 | 1520 |
1521 | 1521 |
1522 void RegExpMacroAssemblerARM64::Pop(Register target) { | 1522 void RegExpMacroAssemblerARM64::Pop(Register target) { |
1523 ASSERT(target.Is32Bits()); | 1523 DCHECK(target.Is32Bits()); |
1524 ASSERT(!target.is(backtrack_stackpointer())); | 1524 DCHECK(!target.is(backtrack_stackpointer())); |
1525 __ Ldr(target, | 1525 __ Ldr(target, |
1526 MemOperand(backtrack_stackpointer(), kWRegSize, PostIndex)); | 1526 MemOperand(backtrack_stackpointer(), kWRegSize, PostIndex)); |
1527 } | 1527 } |
1528 | 1528 |
1529 | 1529 |
1530 Register RegExpMacroAssemblerARM64::GetCachedRegister(int register_index) { | 1530 Register RegExpMacroAssemblerARM64::GetCachedRegister(int register_index) { |
1531 ASSERT(register_index < kNumCachedRegisters); | 1531 DCHECK(register_index < kNumCachedRegisters); |
1532 return Register::Create(register_index / 2, kXRegSizeInBits); | 1532 return Register::Create(register_index / 2, kXRegSizeInBits); |
1533 } | 1533 } |
1534 | 1534 |
1535 | 1535 |
1536 Register RegExpMacroAssemblerARM64::GetRegister(int register_index, | 1536 Register RegExpMacroAssemblerARM64::GetRegister(int register_index, |
1537 Register maybe_result) { | 1537 Register maybe_result) { |
1538 ASSERT(maybe_result.Is32Bits()); | 1538 DCHECK(maybe_result.Is32Bits()); |
1539 ASSERT(register_index >= 0); | 1539 DCHECK(register_index >= 0); |
1540 if (num_registers_ <= register_index) { | 1540 if (num_registers_ <= register_index) { |
1541 num_registers_ = register_index + 1; | 1541 num_registers_ = register_index + 1; |
1542 } | 1542 } |
1543 Register result; | 1543 Register result; |
1544 RegisterState register_state = GetRegisterState(register_index); | 1544 RegisterState register_state = GetRegisterState(register_index); |
1545 switch (register_state) { | 1545 switch (register_state) { |
1546 case STACKED: | 1546 case STACKED: |
1547 __ Ldr(maybe_result, register_location(register_index)); | 1547 __ Ldr(maybe_result, register_location(register_index)); |
1548 result = maybe_result; | 1548 result = maybe_result; |
1549 break; | 1549 break; |
1550 case CACHED_LSW: | 1550 case CACHED_LSW: |
1551 result = GetCachedRegister(register_index).W(); | 1551 result = GetCachedRegister(register_index).W(); |
1552 break; | 1552 break; |
1553 case CACHED_MSW: | 1553 case CACHED_MSW: |
1554 __ Lsr(maybe_result.X(), GetCachedRegister(register_index), | 1554 __ Lsr(maybe_result.X(), GetCachedRegister(register_index), |
1555 kWRegSizeInBits); | 1555 kWRegSizeInBits); |
1556 result = maybe_result; | 1556 result = maybe_result; |
1557 break; | 1557 break; |
1558 default: | 1558 default: |
1559 UNREACHABLE(); | 1559 UNREACHABLE(); |
1560 break; | 1560 break; |
1561 } | 1561 } |
1562 ASSERT(result.Is32Bits()); | 1562 DCHECK(result.Is32Bits()); |
1563 return result; | 1563 return result; |
1564 } | 1564 } |
1565 | 1565 |
1566 | 1566 |
1567 void RegExpMacroAssemblerARM64::StoreRegister(int register_index, | 1567 void RegExpMacroAssemblerARM64::StoreRegister(int register_index, |
1568 Register source) { | 1568 Register source) { |
1569 ASSERT(source.Is32Bits()); | 1569 DCHECK(source.Is32Bits()); |
1570 ASSERT(register_index >= 0); | 1570 DCHECK(register_index >= 0); |
1571 if (num_registers_ <= register_index) { | 1571 if (num_registers_ <= register_index) { |
1572 num_registers_ = register_index + 1; | 1572 num_registers_ = register_index + 1; |
1573 } | 1573 } |
1574 | 1574 |
1575 Register cached_register; | 1575 Register cached_register; |
1576 RegisterState register_state = GetRegisterState(register_index); | 1576 RegisterState register_state = GetRegisterState(register_index); |
1577 switch (register_state) { | 1577 switch (register_state) { |
1578 case STACKED: | 1578 case STACKED: |
1579 __ Str(source, register_location(register_index)); | 1579 __ Str(source, register_location(register_index)); |
1580 break; | 1580 break; |
(...skipping 16 matching lines...) Expand all Loading... |
1597 | 1597 |
1598 void RegExpMacroAssemblerARM64::CallIf(Label* to, Condition condition) { | 1598 void RegExpMacroAssemblerARM64::CallIf(Label* to, Condition condition) { |
1599 Label skip_call; | 1599 Label skip_call; |
1600 if (condition != al) __ B(&skip_call, NegateCondition(condition)); | 1600 if (condition != al) __ B(&skip_call, NegateCondition(condition)); |
1601 __ Bl(to); | 1601 __ Bl(to); |
1602 __ Bind(&skip_call); | 1602 __ Bind(&skip_call); |
1603 } | 1603 } |
1604 | 1604 |
1605 | 1605 |
1606 void RegExpMacroAssemblerARM64::RestoreLinkRegister() { | 1606 void RegExpMacroAssemblerARM64::RestoreLinkRegister() { |
1607 ASSERT(csp.Is(__ StackPointer())); | 1607 DCHECK(csp.Is(__ StackPointer())); |
1608 __ Pop(lr, xzr); | 1608 __ Pop(lr, xzr); |
1609 __ Add(lr, lr, Operand(masm_->CodeObject())); | 1609 __ Add(lr, lr, Operand(masm_->CodeObject())); |
1610 } | 1610 } |
1611 | 1611 |
1612 | 1612 |
1613 void RegExpMacroAssemblerARM64::SaveLinkRegister() { | 1613 void RegExpMacroAssemblerARM64::SaveLinkRegister() { |
1614 ASSERT(csp.Is(__ StackPointer())); | 1614 DCHECK(csp.Is(__ StackPointer())); |
1615 __ Sub(lr, lr, Operand(masm_->CodeObject())); | 1615 __ Sub(lr, lr, Operand(masm_->CodeObject())); |
1616 __ Push(xzr, lr); | 1616 __ Push(xzr, lr); |
1617 } | 1617 } |
1618 | 1618 |
1619 | 1619 |
1620 MemOperand RegExpMacroAssemblerARM64::register_location(int register_index) { | 1620 MemOperand RegExpMacroAssemblerARM64::register_location(int register_index) { |
1621 ASSERT(register_index < (1<<30)); | 1621 DCHECK(register_index < (1<<30)); |
1622 ASSERT(register_index >= kNumCachedRegisters); | 1622 DCHECK(register_index >= kNumCachedRegisters); |
1623 if (num_registers_ <= register_index) { | 1623 if (num_registers_ <= register_index) { |
1624 num_registers_ = register_index + 1; | 1624 num_registers_ = register_index + 1; |
1625 } | 1625 } |
1626 register_index -= kNumCachedRegisters; | 1626 register_index -= kNumCachedRegisters; |
1627 int offset = kFirstRegisterOnStack - register_index * kWRegSize; | 1627 int offset = kFirstRegisterOnStack - register_index * kWRegSize; |
1628 return MemOperand(frame_pointer(), offset); | 1628 return MemOperand(frame_pointer(), offset); |
1629 } | 1629 } |
1630 | 1630 |
1631 MemOperand RegExpMacroAssemblerARM64::capture_location(int register_index, | 1631 MemOperand RegExpMacroAssemblerARM64::capture_location(int register_index, |
1632 Register scratch) { | 1632 Register scratch) { |
1633 ASSERT(register_index < (1<<30)); | 1633 DCHECK(register_index < (1<<30)); |
1634 ASSERT(register_index < num_saved_registers_); | 1634 DCHECK(register_index < num_saved_registers_); |
1635 ASSERT(register_index >= kNumCachedRegisters); | 1635 DCHECK(register_index >= kNumCachedRegisters); |
1636 ASSERT_EQ(register_index % 2, 0); | 1636 DCHECK_EQ(register_index % 2, 0); |
1637 register_index -= kNumCachedRegisters; | 1637 register_index -= kNumCachedRegisters; |
1638 int offset = kFirstCaptureOnStack - register_index * kWRegSize; | 1638 int offset = kFirstCaptureOnStack - register_index * kWRegSize; |
1639 // capture_location is used with Stp instructions to load/store 2 registers. | 1639 // capture_location is used with Stp instructions to load/store 2 registers. |
1640 // The immediate field in the encoding is limited to 7 bits (signed). | 1640 // The immediate field in the encoding is limited to 7 bits (signed). |
1641 if (is_int7(offset)) { | 1641 if (is_int7(offset)) { |
1642 return MemOperand(frame_pointer(), offset); | 1642 return MemOperand(frame_pointer(), offset); |
1643 } else { | 1643 } else { |
1644 __ Add(scratch, frame_pointer(), offset); | 1644 __ Add(scratch, frame_pointer(), offset); |
1645 return MemOperand(scratch); | 1645 return MemOperand(scratch); |
1646 } | 1646 } |
1647 } | 1647 } |
1648 | 1648 |
1649 void RegExpMacroAssemblerARM64::LoadCurrentCharacterUnchecked(int cp_offset, | 1649 void RegExpMacroAssemblerARM64::LoadCurrentCharacterUnchecked(int cp_offset, |
1650 int characters) { | 1650 int characters) { |
1651 Register offset = current_input_offset(); | 1651 Register offset = current_input_offset(); |
1652 | 1652 |
1653 // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU | 1653 // The ldr, str, ldrh, strh instructions can do unaligned accesses, if the CPU |
1654 // and the operating system running on the target allow it. | 1654 // and the operating system running on the target allow it. |
1655 // If unaligned load/stores are not supported then this function must only | 1655 // If unaligned load/stores are not supported then this function must only |
1656 // be used to load a single character at a time. | 1656 // be used to load a single character at a time. |
1657 | 1657 |
1658 // ARMv8 supports unaligned accesses but V8 or the kernel can decide to | 1658 // ARMv8 supports unaligned accesses but V8 or the kernel can decide to |
1659 // disable it. | 1659 // disable it. |
1660 // TODO(pielan): See whether or not we should disable unaligned accesses. | 1660 // TODO(pielan): See whether or not we should disable unaligned accesses. |
1661 if (!CanReadUnaligned()) { | 1661 if (!CanReadUnaligned()) { |
1662 ASSERT(characters == 1); | 1662 DCHECK(characters == 1); |
1663 } | 1663 } |
1664 | 1664 |
1665 if (cp_offset != 0) { | 1665 if (cp_offset != 0) { |
1666 if (masm_->emit_debug_code()) { | 1666 if (masm_->emit_debug_code()) { |
1667 __ Mov(x10, cp_offset * char_size()); | 1667 __ Mov(x10, cp_offset * char_size()); |
1668 __ Add(x10, x10, Operand(current_input_offset(), SXTW)); | 1668 __ Add(x10, x10, Operand(current_input_offset(), SXTW)); |
1669 __ Cmp(x10, Operand(w10, SXTW)); | 1669 __ Cmp(x10, Operand(w10, SXTW)); |
1670 // The offset needs to fit in a W register. | 1670 // The offset needs to fit in a W register. |
1671 __ Check(eq, kOffsetOutOfRange); | 1671 __ Check(eq, kOffsetOutOfRange); |
1672 } else { | 1672 } else { |
1673 __ Add(w10, current_input_offset(), cp_offset * char_size()); | 1673 __ Add(w10, current_input_offset(), cp_offset * char_size()); |
1674 } | 1674 } |
1675 offset = w10; | 1675 offset = w10; |
1676 } | 1676 } |
1677 | 1677 |
1678 if (mode_ == ASCII) { | 1678 if (mode_ == ASCII) { |
1679 if (characters == 4) { | 1679 if (characters == 4) { |
1680 __ Ldr(current_character(), MemOperand(input_end(), offset, SXTW)); | 1680 __ Ldr(current_character(), MemOperand(input_end(), offset, SXTW)); |
1681 } else if (characters == 2) { | 1681 } else if (characters == 2) { |
1682 __ Ldrh(current_character(), MemOperand(input_end(), offset, SXTW)); | 1682 __ Ldrh(current_character(), MemOperand(input_end(), offset, SXTW)); |
1683 } else { | 1683 } else { |
1684 ASSERT(characters == 1); | 1684 DCHECK(characters == 1); |
1685 __ Ldrb(current_character(), MemOperand(input_end(), offset, SXTW)); | 1685 __ Ldrb(current_character(), MemOperand(input_end(), offset, SXTW)); |
1686 } | 1686 } |
1687 } else { | 1687 } else { |
1688 ASSERT(mode_ == UC16); | 1688 DCHECK(mode_ == UC16); |
1689 if (characters == 2) { | 1689 if (characters == 2) { |
1690 __ Ldr(current_character(), MemOperand(input_end(), offset, SXTW)); | 1690 __ Ldr(current_character(), MemOperand(input_end(), offset, SXTW)); |
1691 } else { | 1691 } else { |
1692 ASSERT(characters == 1); | 1692 DCHECK(characters == 1); |
1693 __ Ldrh(current_character(), MemOperand(input_end(), offset, SXTW)); | 1693 __ Ldrh(current_character(), MemOperand(input_end(), offset, SXTW)); |
1694 } | 1694 } |
1695 } | 1695 } |
1696 } | 1696 } |
1697 | 1697 |
1698 #endif // V8_INTERPRETED_REGEXP | 1698 #endif // V8_INTERPRETED_REGEXP |
1699 | 1699 |
1700 }} // namespace v8::internal | 1700 }} // namespace v8::internal |
1701 | 1701 |
1702 #endif // V8_TARGET_ARCH_ARM64 | 1702 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |