| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 __ Ldr(w10, register_location(reg)); | 192 __ Ldr(w10, register_location(reg)); |
| 193 __ Add(w10, w10, by); | 193 __ Add(w10, w10, by); |
| 194 __ Str(w10, register_location(reg)); | 194 __ Str(w10, register_location(reg)); |
| 195 break; | 195 break; |
| 196 case CACHED_LSW: | 196 case CACHED_LSW: |
| 197 to_advance = GetCachedRegister(reg); | 197 to_advance = GetCachedRegister(reg); |
| 198 __ Add(to_advance, to_advance, by); | 198 __ Add(to_advance, to_advance, by); |
| 199 break; | 199 break; |
| 200 case CACHED_MSW: | 200 case CACHED_MSW: |
| 201 to_advance = GetCachedRegister(reg); | 201 to_advance = GetCachedRegister(reg); |
| 202 __ Add(to_advance, to_advance, static_cast<int64_t>(by) << kWRegSize); | 202 __ Add(to_advance, to_advance, |
| 203 static_cast<int64_t>(by) << kWRegSizeInBits); |
| 203 break; | 204 break; |
| 204 default: | 205 default: |
| 205 UNREACHABLE(); | 206 UNREACHABLE(); |
| 206 break; | 207 break; |
| 207 } | 208 } |
| 208 } | 209 } |
| 209 } | 210 } |
| 210 | 211 |
| 211 | 212 |
| 212 void RegExpMacroAssemblerA64::Backtrack() { | 213 void RegExpMacroAssemblerA64::Backtrack() { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 CompareAndBranchOrBacktrack(w10, str[i], ne, on_failure); | 290 CompareAndBranchOrBacktrack(w10, str[i], ne, on_failure); |
| 290 } | 291 } |
| 291 } | 292 } |
| 292 | 293 |
| 293 | 294 |
| 294 void RegExpMacroAssemblerA64::CheckGreedyLoop(Label* on_equal) { | 295 void RegExpMacroAssemblerA64::CheckGreedyLoop(Label* on_equal) { |
| 295 __ Ldr(w10, MemOperand(backtrack_stackpointer())); | 296 __ Ldr(w10, MemOperand(backtrack_stackpointer())); |
| 296 __ Cmp(current_input_offset(), w10); | 297 __ Cmp(current_input_offset(), w10); |
| 297 __ Cset(x11, eq); | 298 __ Cset(x11, eq); |
| 298 __ Add(backtrack_stackpointer(), | 299 __ Add(backtrack_stackpointer(), |
| 299 backtrack_stackpointer(), Operand(x11, LSL, kWRegSizeInBytesLog2)); | 300 backtrack_stackpointer(), Operand(x11, LSL, kWRegSizeLog2)); |
| 300 BranchOrBacktrack(eq, on_equal); | 301 BranchOrBacktrack(eq, on_equal); |
| 301 } | 302 } |
| 302 | 303 |
| 303 void RegExpMacroAssemblerA64::CheckNotBackReferenceIgnoreCase( | 304 void RegExpMacroAssemblerA64::CheckNotBackReferenceIgnoreCase( |
| 304 int start_reg, | 305 int start_reg, |
| 305 Label* on_no_match) { | 306 Label* on_no_match) { |
| 306 Label fallthrough; | 307 Label fallthrough; |
| 307 | 308 |
| 308 Register capture_start_offset = w10; | 309 Register capture_start_offset = w10; |
| 309 // Save the capture length in a callee-saved register so it will | 310 // Save the capture length in a callee-saved register so it will |
| 310 // be preserved if we call a C helper. | 311 // be preserved if we call a C helper. |
| 311 Register capture_length = w19; | 312 Register capture_length = w19; |
| 312 ASSERT(kCalleeSaved.IncludesAliasOf(capture_length)); | 313 ASSERT(kCalleeSaved.IncludesAliasOf(capture_length)); |
| 313 | 314 |
| 314 // Find length of back-referenced capture. | 315 // Find length of back-referenced capture. |
| 315 ASSERT((start_reg % 2) == 0); | 316 ASSERT((start_reg % 2) == 0); |
| 316 if (start_reg < kNumCachedRegisters) { | 317 if (start_reg < kNumCachedRegisters) { |
| 317 __ Mov(capture_start_offset.X(), GetCachedRegister(start_reg)); | 318 __ Mov(capture_start_offset.X(), GetCachedRegister(start_reg)); |
| 318 __ Lsr(x11, GetCachedRegister(start_reg), kWRegSize); | 319 __ Lsr(x11, GetCachedRegister(start_reg), kWRegSizeInBits); |
| 319 } else { | 320 } else { |
| 320 __ Ldp(w11, capture_start_offset, capture_location(start_reg, x10)); | 321 __ Ldp(w11, capture_start_offset, capture_location(start_reg, x10)); |
| 321 } | 322 } |
| 322 __ Sub(capture_length, w11, capture_start_offset); // Length to check. | 323 __ Sub(capture_length, w11, capture_start_offset); // Length to check. |
| 323 // Succeed on empty capture (including no capture). | 324 // Succeed on empty capture (including no capture). |
| 324 __ Cbz(capture_length, &fallthrough); | 325 __ Cbz(capture_length, &fallthrough); |
| 325 | 326 |
| 326 // Check that there are enough characters left in the input. | 327 // Check that there are enough characters left in the input. |
| 327 __ Cmn(capture_length, current_input_offset()); | 328 __ Cmn(capture_length, current_input_offset()); |
| 328 BranchOrBacktrack(gt, on_no_match); | 329 BranchOrBacktrack(gt, on_no_match); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); | 383 __ Cmp(current_input_offset().X(), Operand(current_input_offset(), SXTW)); |
| 383 __ Ccmp(current_input_offset(), 0, NoFlag, eq); | 384 __ Ccmp(current_input_offset(), 0, NoFlag, eq); |
| 384 // The current input offset should be <= 0, and fit in a W register. | 385 // The current input offset should be <= 0, and fit in a W register. |
| 385 __ Check(le, kOffsetOutOfRange); | 386 __ Check(le, kOffsetOutOfRange); |
| 386 } | 387 } |
| 387 } else { | 388 } else { |
| 388 ASSERT(mode_ == UC16); | 389 ASSERT(mode_ == UC16); |
| 389 int argument_count = 4; | 390 int argument_count = 4; |
| 390 | 391 |
| 391 // The cached registers need to be retained. | 392 // The cached registers need to be retained. |
| 392 CPURegList cached_registers(CPURegister::kRegister, kXRegSize, 0, 7); | 393 CPURegList cached_registers(CPURegister::kRegister, kXRegSizeInBits, 0, 7); |
| 393 ASSERT((cached_registers.Count() * 2) == kNumCachedRegisters); | 394 ASSERT((cached_registers.Count() * 2) == kNumCachedRegisters); |
| 394 __ PushCPURegList(cached_registers); | 395 __ PushCPURegList(cached_registers); |
| 395 | 396 |
| 396 // Put arguments into arguments registers. | 397 // Put arguments into arguments registers. |
| 397 // Parameters are | 398 // Parameters are |
| 398 // x0: Address byte_offset1 - Address captured substring's start. | 399 // x0: Address byte_offset1 - Address captured substring's start. |
| 399 // x1: Address byte_offset2 - Address of current character position. | 400 // x1: Address byte_offset2 - Address of current character position. |
| 400 // w2: size_t byte_length - length of capture in bytes(!) | 401 // w2: size_t byte_length - length of capture in bytes(!) |
| 401 // x3: Isolate* isolate | 402 // x3: Isolate* isolate |
| 402 | 403 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 | 435 |
| 435 Register capture_start_address = x12; | 436 Register capture_start_address = x12; |
| 436 Register capture_end_address = x13; | 437 Register capture_end_address = x13; |
| 437 Register current_position_address = x14; | 438 Register current_position_address = x14; |
| 438 Register capture_length = w15; | 439 Register capture_length = w15; |
| 439 | 440 |
| 440 // Find length of back-referenced capture. | 441 // Find length of back-referenced capture. |
| 441 ASSERT((start_reg % 2) == 0); | 442 ASSERT((start_reg % 2) == 0); |
| 442 if (start_reg < kNumCachedRegisters) { | 443 if (start_reg < kNumCachedRegisters) { |
| 443 __ Mov(x10, GetCachedRegister(start_reg)); | 444 __ Mov(x10, GetCachedRegister(start_reg)); |
| 444 __ Lsr(x11, GetCachedRegister(start_reg), kWRegSize); | 445 __ Lsr(x11, GetCachedRegister(start_reg), kWRegSizeInBits); |
| 445 } else { | 446 } else { |
| 446 __ Ldp(w11, w10, capture_location(start_reg, x10)); | 447 __ Ldp(w11, w10, capture_location(start_reg, x10)); |
| 447 } | 448 } |
| 448 __ Sub(capture_length, w11, w10); // Length to check. | 449 __ Sub(capture_length, w11, w10); // Length to check. |
| 449 // Succeed on empty capture (including no capture). | 450 // Succeed on empty capture (including no capture). |
| 450 __ Cbz(capture_length, &fallthrough); | 451 __ Cbz(capture_length, &fallthrough); |
| 451 | 452 |
| 452 // Check that there are enough characters left in the input. | 453 // Check that there are enough characters left in the input. |
| 453 __ Cmn(capture_length, current_input_offset()); | 454 __ Cmn(capture_length, current_input_offset()); |
| 454 BranchOrBacktrack(gt, on_no_match); | 455 BranchOrBacktrack(gt, on_no_match); |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 719 // - (num_registers_ - kNumCachedRegisters) (W registers) | 720 // - (num_registers_ - kNumCachedRegisters) (W registers) |
| 720 int num_wreg_to_allocate = num_registers_ - kNumCachedRegisters; | 721 int num_wreg_to_allocate = num_registers_ - kNumCachedRegisters; |
| 721 // Do not allocate registers on the stack if they can all be cached. | 722 // Do not allocate registers on the stack if they can all be cached. |
| 722 if (num_wreg_to_allocate < 0) { num_wreg_to_allocate = 0; } | 723 if (num_wreg_to_allocate < 0) { num_wreg_to_allocate = 0; } |
| 723 // Make room for the success_counter. | 724 // Make room for the success_counter. |
| 724 num_wreg_to_allocate += 2; | 725 num_wreg_to_allocate += 2; |
| 725 | 726 |
| 726 // Make sure the stack alignment will be respected. | 727 // Make sure the stack alignment will be respected. |
| 727 int alignment = masm_->ActivationFrameAlignment(); | 728 int alignment = masm_->ActivationFrameAlignment(); |
| 728 ASSERT_EQ(alignment % 16, 0); | 729 ASSERT_EQ(alignment % 16, 0); |
| 729 int align_mask = (alignment / kWRegSizeInBytes) - 1; | 730 int align_mask = (alignment / kWRegSize) - 1; |
| 730 num_wreg_to_allocate = (num_wreg_to_allocate + align_mask) & ~align_mask; | 731 num_wreg_to_allocate = (num_wreg_to_allocate + align_mask) & ~align_mask; |
| 731 | 732 |
| 732 // Check if we have space on the stack. | 733 // Check if we have space on the stack. |
| 733 Label stack_limit_hit; | 734 Label stack_limit_hit; |
| 734 Label stack_ok; | 735 Label stack_ok; |
| 735 | 736 |
| 736 ExternalReference stack_limit = | 737 ExternalReference stack_limit = |
| 737 ExternalReference::address_of_stack_limit(isolate()); | 738 ExternalReference::address_of_stack_limit(isolate()); |
| 738 __ Mov(x10, Operand(stack_limit)); | 739 __ Mov(x10, Operand(stack_limit)); |
| 739 __ Ldr(x10, MemOperand(x10)); | 740 __ Ldr(x10, MemOperand(x10)); |
| 740 __ Subs(x10, csp, x10); | 741 __ Subs(x10, csp, x10); |
| 741 | 742 |
| 742 // Handle it if the stack pointer is already below the stack limit. | 743 // Handle it if the stack pointer is already below the stack limit. |
| 743 __ B(ls, &stack_limit_hit); | 744 __ B(ls, &stack_limit_hit); |
| 744 | 745 |
| 745 // Check if there is room for the variable number of registers above | 746 // Check if there is room for the variable number of registers above |
| 746 // the stack limit. | 747 // the stack limit. |
| 747 __ Cmp(x10, num_wreg_to_allocate * kWRegSizeInBytes); | 748 __ Cmp(x10, num_wreg_to_allocate * kWRegSize); |
| 748 __ B(hs, &stack_ok); | 749 __ B(hs, &stack_ok); |
| 749 | 750 |
| 750 // Exit with OutOfMemory exception. There is not enough space on the stack | 751 // Exit with OutOfMemory exception. There is not enough space on the stack |
| 751 // for our working registers. | 752 // for our working registers. |
| 752 __ Mov(w0, EXCEPTION); | 753 __ Mov(w0, EXCEPTION); |
| 753 __ B(&return_w0); | 754 __ B(&return_w0); |
| 754 | 755 |
| 755 __ Bind(&stack_limit_hit); | 756 __ Bind(&stack_limit_hit); |
| 756 CallCheckStackGuardState(x10); | 757 CallCheckStackGuardState(x10); |
| 757 // If returned value is non-zero, we exit with the returned value as result. | 758 // If returned value is non-zero, we exit with the returned value as result. |
| 758 __ Cbnz(w0, &return_w0); | 759 __ Cbnz(w0, &return_w0); |
| 759 | 760 |
| 760 __ Bind(&stack_ok); | 761 __ Bind(&stack_ok); |
| 761 | 762 |
| 762 // Allocate space on stack. | 763 // Allocate space on stack. |
| 763 __ Claim(num_wreg_to_allocate, kWRegSizeInBytes); | 764 __ Claim(num_wreg_to_allocate, kWRegSize); |
| 764 | 765 |
| 765 // Initialize success_counter with 0. | 766 // Initialize success_counter with 0. |
| 766 __ Str(wzr, MemOperand(frame_pointer(), kSuccessCounter)); | 767 __ Str(wzr, MemOperand(frame_pointer(), kSuccessCounter)); |
| 767 | 768 |
| 768 // Find negative length (offset of start relative to end). | 769 // Find negative length (offset of start relative to end). |
| 769 __ Sub(x10, input_start(), input_end()); | 770 __ Sub(x10, input_start(), input_end()); |
| 770 if (masm_->emit_debug_code()) { | 771 if (masm_->emit_debug_code()) { |
| 771 // Check that the input string length is < 2^30. | 772 // Check that the input string length is < 2^30. |
| 772 __ Neg(x11, x10); | 773 __ Neg(x11, x10); |
| 773 __ Cmp(x11, (1<<30) - 1); | 774 __ Cmp(x11, (1<<30) - 1); |
| 774 __ Check(ls, kInputStringTooLong); | 775 __ Check(ls, kInputStringTooLong); |
| 775 } | 776 } |
| 776 __ Mov(current_input_offset(), w10); | 777 __ Mov(current_input_offset(), w10); |
| 777 | 778 |
| 778 // The non-position value is used as a clearing value for the | 779 // The non-position value is used as a clearing value for the |
| 779 // capture registers, it corresponds to the position of the first character | 780 // capture registers, it corresponds to the position of the first character |
| 780 // minus one. | 781 // minus one. |
| 781 __ Sub(non_position_value(), current_input_offset(), char_size()); | 782 __ Sub(non_position_value(), current_input_offset(), char_size()); |
| 782 __ Sub(non_position_value(), non_position_value(), | 783 __ Sub(non_position_value(), non_position_value(), |
| 783 Operand(start_offset(), LSL, (mode_ == UC16) ? 1 : 0)); | 784 Operand(start_offset(), LSL, (mode_ == UC16) ? 1 : 0)); |
| 784 // We can store this value twice in an X register for initializing | 785 // We can store this value twice in an X register for initializing |
| 785 // on-stack registers later. | 786 // on-stack registers later. |
| 786 __ Orr(twice_non_position_value(), | 787 __ Orr(twice_non_position_value(), |
| 787 non_position_value().X(), | 788 non_position_value().X(), |
| 788 Operand(non_position_value().X(), LSL, kWRegSize)); | 789 Operand(non_position_value().X(), LSL, kWRegSizeInBits)); |
| 789 | 790 |
| 790 // Initialize code pointer register. | 791 // Initialize code pointer register. |
| 791 __ Mov(code_pointer(), Operand(masm_->CodeObject())); | 792 __ Mov(code_pointer(), Operand(masm_->CodeObject())); |
| 792 | 793 |
| 793 Label load_char_start_regexp, start_regexp; | 794 Label load_char_start_regexp, start_regexp; |
| 794 // Load newline if index is at start, previous character otherwise. | 795 // Load newline if index is at start, previous character otherwise. |
| 795 __ Cbnz(start_offset(), &load_char_start_regexp); | 796 __ Cbnz(start_offset(), &load_char_start_regexp); |
| 796 __ Mov(current_character(), '\n'); | 797 __ Mov(current_character(), '\n'); |
| 797 __ B(&start_regexp); | 798 __ B(&start_regexp); |
| 798 | 799 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 844 __ Add(input_length, start_offset(), Operand(w10, LSR, 1)); | 845 __ Add(input_length, start_offset(), Operand(w10, LSR, 1)); |
| 845 } else { | 846 } else { |
| 846 __ Add(input_length, start_offset(), w10); | 847 __ Add(input_length, start_offset(), w10); |
| 847 } | 848 } |
| 848 | 849 |
| 849 // Copy the results to the output array from the cached registers first. | 850 // Copy the results to the output array from the cached registers first. |
| 850 for (int i = 0; | 851 for (int i = 0; |
| 851 (i < num_saved_registers_) && (i < kNumCachedRegisters); | 852 (i < num_saved_registers_) && (i < kNumCachedRegisters); |
| 852 i += 2) { | 853 i += 2) { |
| 853 __ Mov(capture_start.X(), GetCachedRegister(i)); | 854 __ Mov(capture_start.X(), GetCachedRegister(i)); |
| 854 __ Lsr(capture_end.X(), capture_start.X(), kWRegSize); | 855 __ Lsr(capture_end.X(), capture_start.X(), kWRegSizeInBits); |
| 855 if ((i == 0) && global_with_zero_length_check()) { | 856 if ((i == 0) && global_with_zero_length_check()) { |
| 856 // Keep capture start for the zero-length check later. | 857 // Keep capture start for the zero-length check later. |
| 857 __ Mov(first_capture_start, capture_start); | 858 __ Mov(first_capture_start, capture_start); |
| 858 } | 859 } |
| 859 // Offsets need to be relative to the start of the string. | 860 // Offsets need to be relative to the start of the string. |
| 860 if (mode_ == UC16) { | 861 if (mode_ == UC16) { |
| 861 __ Add(capture_start, input_length, Operand(capture_start, ASR, 1)); | 862 __ Add(capture_start, input_length, Operand(capture_start, ASR, 1)); |
| 862 __ Add(capture_end, input_length, Operand(capture_end, ASR, 1)); | 863 __ Add(capture_end, input_length, Operand(capture_end, ASR, 1)); |
| 863 } else { | 864 } else { |
| 864 __ Add(capture_start, input_length, capture_start); | 865 __ Add(capture_start, input_length, capture_start); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 999 __ Mov(csp, fp); | 1000 __ Mov(csp, fp); |
| 1000 | 1001 |
| 1001 // Restore registers. | 1002 // Restore registers. |
| 1002 __ PopCPURegList(registers_to_retain); | 1003 __ PopCPURegList(registers_to_retain); |
| 1003 | 1004 |
| 1004 __ Ret(); | 1005 __ Ret(); |
| 1005 | 1006 |
| 1006 Label exit_with_exception; | 1007 Label exit_with_exception; |
| 1007 // Registers x0 to x7 are used to store the first captures, they need to be | 1008 // Registers x0 to x7 are used to store the first captures, they need to be |
| 1008 // retained over calls to C++ code. | 1009 // retained over calls to C++ code. |
| 1009 CPURegList cached_registers(CPURegister::kRegister, kXRegSize, 0, 7); | 1010 CPURegList cached_registers(CPURegister::kRegister, kXRegSizeInBits, 0, 7); |
| 1010 ASSERT((cached_registers.Count() * 2) == kNumCachedRegisters); | 1011 ASSERT((cached_registers.Count() * 2) == kNumCachedRegisters); |
| 1011 | 1012 |
| 1012 if (check_preempt_label_.is_linked()) { | 1013 if (check_preempt_label_.is_linked()) { |
| 1013 __ Bind(&check_preempt_label_); | 1014 __ Bind(&check_preempt_label_); |
| 1014 SaveLinkRegister(); | 1015 SaveLinkRegister(); |
| 1015 // The cached registers need to be retained. | 1016 // The cached registers need to be retained. |
| 1016 __ PushCPURegList(cached_registers); | 1017 __ PushCPURegList(cached_registers); |
| 1017 CallCheckStackGuardState(x10); | 1018 CallCheckStackGuardState(x10); |
| 1018 // Returning from the regexp code restores the stack (csp <- fp) | 1019 // Returning from the regexp code restores the stack (csp <- fp) |
| 1019 // so we don't need to drop the link register from it before exiting. | 1020 // so we don't need to drop the link register from it before exiting. |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1161 switch (register_state) { | 1162 switch (register_state) { |
| 1162 case STACKED: | 1163 case STACKED: |
| 1163 __ Ldr(current_input_offset(), register_location(reg)); | 1164 __ Ldr(current_input_offset(), register_location(reg)); |
| 1164 break; | 1165 break; |
| 1165 case CACHED_LSW: | 1166 case CACHED_LSW: |
| 1166 cached_register = GetCachedRegister(reg); | 1167 cached_register = GetCachedRegister(reg); |
| 1167 __ Mov(current_input_offset(), cached_register.W()); | 1168 __ Mov(current_input_offset(), cached_register.W()); |
| 1168 break; | 1169 break; |
| 1169 case CACHED_MSW: | 1170 case CACHED_MSW: |
| 1170 cached_register = GetCachedRegister(reg); | 1171 cached_register = GetCachedRegister(reg); |
| 1171 __ Lsr(current_input_offset().X(), cached_register, kWRegSize); | 1172 __ Lsr(current_input_offset().X(), cached_register, kWRegSizeInBits); |
| 1172 break; | 1173 break; |
| 1173 default: | 1174 default: |
| 1174 UNREACHABLE(); | 1175 UNREACHABLE(); |
| 1175 break; | 1176 break; |
| 1176 } | 1177 } |
| 1177 } | 1178 } |
| 1178 | 1179 |
| 1179 | 1180 |
| 1180 void RegExpMacroAssemblerA64::ReadStackPointerFromRegister(int reg) { | 1181 void RegExpMacroAssemblerA64::ReadStackPointerFromRegister(int reg) { |
| 1181 Register read_from = GetRegister(reg, w10); | 1182 Register read_from = GetRegister(reg, w10); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1256 ASSERT(reg_from >= kNumCachedRegisters); | 1257 ASSERT(reg_from >= kNumCachedRegisters); |
| 1257 | 1258 |
| 1258 // Move down the indexes of the registers on stack to get the correct offset | 1259 // Move down the indexes of the registers on stack to get the correct offset |
| 1259 // in memory. | 1260 // in memory. |
| 1260 reg_from -= kNumCachedRegisters; | 1261 reg_from -= kNumCachedRegisters; |
| 1261 reg_to -= kNumCachedRegisters; | 1262 reg_to -= kNumCachedRegisters; |
| 1262 // We should not unroll the loop for less than 2 registers. | 1263 // We should not unroll the loop for less than 2 registers. |
| 1263 STATIC_ASSERT(kNumRegistersToUnroll > 2); | 1264 STATIC_ASSERT(kNumRegistersToUnroll > 2); |
| 1264 // We position the base pointer to (reg_from + 1). | 1265 // We position the base pointer to (reg_from + 1). |
| 1265 int base_offset = kFirstRegisterOnStack - | 1266 int base_offset = kFirstRegisterOnStack - |
| 1266 kWRegSizeInBytes - (kWRegSizeInBytes * reg_from); | 1267 kWRegSize - (kWRegSize * reg_from); |
| 1267 if (num_registers > kNumRegistersToUnroll) { | 1268 if (num_registers > kNumRegistersToUnroll) { |
| 1268 Register base = x10; | 1269 Register base = x10; |
| 1269 __ Add(base, frame_pointer(), base_offset); | 1270 __ Add(base, frame_pointer(), base_offset); |
| 1270 | 1271 |
| 1271 Label loop; | 1272 Label loop; |
| 1272 __ Mov(x11, num_registers); | 1273 __ Mov(x11, num_registers); |
| 1273 __ Bind(&loop); | 1274 __ Bind(&loop); |
| 1274 __ Str(twice_non_position_value(), | 1275 __ Str(twice_non_position_value(), |
| 1275 MemOperand(base, -kPointerSize, PostIndex)); | 1276 MemOperand(base, -kPointerSize, PostIndex)); |
| 1276 __ Sub(x11, x11, 2); | 1277 __ Sub(x11, x11, 2); |
| 1277 __ Cbnz(x11, &loop); | 1278 __ Cbnz(x11, &loop); |
| 1278 } else { | 1279 } else { |
| 1279 for (int i = reg_from; i <= reg_to; i += 2) { | 1280 for (int i = reg_from; i <= reg_to; i += 2) { |
| 1280 __ Str(twice_non_position_value(), | 1281 __ Str(twice_non_position_value(), |
| 1281 MemOperand(frame_pointer(), base_offset)); | 1282 MemOperand(frame_pointer(), base_offset)); |
| 1282 base_offset -= kWRegSizeInBytes * 2; | 1283 base_offset -= kWRegSize * 2; |
| 1283 } | 1284 } |
| 1284 } | 1285 } |
| 1285 } | 1286 } |
| 1286 } | 1287 } |
| 1287 | 1288 |
| 1288 | 1289 |
| 1289 void RegExpMacroAssemblerA64::WriteStackPointerToRegister(int reg) { | 1290 void RegExpMacroAssemblerA64::WriteStackPointerToRegister(int reg) { |
| 1290 __ Ldr(x10, MemOperand(frame_pointer(), kStackBase)); | 1291 __ Ldr(x10, MemOperand(frame_pointer(), kStackBase)); |
| 1291 __ Sub(x10, backtrack_stackpointer(), x10); | 1292 __ Sub(x10, backtrack_stackpointer(), x10); |
| 1292 if (masm_->emit_debug_code()) { | 1293 if (masm_->emit_debug_code()) { |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1422 | 1423 |
| 1423 // Private methods: | 1424 // Private methods: |
| 1424 | 1425 |
| 1425 void RegExpMacroAssemblerA64::CallCheckStackGuardState(Register scratch) { | 1426 void RegExpMacroAssemblerA64::CallCheckStackGuardState(Register scratch) { |
| 1426 // Allocate space on the stack to store the return address. The | 1427 // Allocate space on the stack to store the return address. The |
| 1427 // CheckStackGuardState C++ function will override it if the code | 1428 // CheckStackGuardState C++ function will override it if the code |
| 1428 // moved. Allocate extra space for 2 arguments passed by pointers. | 1429 // moved. Allocate extra space for 2 arguments passed by pointers. |
| 1429 // AAPCS64 requires the stack to be 16 byte aligned. | 1430 // AAPCS64 requires the stack to be 16 byte aligned. |
| 1430 int alignment = masm_->ActivationFrameAlignment(); | 1431 int alignment = masm_->ActivationFrameAlignment(); |
| 1431 ASSERT_EQ(alignment % 16, 0); | 1432 ASSERT_EQ(alignment % 16, 0); |
| 1432 int align_mask = (alignment / kXRegSizeInBytes) - 1; | 1433 int align_mask = (alignment / kXRegSize) - 1; |
| 1433 int xreg_to_claim = (3 + align_mask) & ~align_mask; | 1434 int xreg_to_claim = (3 + align_mask) & ~align_mask; |
| 1434 | 1435 |
| 1435 ASSERT(csp.Is(__ StackPointer())); | 1436 ASSERT(csp.Is(__ StackPointer())); |
| 1436 __ Claim(xreg_to_claim); | 1437 __ Claim(xreg_to_claim); |
| 1437 | 1438 |
| 1438 // CheckStackGuardState needs the end and start addresses of the input string. | 1439 // CheckStackGuardState needs the end and start addresses of the input string. |
| 1439 __ Poke(input_end(), 2 * kPointerSize); | 1440 __ Poke(input_end(), 2 * kPointerSize); |
| 1440 __ Add(x5, csp, 2 * kPointerSize); | 1441 __ Add(x5, csp, 2 * kPointerSize); |
| 1441 __ Poke(input_start(), kPointerSize); | 1442 __ Poke(input_start(), kPointerSize); |
| 1442 __ Add(x4, csp, kPointerSize); | 1443 __ Add(x4, csp, kPointerSize); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1534 __ Cmp(backtrack_stackpointer(), x10); | 1535 __ Cmp(backtrack_stackpointer(), x10); |
| 1535 CallIf(&stack_overflow_label_, ls); | 1536 CallIf(&stack_overflow_label_, ls); |
| 1536 } | 1537 } |
| 1537 | 1538 |
| 1538 | 1539 |
| 1539 void RegExpMacroAssemblerA64::Push(Register source) { | 1540 void RegExpMacroAssemblerA64::Push(Register source) { |
| 1540 ASSERT(source.Is32Bits()); | 1541 ASSERT(source.Is32Bits()); |
| 1541 ASSERT(!source.is(backtrack_stackpointer())); | 1542 ASSERT(!source.is(backtrack_stackpointer())); |
| 1542 __ Str(source, | 1543 __ Str(source, |
| 1543 MemOperand(backtrack_stackpointer(), | 1544 MemOperand(backtrack_stackpointer(), |
| 1544 -static_cast<int>(kWRegSizeInBytes), | 1545 -static_cast<int>(kWRegSize), |
| 1545 PreIndex)); | 1546 PreIndex)); |
| 1546 } | 1547 } |
| 1547 | 1548 |
| 1548 | 1549 |
| 1549 void RegExpMacroAssemblerA64::Pop(Register target) { | 1550 void RegExpMacroAssemblerA64::Pop(Register target) { |
| 1550 ASSERT(target.Is32Bits()); | 1551 ASSERT(target.Is32Bits()); |
| 1551 ASSERT(!target.is(backtrack_stackpointer())); | 1552 ASSERT(!target.is(backtrack_stackpointer())); |
| 1552 __ Ldr(target, | 1553 __ Ldr(target, |
| 1553 MemOperand(backtrack_stackpointer(), kWRegSizeInBytes, PostIndex)); | 1554 MemOperand(backtrack_stackpointer(), kWRegSize, PostIndex)); |
| 1554 } | 1555 } |
| 1555 | 1556 |
| 1556 | 1557 |
| 1557 Register RegExpMacroAssemblerA64::GetCachedRegister(int register_index) { | 1558 Register RegExpMacroAssemblerA64::GetCachedRegister(int register_index) { |
| 1558 ASSERT(register_index < kNumCachedRegisters); | 1559 ASSERT(register_index < kNumCachedRegisters); |
| 1559 return Register::Create(register_index / 2, kXRegSize); | 1560 return Register::Create(register_index / 2, kXRegSizeInBits); |
| 1560 } | 1561 } |
| 1561 | 1562 |
| 1562 | 1563 |
| 1563 Register RegExpMacroAssemblerA64::GetRegister(int register_index, | 1564 Register RegExpMacroAssemblerA64::GetRegister(int register_index, |
| 1564 Register maybe_result) { | 1565 Register maybe_result) { |
| 1565 ASSERT(maybe_result.Is32Bits()); | 1566 ASSERT(maybe_result.Is32Bits()); |
| 1566 ASSERT(register_index >= 0); | 1567 ASSERT(register_index >= 0); |
| 1567 if (num_registers_ <= register_index) { | 1568 if (num_registers_ <= register_index) { |
| 1568 num_registers_ = register_index + 1; | 1569 num_registers_ = register_index + 1; |
| 1569 } | 1570 } |
| 1570 Register result; | 1571 Register result; |
| 1571 RegisterState register_state = GetRegisterState(register_index); | 1572 RegisterState register_state = GetRegisterState(register_index); |
| 1572 switch (register_state) { | 1573 switch (register_state) { |
| 1573 case STACKED: | 1574 case STACKED: |
| 1574 __ Ldr(maybe_result, register_location(register_index)); | 1575 __ Ldr(maybe_result, register_location(register_index)); |
| 1575 result = maybe_result; | 1576 result = maybe_result; |
| 1576 break; | 1577 break; |
| 1577 case CACHED_LSW: | 1578 case CACHED_LSW: |
| 1578 result = GetCachedRegister(register_index).W(); | 1579 result = GetCachedRegister(register_index).W(); |
| 1579 break; | 1580 break; |
| 1580 case CACHED_MSW: | 1581 case CACHED_MSW: |
| 1581 __ Lsr(maybe_result.X(), GetCachedRegister(register_index), kWRegSize); | 1582 __ Lsr(maybe_result.X(), GetCachedRegister(register_index), |
| 1583 kWRegSizeInBits); |
| 1582 result = maybe_result; | 1584 result = maybe_result; |
| 1583 break; | 1585 break; |
| 1584 default: | 1586 default: |
| 1585 UNREACHABLE(); | 1587 UNREACHABLE(); |
| 1586 break; | 1588 break; |
| 1587 } | 1589 } |
| 1588 ASSERT(result.Is32Bits()); | 1590 ASSERT(result.Is32Bits()); |
| 1589 return result; | 1591 return result; |
| 1590 } | 1592 } |
| 1591 | 1593 |
| 1592 | 1594 |
| 1593 void RegExpMacroAssemblerA64::StoreRegister(int register_index, | 1595 void RegExpMacroAssemblerA64::StoreRegister(int register_index, |
| 1594 Register source) { | 1596 Register source) { |
| 1595 ASSERT(source.Is32Bits()); | 1597 ASSERT(source.Is32Bits()); |
| 1596 ASSERT(register_index >= 0); | 1598 ASSERT(register_index >= 0); |
| 1597 if (num_registers_ <= register_index) { | 1599 if (num_registers_ <= register_index) { |
| 1598 num_registers_ = register_index + 1; | 1600 num_registers_ = register_index + 1; |
| 1599 } | 1601 } |
| 1600 | 1602 |
| 1601 Register cached_register; | 1603 Register cached_register; |
| 1602 RegisterState register_state = GetRegisterState(register_index); | 1604 RegisterState register_state = GetRegisterState(register_index); |
| 1603 switch (register_state) { | 1605 switch (register_state) { |
| 1604 case STACKED: | 1606 case STACKED: |
| 1605 __ Str(source, register_location(register_index)); | 1607 __ Str(source, register_location(register_index)); |
| 1606 break; | 1608 break; |
| 1607 case CACHED_LSW: | 1609 case CACHED_LSW: |
| 1608 cached_register = GetCachedRegister(register_index); | 1610 cached_register = GetCachedRegister(register_index); |
| 1609 if (!source.Is(cached_register.W())) { | 1611 if (!source.Is(cached_register.W())) { |
| 1610 __ Bfi(cached_register, source.X(), 0, kWRegSize); | 1612 __ Bfi(cached_register, source.X(), 0, kWRegSizeInBits); |
| 1611 } | 1613 } |
| 1612 break; | 1614 break; |
| 1613 case CACHED_MSW: | 1615 case CACHED_MSW: |
| 1614 cached_register = GetCachedRegister(register_index); | 1616 cached_register = GetCachedRegister(register_index); |
| 1615 __ Bfi(cached_register, source.X(), kWRegSize, kWRegSize); | 1617 __ Bfi(cached_register, source.X(), kWRegSizeInBits, kWRegSizeInBits); |
| 1616 break; | 1618 break; |
| 1617 default: | 1619 default: |
| 1618 UNREACHABLE(); | 1620 UNREACHABLE(); |
| 1619 break; | 1621 break; |
| 1620 } | 1622 } |
| 1621 } | 1623 } |
| 1622 | 1624 |
| 1623 | 1625 |
| 1624 void RegExpMacroAssemblerA64::CallIf(Label* to, Condition condition) { | 1626 void RegExpMacroAssemblerA64::CallIf(Label* to, Condition condition) { |
| 1625 Label skip_call; | 1627 Label skip_call; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1643 } | 1645 } |
| 1644 | 1646 |
| 1645 | 1647 |
| 1646 MemOperand RegExpMacroAssemblerA64::register_location(int register_index) { | 1648 MemOperand RegExpMacroAssemblerA64::register_location(int register_index) { |
| 1647 ASSERT(register_index < (1<<30)); | 1649 ASSERT(register_index < (1<<30)); |
| 1648 ASSERT(register_index >= kNumCachedRegisters); | 1650 ASSERT(register_index >= kNumCachedRegisters); |
| 1649 if (num_registers_ <= register_index) { | 1651 if (num_registers_ <= register_index) { |
| 1650 num_registers_ = register_index + 1; | 1652 num_registers_ = register_index + 1; |
| 1651 } | 1653 } |
| 1652 register_index -= kNumCachedRegisters; | 1654 register_index -= kNumCachedRegisters; |
| 1653 int offset = kFirstRegisterOnStack - register_index * kWRegSizeInBytes; | 1655 int offset = kFirstRegisterOnStack - register_index * kWRegSize; |
| 1654 return MemOperand(frame_pointer(), offset); | 1656 return MemOperand(frame_pointer(), offset); |
| 1655 } | 1657 } |
| 1656 | 1658 |
| 1657 MemOperand RegExpMacroAssemblerA64::capture_location(int register_index, | 1659 MemOperand RegExpMacroAssemblerA64::capture_location(int register_index, |
| 1658 Register scratch) { | 1660 Register scratch) { |
| 1659 ASSERT(register_index < (1<<30)); | 1661 ASSERT(register_index < (1<<30)); |
| 1660 ASSERT(register_index < num_saved_registers_); | 1662 ASSERT(register_index < num_saved_registers_); |
| 1661 ASSERT(register_index >= kNumCachedRegisters); | 1663 ASSERT(register_index >= kNumCachedRegisters); |
| 1662 ASSERT_EQ(register_index % 2, 0); | 1664 ASSERT_EQ(register_index % 2, 0); |
| 1663 register_index -= kNumCachedRegisters; | 1665 register_index -= kNumCachedRegisters; |
| 1664 int offset = kFirstCaptureOnStack - register_index * kWRegSizeInBytes; | 1666 int offset = kFirstCaptureOnStack - register_index * kWRegSize; |
| 1665 // capture_location is used with Stp instructions to load/store 2 registers. | 1667 // capture_location is used with Stp instructions to load/store 2 registers. |
| 1666 // The immediate field in the encoding is limited to 7 bits (signed). | 1668 // The immediate field in the encoding is limited to 7 bits (signed). |
| 1667 if (is_int7(offset)) { | 1669 if (is_int7(offset)) { |
| 1668 return MemOperand(frame_pointer(), offset); | 1670 return MemOperand(frame_pointer(), offset); |
| 1669 } else { | 1671 } else { |
| 1670 __ Add(scratch, frame_pointer(), offset); | 1672 __ Add(scratch, frame_pointer(), offset); |
| 1671 return MemOperand(scratch); | 1673 return MemOperand(scratch); |
| 1672 } | 1674 } |
| 1673 } | 1675 } |
| 1674 | 1676 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1719 __ Ldrh(current_character(), MemOperand(input_end(), offset, SXTW)); | 1721 __ Ldrh(current_character(), MemOperand(input_end(), offset, SXTW)); |
| 1720 } | 1722 } |
| 1721 } | 1723 } |
| 1722 } | 1724 } |
| 1723 | 1725 |
| 1724 #endif // V8_INTERPRETED_REGEXP | 1726 #endif // V8_INTERPRETED_REGEXP |
| 1725 | 1727 |
| 1726 }} // namespace v8::internal | 1728 }} // namespace v8::internal |
| 1727 | 1729 |
| 1728 #endif // V8_TARGET_ARCH_A64 | 1730 #endif // V8_TARGET_ARCH_A64 |
| OLD | NEW |