Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(218)

Side by Side Diff: src/ia32/regexp-macro-assembler-ia32.cc

Issue 10386090: Implement loop for global regexps in regexp assembler. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698