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 |