| 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 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 __ j(below, &loop); | 315 __ j(below, &loop); |
| 316 | 316 |
| 317 // Compute new value of character position after the matched part. | 317 // Compute new value of character position after the matched part. |
| 318 __ movp(rdi, r11); | 318 __ movp(rdi, r11); |
| 319 __ subq(rdi, rsi); | 319 __ subq(rdi, rsi); |
| 320 } else { | 320 } else { |
| 321 ASSERT(mode_ == UC16); | 321 ASSERT(mode_ == UC16); |
| 322 // Save important/volatile registers before calling C function. | 322 // Save important/volatile registers before calling C function. |
| 323 #ifndef _WIN64 | 323 #ifndef _WIN64 |
| 324 // Caller save on Linux and callee save in Windows. | 324 // Caller save on Linux and callee save in Windows. |
| 325 __ push(rsi); | 325 __ pushq(rsi); |
| 326 __ push(rdi); | 326 __ pushq(rdi); |
| 327 #endif | 327 #endif |
| 328 __ push(backtrack_stackpointer()); | 328 __ pushq(backtrack_stackpointer()); |
| 329 | 329 |
| 330 static const int num_arguments = 4; | 330 static const int num_arguments = 4; |
| 331 __ PrepareCallCFunction(num_arguments); | 331 __ PrepareCallCFunction(num_arguments); |
| 332 | 332 |
| 333 // Put arguments into parameter registers. Parameters are | 333 // Put arguments into parameter registers. Parameters are |
| 334 // Address byte_offset1 - Address captured substring's start. | 334 // Address byte_offset1 - Address captured substring's start. |
| 335 // Address byte_offset2 - Address of current character position. | 335 // Address byte_offset2 - Address of current character position. |
| 336 // size_t byte_length - length of capture in bytes(!) | 336 // size_t byte_length - length of capture in bytes(!) |
| 337 // Isolate* isolate | 337 // Isolate* isolate |
| 338 #ifdef _WIN64 | 338 #ifdef _WIN64 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 360 { // NOLINT: Can't find a way to open this scope without confusing the | 360 { // NOLINT: Can't find a way to open this scope without confusing the |
| 361 // linter. | 361 // linter. |
| 362 AllowExternalCallThatCantCauseGC scope(&masm_); | 362 AllowExternalCallThatCantCauseGC scope(&masm_); |
| 363 ExternalReference compare = | 363 ExternalReference compare = |
| 364 ExternalReference::re_case_insensitive_compare_uc16(isolate()); | 364 ExternalReference::re_case_insensitive_compare_uc16(isolate()); |
| 365 __ CallCFunction(compare, num_arguments); | 365 __ CallCFunction(compare, num_arguments); |
| 366 } | 366 } |
| 367 | 367 |
| 368 // Restore original values before reacting on result value. | 368 // Restore original values before reacting on result value. |
| 369 __ Move(code_object_pointer(), masm_.CodeObject()); | 369 __ Move(code_object_pointer(), masm_.CodeObject()); |
| 370 __ pop(backtrack_stackpointer()); | 370 __ popq(backtrack_stackpointer()); |
| 371 #ifndef _WIN64 | 371 #ifndef _WIN64 |
| 372 __ pop(rdi); | 372 __ popq(rdi); |
| 373 __ pop(rsi); | 373 __ popq(rsi); |
| 374 #endif | 374 #endif |
| 375 | 375 |
| 376 // Check if function returned non-zero for success or zero for failure. | 376 // Check if function returned non-zero for success or zero for failure. |
| 377 __ testq(rax, rax); | 377 __ testq(rax, rax); |
| 378 BranchOrBacktrack(zero, on_no_match); | 378 BranchOrBacktrack(zero, on_no_match); |
| 379 // On success, increment position by length of capture. | 379 // On success, increment position by length of capture. |
| 380 // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs). | 380 // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs). |
| 381 __ addq(rdi, rbx); | 381 __ addq(rdi, rbx); |
| 382 } | 382 } |
| 383 __ bind(&fallthrough); | 383 __ bind(&fallthrough); |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 // Finalize code - write the entry point code now we know how many | 667 // Finalize code - write the entry point code now we know how many |
| 668 // registers we need. | 668 // registers we need. |
| 669 // Entry code: | 669 // Entry code: |
| 670 __ bind(&entry_label_); | 670 __ bind(&entry_label_); |
| 671 | 671 |
| 672 // Tell the system that we have a stack frame. Because the type is MANUAL, no | 672 // Tell the system that we have a stack frame. Because the type is MANUAL, no |
| 673 // is generated. | 673 // is generated. |
| 674 FrameScope scope(&masm_, StackFrame::MANUAL); | 674 FrameScope scope(&masm_, StackFrame::MANUAL); |
| 675 | 675 |
| 676 // Actually emit code to start a new stack frame. | 676 // Actually emit code to start a new stack frame. |
| 677 __ push(rbp); | 677 __ pushq(rbp); |
| 678 __ movp(rbp, rsp); | 678 __ movp(rbp, rsp); |
| 679 // Save parameters and callee-save registers. Order here should correspond | 679 // Save parameters and callee-save registers. Order here should correspond |
| 680 // to order of kBackup_ebx etc. | 680 // to order of kBackup_ebx etc. |
| 681 #ifdef _WIN64 | 681 #ifdef _WIN64 |
| 682 // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots. | 682 // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots. |
| 683 // Store register parameters in pre-allocated stack slots, | 683 // Store register parameters in pre-allocated stack slots, |
| 684 __ movq(Operand(rbp, kInputString), rcx); | 684 __ movq(Operand(rbp, kInputString), rcx); |
| 685 __ movq(Operand(rbp, kStartIndex), rdx); // Passed as int32 in edx. | 685 __ movq(Operand(rbp, kStartIndex), rdx); // Passed as int32 in edx. |
| 686 __ movq(Operand(rbp, kInputStart), r8); | 686 __ movq(Operand(rbp, kInputStart), r8); |
| 687 __ movq(Operand(rbp, kInputEnd), r9); | 687 __ movq(Operand(rbp, kInputEnd), r9); |
| 688 // Callee-save on Win64. | 688 // Callee-save on Win64. |
| 689 __ push(rsi); | 689 __ pushq(rsi); |
| 690 __ push(rdi); | 690 __ pushq(rdi); |
| 691 __ push(rbx); | 691 __ pushq(rbx); |
| 692 #else | 692 #else |
| 693 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9 (and then on stack). | 693 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9 (and then on stack). |
| 694 // Push register parameters on stack for reference. | 694 // Push register parameters on stack for reference. |
| 695 ASSERT_EQ(kInputString, -1 * kPointerSize); | 695 ASSERT_EQ(kInputString, -1 * kPointerSize); |
| 696 ASSERT_EQ(kStartIndex, -2 * kPointerSize); | 696 ASSERT_EQ(kStartIndex, -2 * kPointerSize); |
| 697 ASSERT_EQ(kInputStart, -3 * kPointerSize); | 697 ASSERT_EQ(kInputStart, -3 * kPointerSize); |
| 698 ASSERT_EQ(kInputEnd, -4 * kPointerSize); | 698 ASSERT_EQ(kInputEnd, -4 * kPointerSize); |
| 699 ASSERT_EQ(kRegisterOutput, -5 * kPointerSize); | 699 ASSERT_EQ(kRegisterOutput, -5 * kPointerSize); |
| 700 ASSERT_EQ(kNumOutputRegisters, -6 * kPointerSize); | 700 ASSERT_EQ(kNumOutputRegisters, -6 * kPointerSize); |
| 701 __ push(rdi); | 701 __ pushq(rdi); |
| 702 __ push(rsi); | 702 __ pushq(rsi); |
| 703 __ push(rdx); | 703 __ pushq(rdx); |
| 704 __ push(rcx); | 704 __ pushq(rcx); |
| 705 __ push(r8); | 705 __ pushq(r8); |
| 706 __ push(r9); | 706 __ pushq(r9); |
| 707 | 707 |
| 708 __ push(rbx); // Callee-save | 708 __ pushq(rbx); // Callee-save |
| 709 #endif | 709 #endif |
| 710 | 710 |
| 711 __ push(Immediate(0)); // Number of successful matches in a global regexp. | 711 __ Push(Immediate(0)); // Number of successful matches in a global regexp. |
| 712 __ push(Immediate(0)); // Make room for "input start - 1" constant. | 712 __ Push(Immediate(0)); // Make room for "input start - 1" constant. |
| 713 | 713 |
| 714 // Check if we have space on the stack for registers. | 714 // Check if we have space on the stack for registers. |
| 715 Label stack_limit_hit; | 715 Label stack_limit_hit; |
| 716 Label stack_ok; | 716 Label stack_ok; |
| 717 | 717 |
| 718 ExternalReference stack_limit = | 718 ExternalReference stack_limit = |
| 719 ExternalReference::address_of_stack_limit(isolate()); | 719 ExternalReference::address_of_stack_limit(isolate()); |
| 720 __ movp(rcx, rsp); | 720 __ movp(rcx, rsp); |
| 721 __ Move(kScratchRegister, stack_limit); | 721 __ Move(kScratchRegister, stack_limit); |
| 722 __ subq(rcx, Operand(kScratchRegister, 0)); | 722 __ subq(rcx, Operand(kScratchRegister, 0)); |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 890 __ bind(&exit_label_); | 890 __ bind(&exit_label_); |
| 891 if (global()) { | 891 if (global()) { |
| 892 // Return the number of successful captures. | 892 // Return the number of successful captures. |
| 893 __ movp(rax, Operand(rbp, kSuccessfulCaptures)); | 893 __ movp(rax, Operand(rbp, kSuccessfulCaptures)); |
| 894 } | 894 } |
| 895 | 895 |
| 896 __ bind(&return_rax); | 896 __ bind(&return_rax); |
| 897 #ifdef _WIN64 | 897 #ifdef _WIN64 |
| 898 // Restore callee save registers. | 898 // Restore callee save registers. |
| 899 __ lea(rsp, Operand(rbp, kLastCalleeSaveRegister)); | 899 __ lea(rsp, Operand(rbp, kLastCalleeSaveRegister)); |
| 900 __ pop(rbx); | 900 __ popq(rbx); |
| 901 __ pop(rdi); | 901 __ popq(rdi); |
| 902 __ pop(rsi); | 902 __ popq(rsi); |
| 903 // Stack now at rbp. | 903 // Stack now at rbp. |
| 904 #else | 904 #else |
| 905 // Restore callee save register. | 905 // Restore callee save register. |
| 906 __ movp(rbx, Operand(rbp, kBackup_rbx)); | 906 __ movp(rbx, Operand(rbp, kBackup_rbx)); |
| 907 // Skip rsp to rbp. | 907 // Skip rsp to rbp. |
| 908 __ movp(rsp, rbp); | 908 __ movp(rsp, rbp); |
| 909 #endif | 909 #endif |
| 910 // Exit function frame, restore previous one. | 910 // Exit function frame, restore previous one. |
| 911 __ pop(rbp); | 911 __ popq(rbp); |
| 912 __ ret(0); | 912 __ ret(0); |
| 913 | 913 |
| 914 // Backtrack code (branch target for conditional backtracks). | 914 // Backtrack code (branch target for conditional backtracks). |
| 915 if (backtrack_label_.is_linked()) { | 915 if (backtrack_label_.is_linked()) { |
| 916 __ bind(&backtrack_label_); | 916 __ bind(&backtrack_label_); |
| 917 Backtrack(); | 917 Backtrack(); |
| 918 } | 918 } |
| 919 | 919 |
| 920 Label exit_with_exception; | 920 Label exit_with_exception; |
| 921 | 921 |
| 922 // Preempt-code | 922 // Preempt-code |
| 923 if (check_preempt_label_.is_linked()) { | 923 if (check_preempt_label_.is_linked()) { |
| 924 SafeCallTarget(&check_preempt_label_); | 924 SafeCallTarget(&check_preempt_label_); |
| 925 | 925 |
| 926 __ push(backtrack_stackpointer()); | 926 __ pushq(backtrack_stackpointer()); |
| 927 __ push(rdi); | 927 __ pushq(rdi); |
| 928 | 928 |
| 929 CallCheckStackGuardState(); | 929 CallCheckStackGuardState(); |
| 930 __ testq(rax, rax); | 930 __ testq(rax, rax); |
| 931 // If returning non-zero, we should end execution with the given | 931 // If returning non-zero, we should end execution with the given |
| 932 // result as return value. | 932 // result as return value. |
| 933 __ j(not_zero, &return_rax); | 933 __ j(not_zero, &return_rax); |
| 934 | 934 |
| 935 // Restore registers. | 935 // Restore registers. |
| 936 __ Move(code_object_pointer(), masm_.CodeObject()); | 936 __ Move(code_object_pointer(), masm_.CodeObject()); |
| 937 __ pop(rdi); | 937 __ popq(rdi); |
| 938 __ pop(backtrack_stackpointer()); | 938 __ popq(backtrack_stackpointer()); |
| 939 // String might have moved: Reload esi from frame. | 939 // String might have moved: Reload esi from frame. |
| 940 __ movp(rsi, Operand(rbp, kInputEnd)); | 940 __ movp(rsi, Operand(rbp, kInputEnd)); |
| 941 SafeReturn(); | 941 SafeReturn(); |
| 942 } | 942 } |
| 943 | 943 |
| 944 // Backtrack stack overflow code. | 944 // Backtrack stack overflow code. |
| 945 if (stack_overflow_label_.is_linked()) { | 945 if (stack_overflow_label_.is_linked()) { |
| 946 SafeCallTarget(&stack_overflow_label_); | 946 SafeCallTarget(&stack_overflow_label_); |
| 947 // Reached if the backtrack-stack limit has been hit. | 947 // Reached if the backtrack-stack limit has been hit. |
| 948 | 948 |
| 949 Label grow_failed; | 949 Label grow_failed; |
| 950 // Save registers before calling C function | 950 // Save registers before calling C function |
| 951 #ifndef _WIN64 | 951 #ifndef _WIN64 |
| 952 // Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI. | 952 // Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI. |
| 953 __ push(rsi); | 953 __ pushq(rsi); |
| 954 __ push(rdi); | 954 __ pushq(rdi); |
| 955 #endif | 955 #endif |
| 956 | 956 |
| 957 // Call GrowStack(backtrack_stackpointer()) | 957 // Call GrowStack(backtrack_stackpointer()) |
| 958 static const int num_arguments = 3; | 958 static const int num_arguments = 3; |
| 959 __ PrepareCallCFunction(num_arguments); | 959 __ PrepareCallCFunction(num_arguments); |
| 960 #ifdef _WIN64 | 960 #ifdef _WIN64 |
| 961 // Microsoft passes parameters in rcx, rdx, r8. | 961 // Microsoft passes parameters in rcx, rdx, r8. |
| 962 // First argument, backtrack stackpointer, is already in rcx. | 962 // First argument, backtrack stackpointer, is already in rcx. |
| 963 __ lea(rdx, Operand(rbp, kStackHighEnd)); // Second argument | 963 __ lea(rdx, Operand(rbp, kStackHighEnd)); // Second argument |
| 964 __ LoadAddress(r8, ExternalReference::isolate_address(isolate())); | 964 __ LoadAddress(r8, ExternalReference::isolate_address(isolate())); |
| 965 #else | 965 #else |
| 966 // AMD64 ABI passes parameters in rdi, rsi, rdx. | 966 // AMD64 ABI passes parameters in rdi, rsi, rdx. |
| 967 __ movp(rdi, backtrack_stackpointer()); // First argument. | 967 __ movp(rdi, backtrack_stackpointer()); // First argument. |
| 968 __ lea(rsi, Operand(rbp, kStackHighEnd)); // Second argument. | 968 __ lea(rsi, Operand(rbp, kStackHighEnd)); // Second argument. |
| 969 __ LoadAddress(rdx, ExternalReference::isolate_address(isolate())); | 969 __ LoadAddress(rdx, ExternalReference::isolate_address(isolate())); |
| 970 #endif | 970 #endif |
| 971 ExternalReference grow_stack = | 971 ExternalReference grow_stack = |
| 972 ExternalReference::re_grow_stack(isolate()); | 972 ExternalReference::re_grow_stack(isolate()); |
| 973 __ CallCFunction(grow_stack, num_arguments); | 973 __ CallCFunction(grow_stack, num_arguments); |
| 974 // If return NULL, we have failed to grow the stack, and | 974 // If return NULL, we have failed to grow the stack, and |
| 975 // must exit with a stack-overflow exception. | 975 // must exit with a stack-overflow exception. |
| 976 __ testq(rax, rax); | 976 __ testq(rax, rax); |
| 977 __ j(equal, &exit_with_exception); | 977 __ j(equal, &exit_with_exception); |
| 978 // Otherwise use return value as new stack pointer. | 978 // Otherwise use return value as new stack pointer. |
| 979 __ movp(backtrack_stackpointer(), rax); | 979 __ movp(backtrack_stackpointer(), rax); |
| 980 // Restore saved registers and continue. | 980 // Restore saved registers and continue. |
| 981 __ Move(code_object_pointer(), masm_.CodeObject()); | 981 __ Move(code_object_pointer(), masm_.CodeObject()); |
| 982 #ifndef _WIN64 | 982 #ifndef _WIN64 |
| 983 __ pop(rdi); | 983 __ popq(rdi); |
| 984 __ pop(rsi); | 984 __ popq(rsi); |
| 985 #endif | 985 #endif |
| 986 SafeReturn(); | 986 SafeReturn(); |
| 987 } | 987 } |
| 988 | 988 |
| 989 if (exit_with_exception.is_linked()) { | 989 if (exit_with_exception.is_linked()) { |
| 990 // If any of the code above needed to exit with an exception. | 990 // If any of the code above needed to exit with an exception. |
| 991 __ bind(&exit_with_exception); | 991 __ bind(&exit_with_exception); |
| 992 // Exit with Result EXCEPTION(-1) to signal thrown exception. | 992 // Exit with Result EXCEPTION(-1) to signal thrown exception. |
| 993 __ Set(rax, EXCEPTION); | 993 __ Set(rax, EXCEPTION); |
| 994 __ jmp(&return_rax); | 994 __ jmp(&return_rax); |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1439 } | 1439 } |
| 1440 } | 1440 } |
| 1441 | 1441 |
| 1442 #undef __ | 1442 #undef __ |
| 1443 | 1443 |
| 1444 #endif // V8_INTERPRETED_REGEXP | 1444 #endif // V8_INTERPRETED_REGEXP |
| 1445 | 1445 |
| 1446 }} // namespace v8::internal | 1446 }} // namespace v8::internal |
| 1447 | 1447 |
| 1448 #endif // V8_TARGET_ARCH_X64 | 1448 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |