OLD | NEW |
1 // Copyright 2011 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 |
11 // with the distribution. | 11 // with the distribution. |
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
699 return true; | 699 return true; |
700 } | 700 } |
701 // No custom implementation (yet): s(UC16), S(UC16). | 701 // No custom implementation (yet): s(UC16), S(UC16). |
702 default: | 702 default: |
703 return false; | 703 return false; |
704 } | 704 } |
705 } | 705 } |
706 | 706 |
707 | 707 |
708 void RegExpMacroAssemblerIA32::Fail() { | 708 void RegExpMacroAssemblerIA32::Fail() { |
709 ASSERT(FAILURE == 0); // Return value for failure is zero. | 709 STATIC_ASSERT(FAILURE == 0); // Return value for failure is zero. |
710 __ Set(eax, Immediate(0)); | 710 if (!global()) { |
| 711 __ Set(eax, Immediate(FAILURE)); |
| 712 } |
711 __ jmp(&exit_label_); | 713 __ jmp(&exit_label_); |
712 } | 714 } |
713 | 715 |
714 | 716 |
715 Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { | 717 Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) { |
| 718 Label return_eax, restart; |
716 // Finalize code - write the entry point code now we know how many | 719 // Finalize code - write the entry point code now we know how many |
717 // registers we need. | 720 // registers we need. |
718 | 721 |
719 // Entry code: | 722 // Entry code: |
720 __ bind(&entry_label_); | 723 __ bind(&entry_label_); |
721 | 724 |
722 // Tell the system that we have a stack frame. Because the type is MANUAL, no | 725 // Tell the system that we have a stack frame. Because the type is MANUAL, no |
723 // code is generated. | 726 // code is generated. |
724 FrameScope scope(masm_, StackFrame::MANUAL); | 727 FrameScope scope(masm_, StackFrame::MANUAL); |
725 | 728 |
726 // Actually emit code to start a new stack frame. | 729 // Actually emit code to start a new stack frame. |
727 __ push(ebp); | 730 __ push(ebp); |
728 __ mov(ebp, esp); | 731 __ mov(ebp, esp); |
729 // Save callee-save registers. Order here should correspond to order of | 732 // Save callee-save registers. Order here should correspond to order of |
730 // kBackup_ebx etc. | 733 // kBackup_ebx etc. |
731 __ push(esi); | 734 __ push(esi); |
732 __ push(edi); | 735 __ push(edi); |
733 __ push(ebx); // Callee-save on MacOS. | 736 __ push(ebx); // Callee-save on MacOS. |
| 737 __ push(Immediate(0)); // Number of successful matches in a global regexp. |
734 __ push(Immediate(0)); // Make room for "input start - 1" constant. | 738 __ push(Immediate(0)); // Make room for "input start - 1" constant. |
735 | 739 |
736 // Check if we have space on the stack for registers. | 740 // Check if we have space on the stack for registers. |
737 Label stack_limit_hit; | 741 Label stack_limit_hit; |
738 Label stack_ok; | 742 Label stack_ok; |
739 | 743 |
740 ExternalReference stack_limit = | 744 ExternalReference stack_limit = |
741 ExternalReference::address_of_stack_limit(masm_->isolate()); | 745 ExternalReference::address_of_stack_limit(masm_->isolate()); |
742 __ mov(ecx, esp); | 746 __ mov(ecx, esp); |
743 __ sub(ecx, Operand::StaticVariable(stack_limit)); | 747 __ sub(ecx, Operand::StaticVariable(stack_limit)); |
744 // Handle it if the stack pointer is already below the stack limit. | 748 // Handle it if the stack pointer is already below the stack limit. |
745 __ j(below_equal, &stack_limit_hit); | 749 __ j(below_equal, &stack_limit_hit); |
746 // Check if there is room for the variable number of registers above | 750 // Check if there is room for the variable number of registers above |
747 // the stack limit. | 751 // the stack limit. |
748 __ cmp(ecx, num_registers_ * kPointerSize); | 752 __ cmp(ecx, num_registers_ * kPointerSize); |
749 __ j(above_equal, &stack_ok); | 753 __ j(above_equal, &stack_ok); |
750 // Exit with OutOfMemory exception. There is not enough space on the stack | 754 // Exit with OutOfMemory exception. There is not enough space on the stack |
751 // for our working registers. | 755 // for our working registers. |
752 __ mov(eax, EXCEPTION); | 756 __ mov(eax, EXCEPTION); |
753 __ jmp(&exit_label_); | 757 __ jmp(&return_eax); |
754 | 758 |
755 __ bind(&stack_limit_hit); | 759 __ bind(&stack_limit_hit); |
756 CallCheckStackGuardState(ebx); | 760 CallCheckStackGuardState(ebx); |
757 __ or_(eax, eax); | 761 __ or_(eax, eax); |
758 // If returned value is non-zero, we exit with the returned value as result. | 762 // If returned value is non-zero, we exit with the returned value as result. |
759 __ j(not_zero, &exit_label_); | 763 __ j(not_zero, &return_eax); |
760 | 764 |
761 __ bind(&stack_ok); | 765 __ bind(&stack_ok); |
762 // Load start index for later use. | 766 // Load start index for later use. |
763 __ mov(ebx, Operand(ebp, kStartIndex)); | 767 __ mov(ebx, Operand(ebp, kStartIndex)); |
764 | 768 |
765 // Allocate space on stack for registers. | 769 // Allocate space on stack for registers. |
766 __ sub(esp, Immediate(num_registers_ * kPointerSize)); | 770 __ sub(esp, Immediate(num_registers_ * kPointerSize)); |
767 // Load string length. | 771 // Load string length. |
768 __ mov(esi, Operand(ebp, kInputEnd)); | 772 __ mov(esi, Operand(ebp, kInputEnd)); |
769 // Load input position. | 773 // Load input position. |
(...skipping 30 matching lines...) Expand all Loading... |
800 const int kPageSize = 4096; | 804 const int kPageSize = 4096; |
801 const int kRegistersPerPage = kPageSize / kPointerSize; | 805 const int kRegistersPerPage = kPageSize / kPointerSize; |
802 for (int i = num_saved_registers_ + kRegistersPerPage - 1; | 806 for (int i = num_saved_registers_ + kRegistersPerPage - 1; |
803 i < num_registers_; | 807 i < num_registers_; |
804 i += kRegistersPerPage) { | 808 i += kRegistersPerPage) { |
805 __ mov(register_location(i), eax); // One write every page. | 809 __ mov(register_location(i), eax); // One write every page. |
806 } | 810 } |
807 | 811 |
808 | 812 |
809 // Initialize backtrack stack pointer. | 813 // Initialize backtrack stack pointer. |
| 814 if (global()) { |
| 815 __ bind(&restart); |
| 816 } |
810 __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd)); | 817 __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd)); |
811 // Load previous char as initial value of current-character. | 818 // Load previous char as initial value of current-character. |
812 Label at_start; | 819 Label at_start; |
813 __ cmp(Operand(ebp, kStartIndex), Immediate(0)); | 820 __ cmp(Operand(ebp, kStartIndex), Immediate(0)); |
814 __ j(equal, &at_start); | 821 __ j(equal, &at_start); |
815 LoadCurrentCharacterUnchecked(-1, 1); // Load previous char. | 822 LoadCurrentCharacterUnchecked(-1, 1); // Load previous char. |
816 __ jmp(&start_label_); | 823 __ jmp(&start_label_); |
817 __ bind(&at_start); | 824 __ bind(&at_start); |
818 __ mov(current_character(), '\n'); | 825 __ mov(current_character(), '\n'); |
819 __ jmp(&start_label_); | 826 __ jmp(&start_label_); |
(...skipping 17 matching lines...) Expand all Loading... |
837 for (int i = 0; i < num_saved_registers_; i++) { | 844 for (int i = 0; i < num_saved_registers_; i++) { |
838 __ mov(eax, register_location(i)); | 845 __ mov(eax, register_location(i)); |
839 // Convert to index from start of string, not end. | 846 // Convert to index from start of string, not end. |
840 __ add(eax, ecx); | 847 __ add(eax, ecx); |
841 if (mode_ == UC16) { | 848 if (mode_ == UC16) { |
842 __ sar(eax, 1); // Convert byte index to character index. | 849 __ sar(eax, 1); // Convert byte index to character index. |
843 } | 850 } |
844 __ mov(Operand(ebx, i * kPointerSize), eax); | 851 __ mov(Operand(ebx, i * kPointerSize), eax); |
845 } | 852 } |
846 } | 853 } |
847 __ mov(eax, Immediate(SUCCESS)); | 854 if (global()) { |
| 855 // Set success flag, since we obviously have had successful captures. |
| 856 __ inc(Operand(ebp, kSuccessfulCaptures)); |
| 857 // Capture results have been stored, so the number of remaining global |
| 858 // output registers is reduced by the number of stored captures. |
| 859 __ mov(ecx, Operand(ebp, kNumOutputRegisters)); |
| 860 __ sub(ecx, Immediate(num_saved_registers_)); |
| 861 // Check whether we have enough room for another set of capture results. |
| 862 __ cmp(ecx, Immediate(num_saved_registers_)); |
| 863 __ j(less, &exit_label_); |
| 864 |
| 865 __ mov(Operand(ebp, kNumOutputRegisters), ecx); |
| 866 // Advance the location for output. |
| 867 __ mov(ebx, Operand(ebp, kRegisterOutput)); |
| 868 __ add(Operand(ebp, kRegisterOutput), |
| 869 Immediate(num_saved_registers_ * kPointerSize)); |
| 870 |
| 871 // Loop to the start. |
| 872 __ jmp(&restart); |
| 873 } else { |
| 874 __ mov(eax, Immediate(SUCCESS)); |
| 875 } |
848 } | 876 } |
849 // Exit and return eax | 877 |
850 __ bind(&exit_label_); | 878 __ bind(&exit_label_); |
| 879 if (global()) { |
| 880 // Return the number of successful captures. |
| 881 STATIC_ASSERT(FAILURE == 0 && SUCCESS == 1); |
| 882 __ mov(eax, Operand(ebp, kSuccessfulCaptures)); |
| 883 } |
| 884 |
| 885 __ bind(&return_eax); |
851 // Skip esp past regexp registers. | 886 // Skip esp past regexp registers. |
852 __ lea(esp, Operand(ebp, kBackup_ebx)); | 887 __ lea(esp, Operand(ebp, kBackup_ebx)); |
853 // Restore callee-save registers. | 888 // Restore callee-save registers. |
854 __ pop(ebx); | 889 __ pop(ebx); |
855 __ pop(edi); | 890 __ pop(edi); |
856 __ pop(esi); | 891 __ pop(esi); |
857 // Exit function frame, restore previous one. | 892 // Exit function frame, restore previous one. |
858 __ pop(ebp); | 893 __ pop(ebp); |
859 __ ret(0); | 894 __ ret(0); |
860 | 895 |
861 // Backtrack code (branch target for conditional backtracks). | 896 // Backtrack code (branch target for conditional backtracks). |
862 if (backtrack_label_.is_linked()) { | 897 if (backtrack_label_.is_linked()) { |
863 __ bind(&backtrack_label_); | 898 __ bind(&backtrack_label_); |
864 Backtrack(); | 899 Backtrack(); |
865 } | 900 } |
866 | 901 |
867 Label exit_with_exception; | 902 Label exit_with_exception; |
868 | 903 |
869 // Preempt-code | 904 // Preempt-code |
870 if (check_preempt_label_.is_linked()) { | 905 if (check_preempt_label_.is_linked()) { |
871 SafeCallTarget(&check_preempt_label_); | 906 SafeCallTarget(&check_preempt_label_); |
872 | 907 |
873 __ push(backtrack_stackpointer()); | 908 __ push(backtrack_stackpointer()); |
874 __ push(edi); | 909 __ push(edi); |
875 | 910 |
876 CallCheckStackGuardState(ebx); | 911 CallCheckStackGuardState(ebx); |
877 __ or_(eax, eax); | 912 __ or_(eax, eax); |
878 // If returning non-zero, we should end execution with the given | 913 // If returning non-zero, we should end execution with the given |
879 // result as return value. | 914 // result as return value. |
880 __ j(not_zero, &exit_label_); | 915 __ j(not_zero, &return_eax); |
881 | 916 |
882 __ pop(edi); | 917 __ pop(edi); |
883 __ pop(backtrack_stackpointer()); | 918 __ pop(backtrack_stackpointer()); |
884 // String might have moved: Reload esi from frame. | 919 // String might have moved: Reload esi from frame. |
885 __ mov(esi, Operand(ebp, kInputEnd)); | 920 __ mov(esi, Operand(ebp, kInputEnd)); |
886 SafeReturn(); | 921 SafeReturn(); |
887 } | 922 } |
888 | 923 |
889 // Backtrack stack overflow code. | 924 // Backtrack stack overflow code. |
890 if (stack_overflow_label_.is_linked()) { | 925 if (stack_overflow_label_.is_linked()) { |
(...skipping 26 matching lines...) Expand all Loading... |
917 __ pop(edi); | 952 __ pop(edi); |
918 __ pop(esi); | 953 __ pop(esi); |
919 SafeReturn(); | 954 SafeReturn(); |
920 } | 955 } |
921 | 956 |
922 if (exit_with_exception.is_linked()) { | 957 if (exit_with_exception.is_linked()) { |
923 // If any of the code above needed to exit with an exception. | 958 // If any of the code above needed to exit with an exception. |
924 __ bind(&exit_with_exception); | 959 __ bind(&exit_with_exception); |
925 // Exit with Result EXCEPTION(-1) to signal thrown exception. | 960 // Exit with Result EXCEPTION(-1) to signal thrown exception. |
926 __ mov(eax, EXCEPTION); | 961 __ mov(eax, EXCEPTION); |
927 __ jmp(&exit_label_); | 962 __ jmp(&return_eax); |
928 } | 963 } |
929 | 964 |
930 CodeDesc code_desc; | 965 CodeDesc code_desc; |
931 masm_->GetCode(&code_desc); | 966 masm_->GetCode(&code_desc); |
932 Handle<Code> code = | 967 Handle<Code> code = |
933 masm_->isolate()->factory()->NewCode(code_desc, | 968 masm_->isolate()->factory()->NewCode(code_desc, |
934 Code::ComputeFlags(Code::REGEXP), | 969 Code::ComputeFlags(Code::REGEXP), |
935 masm_->CodeObject()); | 970 masm_->CodeObject()); |
936 PROFILE(masm_->isolate(), RegExpCodeCreateEvent(*code, *source)); | 971 PROFILE(masm_->isolate(), RegExpCodeCreateEvent(*code, *source)); |
937 return Handle<HeapObject>::cast(code); | 972 return Handle<HeapObject>::cast(code); |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1328 } | 1363 } |
1329 | 1364 |
1330 | 1365 |
1331 #undef __ | 1366 #undef __ |
1332 | 1367 |
1333 #endif // V8_INTERPRETED_REGEXP | 1368 #endif // V8_INTERPRETED_REGEXP |
1334 | 1369 |
1335 }} // namespace v8::internal | 1370 }} // namespace v8::internal |
1336 | 1371 |
1337 #endif // V8_TARGET_ARCH_IA32 | 1372 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |