OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 * int start_index, | 108 * int start_index, |
109 * Address start, | 109 * Address start, |
110 * Address end, | 110 * Address end, |
111 * int* capture_output_array, | 111 * int* capture_output_array, |
112 * bool at_start, | 112 * bool at_start, |
113 * byte* stack_area_base, | 113 * byte* stack_area_base, |
114 * bool direct_call) | 114 * bool direct_call) |
115 */ | 115 */ |
116 | 116 |
117 #define __ ACCESS_MASM((&masm_)) | 117 #define __ ACCESS_MASM((&masm_)) |
| 118 #define __k __ |
118 | 119 |
119 RegExpMacroAssemblerX64::RegExpMacroAssemblerX64( | 120 RegExpMacroAssemblerX64::RegExpMacroAssemblerX64( |
120 Mode mode, | 121 Mode mode, |
121 int registers_to_save, | 122 int registers_to_save, |
122 Zone* zone) | 123 Zone* zone) |
123 : NativeRegExpMacroAssembler(zone), | 124 : NativeRegExpMacroAssembler(zone), |
124 masm_(zone->isolate(), NULL, kRegExpCodeSize), | 125 masm_(zone->isolate(), NULL, kRegExpCodeSize), |
125 no_root_array_scope_(&masm_), | 126 no_root_array_scope_(&masm_), |
126 code_relative_fixup_positions_(4, zone), | 127 code_relative_fixup_positions_(4, zone), |
127 mode_(mode), | 128 mode_(mode), |
(...skipping 22 matching lines...) Expand all Loading... |
150 } | 151 } |
151 | 152 |
152 | 153 |
153 int RegExpMacroAssemblerX64::stack_limit_slack() { | 154 int RegExpMacroAssemblerX64::stack_limit_slack() { |
154 return RegExpStack::kStackLimitSlack; | 155 return RegExpStack::kStackLimitSlack; |
155 } | 156 } |
156 | 157 |
157 | 158 |
158 void RegExpMacroAssemblerX64::AdvanceCurrentPosition(int by) { | 159 void RegExpMacroAssemblerX64::AdvanceCurrentPosition(int by) { |
159 if (by != 0) { | 160 if (by != 0) { |
160 __ addq(rdi, Immediate(by * char_size())); | 161 __k addq(rdi, Immediate(by * char_size())); |
161 } | 162 } |
162 } | 163 } |
163 | 164 |
164 | 165 |
165 void RegExpMacroAssemblerX64::AdvanceRegister(int reg, int by) { | 166 void RegExpMacroAssemblerX64::AdvanceRegister(int reg, int by) { |
166 ASSERT(reg >= 0); | 167 ASSERT(reg >= 0); |
167 ASSERT(reg < num_registers_); | 168 ASSERT(reg < num_registers_); |
168 if (by != 0) { | 169 if (by != 0) { |
169 __ addq(register_location(reg), Immediate(by)); | 170 __ addq(register_location(reg), Immediate(by)); |
170 } | 171 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 Drop(); | 235 Drop(); |
235 BranchOrBacktrack(no_condition, on_equal); | 236 BranchOrBacktrack(no_condition, on_equal); |
236 __ bind(&fallthrough); | 237 __ bind(&fallthrough); |
237 } | 238 } |
238 | 239 |
239 | 240 |
240 void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase( | 241 void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase( |
241 int start_reg, | 242 int start_reg, |
242 Label* on_no_match) { | 243 Label* on_no_match) { |
243 Label fallthrough; | 244 Label fallthrough; |
| 245 #ifndef V8_TARGET_ARCH_X32 |
244 __ movq(rdx, register_location(start_reg)); // Offset of start of capture | 246 __ movq(rdx, register_location(start_reg)); // Offset of start of capture |
245 __ movq(rbx, register_location(start_reg + 1)); // Offset of end of capture | 247 __ movq(rbx, register_location(start_reg + 1)); // Offset of end of capture |
| 248 #else |
| 249 __ movsxlq(rdx, register_location(start_reg)); // Offset of start of capture |
| 250 // Offset of end of capture |
| 251 __ movsxlq(rbx, register_location(start_reg + 1)); |
| 252 #endif |
246 __ subq(rbx, rdx); // Length of capture. | 253 __ subq(rbx, rdx); // Length of capture. |
247 | 254 |
248 // ----------------------- | 255 // ----------------------- |
249 // rdx = Start offset of capture. | 256 // rdx = Start offset of capture. |
250 // rbx = Length of capture | 257 // rbx = Length of capture |
251 | 258 |
252 // If length is negative, this code will fail (it's a symptom of a partial or | 259 // If length is negative, this code will fail (it's a symptom of a partial or |
253 // illegal capture where start of capture after end of capture). | 260 // illegal capture where start of capture after end of capture). |
254 // This must not happen (no back-reference can reference a capture that wasn't | 261 // This must not happen (no back-reference can reference a capture that wasn't |
255 // closed before in the reg-exp, and we must not generate code that can cause | 262 // closed before in the reg-exp, and we must not generate code that can cause |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 __ bind(&loop_increment); | 316 __ bind(&loop_increment); |
310 // Increment pointers into match and capture strings. | 317 // Increment pointers into match and capture strings. |
311 __ addq(r11, Immediate(1)); | 318 __ addq(r11, Immediate(1)); |
312 __ addq(r9, Immediate(1)); | 319 __ addq(r9, Immediate(1)); |
313 // Compare to end of capture, and loop if not done. | 320 // Compare to end of capture, and loop if not done. |
314 __ cmpq(r9, rbx); | 321 __ cmpq(r9, rbx); |
315 __ j(below, &loop); | 322 __ j(below, &loop); |
316 | 323 |
317 // Compute new value of character position after the matched part. | 324 // Compute new value of character position after the matched part. |
318 __ movq(rdi, r11); | 325 __ movq(rdi, r11); |
319 __ subq(rdi, rsi); | 326 __k subq(rdi, rsi); |
320 } else { | 327 } else { |
321 ASSERT(mode_ == UC16); | 328 ASSERT(mode_ == UC16); |
322 // Save important/volatile registers before calling C function. | 329 // Save important/volatile registers before calling C function. |
323 #ifndef _WIN64 | 330 #ifndef _WIN64 |
324 // Caller save on Linux and callee save in Windows. | 331 // Caller save on Linux and callee save in Windows. |
325 __ push(rsi); | 332 __k push(rsi); |
326 __ push(rdi); | 333 __k push(rdi); |
327 #endif | 334 #endif |
328 __ push(backtrack_stackpointer()); | 335 __k push(backtrack_stackpointer()); |
329 | 336 |
330 static const int num_arguments = 4; | 337 static const int num_arguments = 4; |
331 __ PrepareCallCFunction(num_arguments); | 338 __ PrepareCallCFunction(num_arguments); |
332 | 339 |
333 // Put arguments into parameter registers. Parameters are | 340 // Put arguments into parameter registers. Parameters are |
334 // Address byte_offset1 - Address captured substring's start. | 341 // Address byte_offset1 - Address captured substring's start. |
335 // Address byte_offset2 - Address of current character position. | 342 // Address byte_offset2 - Address of current character position. |
336 // size_t byte_length - length of capture in bytes(!) | 343 // size_t byte_length - length of capture in bytes(!) |
337 // Isolate* isolate | 344 // Isolate* isolate |
338 #ifdef _WIN64 | 345 #ifdef _WIN64 |
(...skipping 21 matching lines...) Expand all Loading... |
360 { // NOLINT: Can't find a way to open this scope without confusing the | 367 { // NOLINT: Can't find a way to open this scope without confusing the |
361 // linter. | 368 // linter. |
362 AllowExternalCallThatCantCauseGC scope(&masm_); | 369 AllowExternalCallThatCantCauseGC scope(&masm_); |
363 ExternalReference compare = | 370 ExternalReference compare = |
364 ExternalReference::re_case_insensitive_compare_uc16(isolate()); | 371 ExternalReference::re_case_insensitive_compare_uc16(isolate()); |
365 __ CallCFunction(compare, num_arguments); | 372 __ CallCFunction(compare, num_arguments); |
366 } | 373 } |
367 | 374 |
368 // Restore original values before reacting on result value. | 375 // Restore original values before reacting on result value. |
369 __ Move(code_object_pointer(), masm_.CodeObject()); | 376 __ Move(code_object_pointer(), masm_.CodeObject()); |
370 __ pop(backtrack_stackpointer()); | 377 __k pop(backtrack_stackpointer()); |
371 #ifndef _WIN64 | 378 #ifndef _WIN64 |
372 __ pop(rdi); | 379 __k pop(rdi); |
373 __ pop(rsi); | 380 __k pop(rsi); |
374 #endif | 381 #endif |
375 | 382 |
376 // Check if function returned non-zero for success or zero for failure. | 383 // Check if function returned non-zero for success or zero for failure. |
377 __ testq(rax, rax); | 384 __ testq(rax, rax); |
378 BranchOrBacktrack(zero, on_no_match); | 385 BranchOrBacktrack(zero, on_no_match); |
379 // On success, increment position by length of capture. | 386 // On success, increment position by length of capture. |
380 // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs). | 387 // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs). |
381 __ addq(rdi, rbx); | 388 __k addq(rdi, rbx); |
382 } | 389 } |
383 __ bind(&fallthrough); | 390 __ bind(&fallthrough); |
384 } | 391 } |
385 | 392 |
386 | 393 |
387 void RegExpMacroAssemblerX64::CheckNotBackReference( | 394 void RegExpMacroAssemblerX64::CheckNotBackReference( |
388 int start_reg, | 395 int start_reg, |
389 Label* on_no_match) { | 396 Label* on_no_match) { |
390 Label fallthrough; | 397 Label fallthrough; |
391 | 398 |
392 // Find length of back-referenced capture. | 399 // Find length of back-referenced capture. |
| 400 #ifndef V8_TARGET_ARCH_X32 |
393 __ movq(rdx, register_location(start_reg)); | 401 __ movq(rdx, register_location(start_reg)); |
394 __ movq(rax, register_location(start_reg + 1)); | 402 __ movq(rax, register_location(start_reg + 1)); |
| 403 #else |
| 404 __ movsxlq(rdx, register_location(start_reg)); |
| 405 __ movsxlq(rax, register_location(start_reg + 1)); |
| 406 #endif |
395 __ subq(rax, rdx); // Length to check. | 407 __ subq(rax, rdx); // Length to check. |
396 | 408 |
397 // Fail on partial or illegal capture (start of capture after end of capture). | 409 // Fail on partial or illegal capture (start of capture after end of capture). |
398 // This must not happen (no back-reference can reference a capture that wasn't | 410 // This must not happen (no back-reference can reference a capture that wasn't |
399 // closed before in the reg-exp). | 411 // closed before in the reg-exp). |
400 __ Check(greater_equal, "Invalid capture referenced"); | 412 __ Check(greater_equal, "Invalid capture referenced"); |
401 | 413 |
402 // Succeed on empty capture (including non-participating capture) | 414 // Succeed on empty capture (including non-participating capture) |
403 __ j(equal, &fallthrough); | 415 __ j(equal, &fallthrough); |
404 | 416 |
(...skipping 30 matching lines...) Expand all Loading... |
435 // Increment pointers into capture and match string. | 447 // Increment pointers into capture and match string. |
436 __ addq(rbx, Immediate(char_size())); | 448 __ addq(rbx, Immediate(char_size())); |
437 __ addq(rdx, Immediate(char_size())); | 449 __ addq(rdx, Immediate(char_size())); |
438 // Check if we have reached end of match area. | 450 // Check if we have reached end of match area. |
439 __ cmpq(rdx, r9); | 451 __ cmpq(rdx, r9); |
440 __ j(below, &loop); | 452 __ j(below, &loop); |
441 | 453 |
442 // Success. | 454 // Success. |
443 // Set current character position to position after match. | 455 // Set current character position to position after match. |
444 __ movq(rdi, rbx); | 456 __ movq(rdi, rbx); |
445 __ subq(rdi, rsi); | 457 __k subq(rdi, rsi); |
446 | 458 |
447 __ bind(&fallthrough); | 459 __ bind(&fallthrough); |
448 } | 460 } |
449 | 461 |
450 | 462 |
451 void RegExpMacroAssemblerX64::CheckNotCharacter(uint32_t c, | 463 void RegExpMacroAssemblerX64::CheckNotCharacter(uint32_t c, |
452 Label* on_not_equal) { | 464 Label* on_not_equal) { |
453 __ cmpl(current_character(), Immediate(c)); | 465 __ cmpl(current_character(), Immediate(c)); |
454 BranchOrBacktrack(not_equal, on_not_equal); | 466 BranchOrBacktrack(not_equal, on_not_equal); |
455 } | 467 } |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 FrameScope scope(&masm_, StackFrame::MANUAL); | 686 FrameScope scope(&masm_, StackFrame::MANUAL); |
675 | 687 |
676 // Actually emit code to start a new stack frame. | 688 // Actually emit code to start a new stack frame. |
677 __ push(rbp); | 689 __ push(rbp); |
678 __ movq(rbp, rsp); | 690 __ movq(rbp, rsp); |
679 // Save parameters and callee-save registers. Order here should correspond | 691 // Save parameters and callee-save registers. Order here should correspond |
680 // to order of kBackup_ebx etc. | 692 // to order of kBackup_ebx etc. |
681 #ifdef _WIN64 | 693 #ifdef _WIN64 |
682 // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots. | 694 // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots. |
683 // Store register parameters in pre-allocated stack slots, | 695 // Store register parameters in pre-allocated stack slots, |
684 __ movq(Operand(rbp, kInputString), rcx); | 696 __k movq(Operand(rbp, kInputString), rcx); |
685 __ movq(Operand(rbp, kStartIndex), rdx); // Passed as int32 in edx. | 697 __k movq(Operand(rbp, kStartIndex), rdx); // Passed as int32 in edx. |
686 __ movq(Operand(rbp, kInputStart), r8); | 698 __k movq(Operand(rbp, kInputStart), r8); |
687 __ movq(Operand(rbp, kInputEnd), r9); | 699 __k movq(Operand(rbp, kInputEnd), r9); |
688 // Callee-save on Win64. | 700 // Callee-save on Win64. |
689 __ push(rsi); | 701 __k push(rsi); |
690 __ push(rdi); | 702 __k push(rdi); |
691 __ push(rbx); | 703 __k push(rbx); |
692 #else | 704 #else |
693 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9 (and then on stack). | 705 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9 (and then on stack). |
694 // Push register parameters on stack for reference. | 706 // Push register parameters on stack for reference. |
| 707 #ifndef V8_TARGET_ARCH_X32 |
695 ASSERT_EQ(kInputString, -1 * kPointerSize); | 708 ASSERT_EQ(kInputString, -1 * kPointerSize); |
696 ASSERT_EQ(kStartIndex, -2 * kPointerSize); | 709 ASSERT_EQ(kStartIndex, -2 * kPointerSize); |
697 ASSERT_EQ(kInputStart, -3 * kPointerSize); | 710 ASSERT_EQ(kInputStart, -3 * kPointerSize); |
698 ASSERT_EQ(kInputEnd, -4 * kPointerSize); | 711 ASSERT_EQ(kInputEnd, -4 * kPointerSize); |
699 ASSERT_EQ(kRegisterOutput, -5 * kPointerSize); | 712 ASSERT_EQ(kRegisterOutput, -5 * kPointerSize); |
700 ASSERT_EQ(kNumOutputRegisters, -6 * kPointerSize); | 713 ASSERT_EQ(kNumOutputRegisters, -6 * kPointerSize); |
701 __ push(rdi); | 714 #else |
702 __ push(rsi); | 715 ASSERT_EQ(kInputString, -1 * kHWRegSize); |
703 __ push(rdx); | 716 ASSERT_EQ(kStartIndex, -2 * kHWRegSize); |
704 __ push(rcx); | 717 ASSERT_EQ(kInputStart, -3 * kHWRegSize); |
705 __ push(r8); | 718 ASSERT_EQ(kInputEnd, -4 * kHWRegSize); |
706 __ push(r9); | 719 ASSERT_EQ(kRegisterOutput, -5 * kHWRegSize); |
| 720 ASSERT_EQ(kNumOutputRegisters, -6 * kHWRegSize); |
| 721 #endif |
| 722 __k push(rdi); |
| 723 __k push(rsi); |
| 724 __k push(rdx); |
| 725 __k push(rcx); |
| 726 __k push(r8); |
| 727 __k push(r9); |
707 | 728 |
708 __ push(rbx); // Callee-save | 729 __k push(rbx); // Callee-save |
709 #endif | 730 #endif |
710 | 731 |
711 __ push(Immediate(0)); // Number of successful matches in a global regexp. | 732 __ push(Immediate(0)); // Number of successful matches in a global regexp. |
712 __ push(Immediate(0)); // Make room for "input start - 1" constant. | 733 __ push(Immediate(0)); // Make room for "input start - 1" constant. |
713 | 734 |
714 // Check if we have space on the stack for registers. | 735 // Check if we have space on the stack for registers. |
715 Label stack_limit_hit; | 736 Label stack_limit_hit; |
716 Label stack_ok; | 737 Label stack_ok; |
717 | 738 |
718 ExternalReference stack_limit = | 739 ExternalReference stack_limit = |
(...skipping 21 matching lines...) Expand all Loading... |
740 | 761 |
741 __ bind(&stack_ok); | 762 __ bind(&stack_ok); |
742 | 763 |
743 // Allocate space on stack for registers. | 764 // Allocate space on stack for registers. |
744 __ subq(rsp, Immediate(num_registers_ * kPointerSize)); | 765 __ subq(rsp, Immediate(num_registers_ * kPointerSize)); |
745 // Load string length. | 766 // Load string length. |
746 __ movq(rsi, Operand(rbp, kInputEnd)); | 767 __ movq(rsi, Operand(rbp, kInputEnd)); |
747 // Load input position. | 768 // Load input position. |
748 __ movq(rdi, Operand(rbp, kInputStart)); | 769 __ movq(rdi, Operand(rbp, kInputStart)); |
749 // Set up rdi to be negative offset from string end. | 770 // Set up rdi to be negative offset from string end. |
750 __ subq(rdi, rsi); | 771 __k subq(rdi, rsi); |
751 // Set rax to address of char before start of the string | 772 // Set rax to address of char before start of the string |
752 // (effectively string position -1). | 773 // (effectively string position -1). |
753 __ movq(rbx, Operand(rbp, kStartIndex)); | 774 __ movq(rbx, Operand(rbp, kStartIndex)); |
754 __ neg(rbx); | 775 __k neg(rbx); |
755 if (mode_ == UC16) { | 776 if (mode_ == UC16) { |
756 __ lea(rax, Operand(rdi, rbx, times_2, -char_size())); | 777 __ lea(rax, Operand(rdi, rbx, times_2, -char_size())); |
757 } else { | 778 } else { |
758 __ lea(rax, Operand(rdi, rbx, times_1, -char_size())); | 779 __ lea(rax, Operand(rdi, rbx, times_1, -char_size())); |
759 } | 780 } |
760 // Store this value in a local variable, for use when clearing | 781 // Store this value in a local variable, for use when clearing |
761 // position registers. | 782 // position registers. |
762 __ movq(Operand(rbp, kInputStartMinusOne), rax); | 783 __ movq(Operand(rbp, kInputStartMinusOne), rax); |
763 | 784 |
764 #ifdef WIN32 | 785 #ifdef WIN32 |
(...skipping 27 matching lines...) Expand all Loading... |
792 // Initialize on-stack registers. | 813 // Initialize on-stack registers. |
793 if (num_saved_registers_ > 0) { | 814 if (num_saved_registers_ > 0) { |
794 // Fill saved registers with initial value = start offset - 1 | 815 // Fill saved registers with initial value = start offset - 1 |
795 // Fill in stack push order, to avoid accessing across an unwritten | 816 // Fill in stack push order, to avoid accessing across an unwritten |
796 // page (a problem on Windows). | 817 // page (a problem on Windows). |
797 if (num_saved_registers_ > 8) { | 818 if (num_saved_registers_ > 8) { |
798 __ Set(rcx, kRegisterZero); | 819 __ Set(rcx, kRegisterZero); |
799 Label init_loop; | 820 Label init_loop; |
800 __ bind(&init_loop); | 821 __ bind(&init_loop); |
801 __ movq(Operand(rbp, rcx, times_1, 0), rax); | 822 __ movq(Operand(rbp, rcx, times_1, 0), rax); |
802 __ subq(rcx, Immediate(kPointerSize)); | 823 __k subq(rcx, Immediate(kPointerSize)); |
803 __ cmpq(rcx, | 824 __k cmpq(rcx, |
804 Immediate(kRegisterZero - num_saved_registers_ * kPointerSize)); | 825 Immediate(kRegisterZero - num_saved_registers_ * kPointerSize)); |
805 __ j(greater, &init_loop); | 826 __ j(greater, &init_loop); |
806 } else { // Unroll the loop. | 827 } else { // Unroll the loop. |
807 for (int i = 0; i < num_saved_registers_; i++) { | 828 for (int i = 0; i < num_saved_registers_; i++) { |
808 __ movq(register_location(i), rax); | 829 __ movq(register_location(i), rax); |
809 } | 830 } |
810 } | 831 } |
811 } | 832 } |
812 | 833 |
813 // Initialize backtrack stack pointer. | 834 // Initialize backtrack stack pointer. |
(...skipping 10 matching lines...) Expand all Loading... |
824 __ movq(rdx, Operand(rbp, kStartIndex)); | 845 __ movq(rdx, Operand(rbp, kStartIndex)); |
825 __ movq(rbx, Operand(rbp, kRegisterOutput)); | 846 __ movq(rbx, Operand(rbp, kRegisterOutput)); |
826 __ movq(rcx, Operand(rbp, kInputEnd)); | 847 __ movq(rcx, Operand(rbp, kInputEnd)); |
827 __ subq(rcx, Operand(rbp, kInputStart)); | 848 __ subq(rcx, Operand(rbp, kInputStart)); |
828 if (mode_ == UC16) { | 849 if (mode_ == UC16) { |
829 __ lea(rcx, Operand(rcx, rdx, times_2, 0)); | 850 __ lea(rcx, Operand(rcx, rdx, times_2, 0)); |
830 } else { | 851 } else { |
831 __ addq(rcx, rdx); | 852 __ addq(rcx, rdx); |
832 } | 853 } |
833 for (int i = 0; i < num_saved_registers_; i++) { | 854 for (int i = 0; i < num_saved_registers_; i++) { |
| 855 #ifndef V8_TARGET_ARCH_X32 |
834 __ movq(rax, register_location(i)); | 856 __ movq(rax, register_location(i)); |
| 857 #else |
| 858 __ movsxlq(rax, register_location(i)); |
| 859 #endif |
835 if (i == 0 && global_with_zero_length_check()) { | 860 if (i == 0 && global_with_zero_length_check()) { |
836 // Keep capture start in rdx for the zero-length check later. | 861 // Keep capture start in rdx for the zero-length check later. |
837 __ movq(rdx, rax); | 862 __ movq(rdx, rax); |
838 } | 863 } |
839 __ addq(rax, rcx); // Convert to index from start, not end. | 864 __ addq(rax, rcx); // Convert to index from start, not end. |
840 if (mode_ == UC16) { | 865 if (mode_ == UC16) { |
841 __ sar(rax, Immediate(1)); // Convert byte index to character index. | 866 __ sar(rax, Immediate(1)); // Convert byte index to character index. |
842 } | 867 } |
843 __ movl(Operand(rbx, i * kIntSize), rax); | 868 __ movl(Operand(rbx, i * kIntSize), rax); |
844 } | 869 } |
(...skipping 23 matching lines...) Expand all Loading... |
868 // Special case for zero-length matches. | 893 // Special case for zero-length matches. |
869 // rdx: capture start index | 894 // rdx: capture start index |
870 __ cmpq(rdi, rdx); | 895 __ cmpq(rdi, rdx); |
871 // Not a zero-length match, restart. | 896 // Not a zero-length match, restart. |
872 __ j(not_equal, &load_char_start_regexp); | 897 __ j(not_equal, &load_char_start_regexp); |
873 // rdi (offset from the end) is zero if we already reached the end. | 898 // rdi (offset from the end) is zero if we already reached the end. |
874 __ testq(rdi, rdi); | 899 __ testq(rdi, rdi); |
875 __ j(zero, &exit_label_, Label::kNear); | 900 __ j(zero, &exit_label_, Label::kNear); |
876 // Advance current position after a zero-length match. | 901 // Advance current position after a zero-length match. |
877 if (mode_ == UC16) { | 902 if (mode_ == UC16) { |
878 __ addq(rdi, Immediate(2)); | 903 __k addq(rdi, Immediate(2)); |
879 } else { | 904 } else { |
880 __ incq(rdi); | 905 __k incq(rdi); |
881 } | 906 } |
882 } | 907 } |
883 | 908 |
884 __ jmp(&load_char_start_regexp); | 909 __ jmp(&load_char_start_regexp); |
885 } else { | 910 } else { |
886 __ movq(rax, Immediate(SUCCESS)); | 911 __ movq(rax, Immediate(SUCCESS)); |
887 } | 912 } |
888 } | 913 } |
889 | 914 |
890 __ bind(&exit_label_); | 915 __ bind(&exit_label_); |
891 if (global()) { | 916 if (global()) { |
892 // Return the number of successful captures. | 917 // Return the number of successful captures. |
893 __ movq(rax, Operand(rbp, kSuccessfulCaptures)); | 918 __ movq(rax, Operand(rbp, kSuccessfulCaptures)); |
894 } | 919 } |
895 | 920 |
896 __ bind(&return_rax); | 921 __ bind(&return_rax); |
897 #ifdef _WIN64 | 922 #ifdef _WIN64 |
898 // Restore callee save registers. | 923 // Restore callee save registers. |
899 __ lea(rsp, Operand(rbp, kLastCalleeSaveRegister)); | 924 __ lea(rsp, Operand(rbp, kLastCalleeSaveRegister)); |
900 __ pop(rbx); | 925 __k pop(rbx); |
901 __ pop(rdi); | 926 __k pop(rdi); |
902 __ pop(rsi); | 927 __k pop(rsi); |
903 // Stack now at rbp. | 928 // Stack now at rbp. |
904 #else | 929 #else |
905 // Restore callee save register. | 930 // Restore callee save register. |
906 __ movq(rbx, Operand(rbp, kBackup_rbx)); | 931 __ movq(rbx, Operand(rbp, kBackup_rbx)); |
907 // Skip rsp to rbp. | 932 // Skip rsp to rbp. |
908 __ movq(rsp, rbp); | 933 __ movq(rsp, rbp); |
909 #endif | 934 #endif |
910 // Exit function frame, restore previous one. | 935 // Exit function frame, restore previous one. |
911 __ pop(rbp); | 936 __ pop(rbp); |
912 __ ret(0); | 937 __ ret(0); |
913 | 938 |
914 // Backtrack code (branch target for conditional backtracks). | 939 // Backtrack code (branch target for conditional backtracks). |
915 if (backtrack_label_.is_linked()) { | 940 if (backtrack_label_.is_linked()) { |
916 __ bind(&backtrack_label_); | 941 __ bind(&backtrack_label_); |
917 Backtrack(); | 942 Backtrack(); |
918 } | 943 } |
919 | 944 |
920 Label exit_with_exception; | 945 Label exit_with_exception; |
921 | 946 |
922 // Preempt-code | 947 // Preempt-code |
923 if (check_preempt_label_.is_linked()) { | 948 if (check_preempt_label_.is_linked()) { |
924 SafeCallTarget(&check_preempt_label_); | 949 SafeCallTarget(&check_preempt_label_); |
925 | 950 |
926 __ push(backtrack_stackpointer()); | 951 __k push(backtrack_stackpointer()); |
927 __ push(rdi); | 952 __k push(rdi); |
928 | 953 |
929 CallCheckStackGuardState(); | 954 CallCheckStackGuardState(); |
930 __ testq(rax, rax); | 955 __ testq(rax, rax); |
931 // If returning non-zero, we should end execution with the given | 956 // If returning non-zero, we should end execution with the given |
932 // result as return value. | 957 // result as return value. |
933 __ j(not_zero, &return_rax); | 958 __ j(not_zero, &return_rax); |
934 | 959 |
935 // Restore registers. | 960 // Restore registers. |
936 __ Move(code_object_pointer(), masm_.CodeObject()); | 961 __ Move(code_object_pointer(), masm_.CodeObject()); |
937 __ pop(rdi); | 962 __k pop(rdi); |
938 __ pop(backtrack_stackpointer()); | 963 __k pop(backtrack_stackpointer()); |
939 // String might have moved: Reload esi from frame. | 964 // String might have moved: Reload esi from frame. |
940 __ movq(rsi, Operand(rbp, kInputEnd)); | 965 __ movq(rsi, Operand(rbp, kInputEnd)); |
941 SafeReturn(); | 966 SafeReturn(); |
942 } | 967 } |
943 | 968 |
944 // Backtrack stack overflow code. | 969 // Backtrack stack overflow code. |
945 if (stack_overflow_label_.is_linked()) { | 970 if (stack_overflow_label_.is_linked()) { |
946 SafeCallTarget(&stack_overflow_label_); | 971 SafeCallTarget(&stack_overflow_label_); |
947 // Reached if the backtrack-stack limit has been hit. | 972 // Reached if the backtrack-stack limit has been hit. |
948 | 973 |
949 Label grow_failed; | 974 Label grow_failed; |
950 // Save registers before calling C function | 975 // Save registers before calling C function |
951 #ifndef _WIN64 | 976 #ifndef _WIN64 |
952 // Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI. | 977 // Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI. |
953 __ push(rsi); | 978 __k push(rsi); |
954 __ push(rdi); | 979 __k push(rdi); |
955 #endif | 980 #endif |
956 | 981 |
957 // Call GrowStack(backtrack_stackpointer()) | 982 // Call GrowStack(backtrack_stackpointer()) |
958 static const int num_arguments = 3; | 983 static const int num_arguments = 3; |
959 __ PrepareCallCFunction(num_arguments); | 984 __ PrepareCallCFunction(num_arguments); |
960 #ifdef _WIN64 | 985 #ifdef _WIN64 |
961 // Microsoft passes parameters in rcx, rdx, r8. | 986 // Microsoft passes parameters in rcx, rdx, r8. |
962 // First argument, backtrack stackpointer, is already in rcx. | 987 // First argument, backtrack stackpointer, is already in rcx. |
963 __ lea(rdx, Operand(rbp, kStackHighEnd)); // Second argument | 988 __ lea(rdx, Operand(rbp, kStackHighEnd)); // Second argument |
964 __ LoadAddress(r8, ExternalReference::isolate_address(isolate())); | 989 __ LoadAddress(r8, ExternalReference::isolate_address(isolate())); |
965 #else | 990 #else |
966 // AMD64 ABI passes parameters in rdi, rsi, rdx. | 991 // AMD64 ABI passes parameters in rdi, rsi, rdx. |
967 __ movq(rdi, backtrack_stackpointer()); // First argument. | 992 __ movq(rdi, backtrack_stackpointer()); // First argument. |
968 __ lea(rsi, Operand(rbp, kStackHighEnd)); // Second argument. | 993 __ lea(rsi, Operand(rbp, kStackHighEnd)); // Second argument. |
969 __ LoadAddress(rdx, ExternalReference::isolate_address(isolate())); | 994 __ LoadAddress(rdx, ExternalReference::isolate_address(isolate())); |
970 #endif | 995 #endif |
971 ExternalReference grow_stack = | 996 ExternalReference grow_stack = |
972 ExternalReference::re_grow_stack(isolate()); | 997 ExternalReference::re_grow_stack(isolate()); |
973 __ CallCFunction(grow_stack, num_arguments); | 998 __ CallCFunction(grow_stack, num_arguments); |
974 // If return NULL, we have failed to grow the stack, and | 999 // If return NULL, we have failed to grow the stack, and |
975 // must exit with a stack-overflow exception. | 1000 // must exit with a stack-overflow exception. |
976 __ testq(rax, rax); | 1001 __ testq(rax, rax); |
977 __ j(equal, &exit_with_exception); | 1002 __ j(equal, &exit_with_exception); |
978 // Otherwise use return value as new stack pointer. | 1003 // Otherwise use return value as new stack pointer. |
979 __ movq(backtrack_stackpointer(), rax); | 1004 __ movq(backtrack_stackpointer(), rax); |
980 // Restore saved registers and continue. | 1005 // Restore saved registers and continue. |
981 __ Move(code_object_pointer(), masm_.CodeObject()); | 1006 __ Move(code_object_pointer(), masm_.CodeObject()); |
982 #ifndef _WIN64 | 1007 #ifndef _WIN64 |
983 __ pop(rdi); | 1008 __k pop(rdi); |
984 __ pop(rsi); | 1009 __k pop(rsi); |
985 #endif | 1010 #endif |
986 SafeReturn(); | 1011 SafeReturn(); |
987 } | 1012 } |
988 | 1013 |
989 if (exit_with_exception.is_linked()) { | 1014 if (exit_with_exception.is_linked()) { |
990 // If any of the code above needed to exit with an exception. | 1015 // If any of the code above needed to exit with an exception. |
991 __ bind(&exit_with_exception); | 1016 __ bind(&exit_with_exception); |
992 // Exit with Result EXCEPTION(-1) to signal thrown exception. | 1017 // Exit with Result EXCEPTION(-1) to signal thrown exception. |
993 __ Set(rax, EXCEPTION); | 1018 __ Set(rax, EXCEPTION); |
994 __ jmp(&return_rax); | 1019 __ jmp(&return_rax); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1078 | 1103 |
1079 void RegExpMacroAssemblerX64::PushRegister(int register_index, | 1104 void RegExpMacroAssemblerX64::PushRegister(int register_index, |
1080 StackCheckFlag check_stack_limit) { | 1105 StackCheckFlag check_stack_limit) { |
1081 __ movq(rax, register_location(register_index)); | 1106 __ movq(rax, register_location(register_index)); |
1082 Push(rax); | 1107 Push(rax); |
1083 if (check_stack_limit) CheckStackLimit(); | 1108 if (check_stack_limit) CheckStackLimit(); |
1084 } | 1109 } |
1085 | 1110 |
1086 | 1111 |
1087 void RegExpMacroAssemblerX64::ReadCurrentPositionFromRegister(int reg) { | 1112 void RegExpMacroAssemblerX64::ReadCurrentPositionFromRegister(int reg) { |
| 1113 #ifndef V8_TARGET_ARCH_X32 |
1088 __ movq(rdi, register_location(reg)); | 1114 __ movq(rdi, register_location(reg)); |
| 1115 #else |
| 1116 __ movsxlq(rdi, register_location(reg)); |
| 1117 #endif |
1089 } | 1118 } |
1090 | 1119 |
1091 | 1120 |
1092 void RegExpMacroAssemblerX64::ReadStackPointerFromRegister(int reg) { | 1121 void RegExpMacroAssemblerX64::ReadStackPointerFromRegister(int reg) { |
| 1122 #ifndef V8_TARGET_ARCH_X32 |
1093 __ movq(backtrack_stackpointer(), register_location(reg)); | 1123 __ movq(backtrack_stackpointer(), register_location(reg)); |
1094 __ addq(backtrack_stackpointer(), Operand(rbp, kStackHighEnd)); | 1124 __ addq(backtrack_stackpointer(), Operand(rbp, kStackHighEnd)); |
| 1125 #else |
| 1126 __ movsxlq(backtrack_stackpointer(), register_location(reg)); |
| 1127 __ addl(backtrack_stackpointer(), Operand(rbp, kStackHighEnd)); |
| 1128 #endif |
1095 } | 1129 } |
1096 | 1130 |
1097 | 1131 |
1098 void RegExpMacroAssemblerX64::SetCurrentPositionFromEnd(int by) { | 1132 void RegExpMacroAssemblerX64::SetCurrentPositionFromEnd(int by) { |
1099 Label after_position; | 1133 Label after_position; |
1100 __ cmpq(rdi, Immediate(-by * char_size())); | 1134 __ cmpq(rdi, Immediate(-by * char_size())); |
1101 __ j(greater_equal, &after_position, Label::kNear); | 1135 __ j(greater_equal, &after_position, Label::kNear); |
1102 __ movq(rdi, Immediate(-by * char_size())); | 1136 __k movq(rdi, Immediate(-by * char_size())); |
1103 // On RegExp code entry (where this operation is used), the character before | 1137 // On RegExp code entry (where this operation is used), the character before |
1104 // the current position is expected to be already loaded. | 1138 // the current position is expected to be already loaded. |
1105 // We have advanced the position, so it's safe to read backwards. | 1139 // We have advanced the position, so it's safe to read backwards. |
1106 LoadCurrentCharacterUnchecked(-1, 1); | 1140 LoadCurrentCharacterUnchecked(-1, 1); |
1107 __ bind(&after_position); | 1141 __ bind(&after_position); |
1108 } | 1142 } |
1109 | 1143 |
1110 | 1144 |
1111 void RegExpMacroAssemblerX64::SetRegister(int register_index, int to) { | 1145 void RegExpMacroAssemblerX64::SetRegister(int register_index, int to) { |
1112 ASSERT(register_index >= num_saved_registers_); // Reserved for positions! | 1146 ASSERT(register_index >= num_saved_registers_); // Reserved for positions! |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1162 // First argument: Next address on the stack (will be address of | 1196 // First argument: Next address on the stack (will be address of |
1163 // return address). | 1197 // return address). |
1164 __ lea(rcx, Operand(rsp, -kPointerSize)); | 1198 __ lea(rcx, Operand(rsp, -kPointerSize)); |
1165 #else | 1199 #else |
1166 // Third argument: RegExp code frame pointer. | 1200 // Third argument: RegExp code frame pointer. |
1167 __ movq(rdx, rbp); | 1201 __ movq(rdx, rbp); |
1168 // Second argument: Code* of self. | 1202 // Second argument: Code* of self. |
1169 __ movq(rsi, code_object_pointer()); | 1203 __ movq(rsi, code_object_pointer()); |
1170 // First argument: Next address on the stack (will be address of | 1204 // First argument: Next address on the stack (will be address of |
1171 // return address). | 1205 // return address). |
| 1206 #ifndef V8_TARGET_ARCH_X32 |
1172 __ lea(rdi, Operand(rsp, -kPointerSize)); | 1207 __ lea(rdi, Operand(rsp, -kPointerSize)); |
| 1208 #else |
| 1209 __ leal(rdi, Operand(rsp, -kHWRegSize)); |
| 1210 #endif |
1173 #endif | 1211 #endif |
1174 ExternalReference stack_check = | 1212 ExternalReference stack_check = |
1175 ExternalReference::re_check_stack_guard_state(isolate()); | 1213 ExternalReference::re_check_stack_guard_state(isolate()); |
1176 __ CallCFunction(stack_check, num_arguments); | 1214 __ CallCFunction(stack_check, num_arguments); |
1177 } | 1215 } |
1178 | 1216 |
1179 | 1217 |
1180 // Helper function for reading a value out of a stack frame. | 1218 // Helper function for reading a value out of a stack frame. |
1181 template <typename T> | 1219 template <typename T> |
1182 static T& frame_entry(Address re_frame, int frame_offset) { | 1220 static T& frame_entry(Address re_frame, int frame_offset) { |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1369 | 1407 |
1370 void RegExpMacroAssemblerX64::Push(Label* backtrack_target) { | 1408 void RegExpMacroAssemblerX64::Push(Label* backtrack_target) { |
1371 __ subq(backtrack_stackpointer(), Immediate(kIntSize)); | 1409 __ subq(backtrack_stackpointer(), Immediate(kIntSize)); |
1372 __ movl(Operand(backtrack_stackpointer(), 0), backtrack_target); | 1410 __ movl(Operand(backtrack_stackpointer(), 0), backtrack_target); |
1373 MarkPositionForCodeRelativeFixup(); | 1411 MarkPositionForCodeRelativeFixup(); |
1374 } | 1412 } |
1375 | 1413 |
1376 | 1414 |
1377 void RegExpMacroAssemblerX64::Pop(Register target) { | 1415 void RegExpMacroAssemblerX64::Pop(Register target) { |
1378 ASSERT(!target.is(backtrack_stackpointer())); | 1416 ASSERT(!target.is(backtrack_stackpointer())); |
1379 __ movsxlq(target, Operand(backtrack_stackpointer(), 0)); | 1417 __k movsxlq(target, Operand(backtrack_stackpointer(), 0)); |
1380 // Notice: This updates flags, unlike normal Pop. | 1418 // Notice: This updates flags, unlike normal Pop. |
1381 __ addq(backtrack_stackpointer(), Immediate(kIntSize)); | 1419 __ addq(backtrack_stackpointer(), Immediate(kIntSize)); |
1382 } | 1420 } |
1383 | 1421 |
1384 | 1422 |
1385 void RegExpMacroAssemblerX64::Drop() { | 1423 void RegExpMacroAssemblerX64::Drop() { |
1386 __ addq(backtrack_stackpointer(), Immediate(kIntSize)); | 1424 __ addq(backtrack_stackpointer(), Immediate(kIntSize)); |
1387 } | 1425 } |
1388 | 1426 |
1389 | 1427 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1433 __ movl(current_character(), | 1471 __ movl(current_character(), |
1434 Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); | 1472 Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); |
1435 } else { | 1473 } else { |
1436 ASSERT(characters == 1); | 1474 ASSERT(characters == 1); |
1437 __ movzxwl(current_character(), | 1475 __ movzxwl(current_character(), |
1438 Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); | 1476 Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); |
1439 } | 1477 } |
1440 } | 1478 } |
1441 } | 1479 } |
1442 | 1480 |
| 1481 #undef __k |
1443 #undef __ | 1482 #undef __ |
1444 | 1483 |
1445 #endif // V8_INTERPRETED_REGEXP | 1484 #endif // V8_INTERPRETED_REGEXP |
1446 | 1485 |
1447 }} // namespace v8::internal | 1486 }} // namespace v8::internal |
1448 | 1487 |
1449 #endif // V8_TARGET_ARCH_X64 | 1488 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |