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

Side by Side Diff: src/runtime.cc

Issue 10386090: Implement loop for global regexps in regexp assembler. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fix bugs, add tests, port to x64 and arm. 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 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 3777 matching lines...) Expand 10 before | Expand all | Expand 10 after
3788 SetLastMatchInfoNoCaptures(subject, 3788 SetLastMatchInfoNoCaptures(subject,
3789 last_match_info, 3789 last_match_info,
3790 match_pos, 3790 match_pos,
3791 match_pos + pattern->length()); 3791 match_pos + pattern->length());
3792 return true; 3792 return true;
3793 } 3793 }
3794 return false; // No matches at all. 3794 return false; // No matches at all.
3795 } 3795 }
3796 3796
3797 3797
3798 static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple( 3798 static int SearchRegExpNoCaptureMultiple(
3799 Isolate* isolate, 3799 Isolate* isolate,
3800 Handle<String> subject, 3800 Handle<String> subject,
3801 Handle<JSRegExp> regexp, 3801 Handle<JSRegExp> regexp,
3802 Handle<JSArray> last_match_array, 3802 Handle<JSArray> last_match_array,
3803 FixedArrayBuilder* builder) { 3803 FixedArrayBuilder* builder) {
3804 ASSERT(subject->IsFlat()); 3804 ASSERT(subject->IsFlat());
3805 ASSERT(regexp->CaptureCount() == 0);
3805 int match_start = -1; 3806 int match_start = -1;
3806 int match_end = 0; 3807 int match_end = 0;
3807 int pos = 0; 3808 int pos = 0;
3808 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject); 3809 int registers_per_match = RegExpImpl::IrregexpPrepare(regexp, subject);
3809 if (required_registers < 0) return RegExpImpl::RE_EXCEPTION; 3810 if (registers_per_match < 0) return RegExpImpl::RE_EXCEPTION;
3810 3811
3811 OffsetsVector registers(required_registers, isolate); 3812 int max_matches;
3813 int num_registers = RegExpImpl::GlobalOffsetsVectorSize(regexp,
3814 registers_per_match,
3815 &max_matches);
3816 OffsetsVector registers(num_registers, isolate);
3812 Vector<int32_t> register_vector(registers.vector(), registers.length()); 3817 Vector<int32_t> register_vector(registers.vector(), registers.length());
3813 int subject_length = subject->length(); 3818 int subject_length = subject->length();
3814 bool first = true; 3819 bool first = true;
3820 for (;;) { // Break on failure, return on exception.
3821 int num_matches = RegExpImpl::IrregexpExecRaw(regexp,
3822 subject,
3823 pos,
3824 register_vector);
3825 if (num_matches > 0) {
3826 for (int match_index = 0; match_index < num_matches; match_index++) {
3827 int32_t* current_match = &register_vector[match_index * 2];
3828 match_start = current_match[0];
3829 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3830 if (match_end < match_start) {
3831 ReplacementStringBuilder::AddSubjectSlice(builder,
3832 match_end,
3833 match_start);
3834 }
3835 match_end = current_match[1];
3836 HandleScope loop_scope(isolate);
3837 if (!first) {
3838 builder->Add(*isolate->factory()->NewProperSubString(subject,
3839 match_start,
3840 match_end));
3841 } else {
3842 builder->Add(*isolate->factory()->NewSubString(subject,
3843 match_start,
3844 match_end));
3845 first = false;
3846 }
3847 }
3815 3848
3816 for (;;) { // Break on failure, return on exception. 3849 // If we did not get the maximum number of matches, we can stop here
3817 RegExpImpl::IrregexpResult result = 3850 // since there are no matches left.
3818 RegExpImpl::IrregexpExecOnce(regexp, 3851 if (num_matches < max_matches) break;
3819 subject, 3852
3820 pos,
3821 register_vector);
3822 if (result == RegExpImpl::RE_SUCCESS) {
3823 match_start = register_vector[0];
3824 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3825 if (match_end < match_start) {
3826 ReplacementStringBuilder::AddSubjectSlice(builder,
3827 match_end,
3828 match_start);
3829 }
3830 match_end = register_vector[1];
3831 HandleScope loop_scope(isolate);
3832 if (!first) {
3833 builder->Add(*isolate->factory()->NewProperSubString(subject,
3834 match_start,
3835 match_end));
3836 } else {
3837 builder->Add(*isolate->factory()->NewSubString(subject,
3838 match_start,
3839 match_end));
3840 }
3841 if (match_start != match_end) { 3853 if (match_start != match_end) {
3842 pos = match_end; 3854 pos = match_end;
3843 } else { 3855 } else {
3844 pos = match_end + 1; 3856 pos = match_end + 1;
3845 if (pos > subject_length) break; 3857 if (pos > subject_length) break;
3846 } 3858 }
3847 } else if (result == RegExpImpl::RE_FAILURE) { 3859 } else if (num_matches == 0) {
3848 break; 3860 break;
3849 } else { 3861 } else {
3850 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION); 3862 ASSERT_EQ(num_matches, RegExpImpl::RE_EXCEPTION);
3851 return result; 3863 return num_matches;
Erik Corry 2012/05/22 08:32:46 Perhaps it is clearer to write "return RegExpImpl:
3852 } 3864 }
3853 first = false;
3854 } 3865 }
3855 3866
3856 if (match_start >= 0) { 3867 if (match_start >= 0) {
3857 if (match_end < subject_length) { 3868 if (match_end < subject_length) {
3858 ReplacementStringBuilder::AddSubjectSlice(builder, 3869 ReplacementStringBuilder::AddSubjectSlice(builder,
3859 match_end, 3870 match_end,
3860 subject_length); 3871 subject_length);
3861 } 3872 }
3862 SetLastMatchInfoNoCaptures(subject, 3873 SetLastMatchInfoNoCaptures(subject,
3863 last_match_array, 3874 last_match_array,
3864 match_start, 3875 match_start,
3865 match_end); 3876 match_end);
3866 return RegExpImpl::RE_SUCCESS; 3877 return RegExpImpl::RE_SUCCESS;
3867 } else { 3878 } else {
3868 return RegExpImpl::RE_FAILURE; // No matches at all. 3879 return RegExpImpl::RE_FAILURE; // No matches at all.
3869 } 3880 }
3870 } 3881 }
3871 3882
3872 3883
3873 // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain 3884 // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
3874 // separate last match info. See comment on that function. 3885 // separate last match info. See comment on that function.
3875 static RegExpImpl::IrregexpResult SearchRegExpMultiple( 3886 static int SearchRegExpMultiple(
3876 Isolate* isolate, 3887 Isolate* isolate,
3877 Handle<String> subject, 3888 Handle<String> subject,
3878 Handle<JSRegExp> regexp, 3889 Handle<JSRegExp> regexp,
3879 Handle<JSArray> last_match_array, 3890 Handle<JSArray> last_match_array,
3880 FixedArrayBuilder* builder) { 3891 FixedArrayBuilder* builder) {
3881 3892
3882 ASSERT(subject->IsFlat()); 3893 ASSERT(subject->IsFlat());
3883 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject); 3894 int registers_per_match = RegExpImpl::IrregexpPrepare(regexp, subject);
3884 if (required_registers < 0) return RegExpImpl::RE_EXCEPTION; 3895 if (registers_per_match < 0) return RegExpImpl::RE_EXCEPTION;
3885 3896
3886 OffsetsVector registers(required_registers, isolate); 3897 int max_matches;
3898 int num_registers = RegExpImpl::GlobalOffsetsVectorSize(regexp,
3899 registers_per_match,
3900 &max_matches);
3901 OffsetsVector registers(num_registers, isolate);
3887 Vector<int32_t> register_vector(registers.vector(), registers.length()); 3902 Vector<int32_t> register_vector(registers.vector(), registers.length());
3888 3903
3889 RegExpImpl::IrregexpResult result = 3904 int num_matches = RegExpImpl::IrregexpExecRaw(regexp,
3890 RegExpImpl::IrregexpExecOnce(regexp, 3905 subject,
3891 subject, 3906 0,
3892 0, 3907 register_vector);
3893 register_vector);
3894 3908
3895 int capture_count = regexp->CaptureCount(); 3909 int capture_count = regexp->CaptureCount();
3896 int subject_length = subject->length(); 3910 int subject_length = subject->length();
3897 3911
3898 // Position to search from. 3912 // Position to search from.
3899 int pos = 0; 3913 int pos = 0;
3900 // End of previous match. Differs from pos if match was empty. 3914 // End of previous match. Differs from pos if match was empty.
3901 int match_end = 0; 3915 int match_end = 0;
3902 if (result == RegExpImpl::RE_SUCCESS) { 3916 bool first = true;
3903 bool first = true; 3917
3918 if (num_matches > 0) {
3904 do { 3919 do {
3905 int match_start = register_vector[0]; 3920 int match_start = 0;
3906 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); 3921 for (int match_index = 0; match_index < num_matches; match_index++) {
3907 if (match_end < match_start) { 3922 int32_t* current_match =
3908 ReplacementStringBuilder::AddSubjectSlice(builder, 3923 &register_vector[match_index * registers_per_match];
3909 match_end, 3924 match_start = current_match[0];
3910 match_start); 3925 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3926 if (match_end < match_start) {
3927 ReplacementStringBuilder::AddSubjectSlice(builder,
3928 match_end,
3929 match_start);
3930 }
3931 match_end = current_match[1];
3932
3933 {
3934 // Avoid accumulating new handles inside loop.
3935 HandleScope temp_scope(isolate);
3936 // Arguments array to replace function is match, captures, index and
3937 // subject, i.e., 3 + capture count in total.
3938 Handle<FixedArray> elements =
3939 isolate->factory()->NewFixedArray(3 + capture_count);
3940 Handle<String> match;
3941 if (!first) {
3942 match = isolate->factory()->NewProperSubString(subject,
3943 match_start,
3944 match_end);
3945 } else {
3946 match = isolate->factory()->NewSubString(subject,
3947 match_start,
3948 match_end);
3949 first = false;
3950 }
3951 elements->set(0, *match);
3952 for (int i = 1; i <= capture_count; i++) {
3953 int start = current_match[i * 2];
3954 if (start >= 0) {
3955 int end = current_match[i * 2 + 1];
3956 ASSERT(start <= end);
3957 Handle<String> substring =
3958 isolate->factory()->NewProperSubString(subject, start, end);
3959 elements->set(i, *substring);
3960 } else {
3961 ASSERT(current_match[i * 2 + 1] < 0);
3962 elements->set(i, isolate->heap()->undefined_value());
3963 }
3964 }
3965 elements->set(capture_count + 1, Smi::FromInt(match_start));
3966 elements->set(capture_count + 2, *subject);
3967 builder->Add(*isolate->factory()->NewJSArrayWithElements(elements));
3968 }
3911 } 3969 }
3912 match_end = register_vector[1];
3913 3970
3914 { 3971 // If we did not get the maximum number of matches, we can stop here
3915 // Avoid accumulating new handles inside loop. 3972 // since there are no matches left.
3916 HandleScope temp_scope(isolate); 3973 if (num_matches < max_matches) break;
3917 // Arguments array to replace function is match, captures, index and
3918 // subject, i.e., 3 + capture count in total.
3919 Handle<FixedArray> elements =
3920 isolate->factory()->NewFixedArray(3 + capture_count);
3921 Handle<String> match;
3922 if (!first) {
3923 match = isolate->factory()->NewProperSubString(subject,
3924 match_start,
3925 match_end);
3926 } else {
3927 match = isolate->factory()->NewSubString(subject,
3928 match_start,
3929 match_end);
3930 }
3931 elements->set(0, *match);
3932 for (int i = 1; i <= capture_count; i++) {
3933 int start = register_vector[i * 2];
3934 if (start >= 0) {
3935 int end = register_vector[i * 2 + 1];
3936 ASSERT(start <= end);
3937 Handle<String> substring;
3938 if (!first) {
3939 substring = isolate->factory()->NewProperSubString(subject,
3940 start,
3941 end);
3942 } else {
3943 substring = isolate->factory()->NewSubString(subject, start, end);
3944 }
3945 elements->set(i, *substring);
3946 } else {
3947 ASSERT(register_vector[i * 2 + 1] < 0);
3948 elements->set(i, isolate->heap()->undefined_value());
3949 }
3950 }
3951 elements->set(capture_count + 1, Smi::FromInt(match_start));
3952 elements->set(capture_count + 2, *subject);
3953 builder->Add(*isolate->factory()->NewJSArrayWithElements(elements));
3954 }
3955 3974
3956 if (match_end > match_start) { 3975 if (match_end > match_start) {
3957 pos = match_end; 3976 pos = match_end;
3958 } else { 3977 } else {
3959 pos = match_end + 1; 3978 pos = match_end + 1;
3960 if (pos > subject_length) { 3979 if (pos > subject_length) {
3961 break; 3980 break;
3962 } 3981 }
3963 } 3982 }
3964 3983
3965 result = RegExpImpl::IrregexpExecOnce(regexp, 3984 num_matches = RegExpImpl::IrregexpExecRaw(regexp,
3966 subject, 3985 subject,
3967 pos, 3986 pos,
3968 register_vector); 3987 register_vector);
3969 first = false; 3988 } while (num_matches > 0);
3970 } while (result == RegExpImpl::RE_SUCCESS);
3971 3989
3972 if (result != RegExpImpl::RE_EXCEPTION) { 3990 if (num_matches != RegExpImpl::RE_EXCEPTION) {
3973 // Finished matching, with at least one match. 3991 // Finished matching, with at least one match.
3974 if (match_end < subject_length) { 3992 if (match_end < subject_length) {
3975 ReplacementStringBuilder::AddSubjectSlice(builder, 3993 ReplacementStringBuilder::AddSubjectSlice(builder,
3976 match_end, 3994 match_end,
3977 subject_length); 3995 subject_length);
3978 } 3996 }
3979 3997
3980 int last_match_capture_count = (capture_count + 1) * 2; 3998 int last_match_capture_count = (capture_count + 1) * 2;
3981 int last_match_array_size = 3999 int last_match_array_size =
3982 last_match_capture_count + RegExpImpl::kLastMatchOverhead; 4000 last_match_capture_count + RegExpImpl::kLastMatchOverhead;
3983 last_match_array->EnsureSize(last_match_array_size); 4001 last_match_array->EnsureSize(last_match_array_size);
3984 AssertNoAllocation no_gc; 4002 AssertNoAllocation no_gc;
3985 FixedArray* elements = FixedArray::cast(last_match_array->elements()); 4003 FixedArray* elements = FixedArray::cast(last_match_array->elements());
3986 // We have to set this even though the rest of the last match array is 4004 // We have to set this even though the rest of the last match array is
3987 // ignored. 4005 // ignored.
3988 RegExpImpl::SetLastCaptureCount(elements, last_match_capture_count); 4006 RegExpImpl::SetLastCaptureCount(elements, last_match_capture_count);
3989 // These are also read without consulting the override. 4007 // These are also read without consulting the override.
3990 RegExpImpl::SetLastSubject(elements, *subject); 4008 RegExpImpl::SetLastSubject(elements, *subject);
3991 RegExpImpl::SetLastInput(elements, *subject); 4009 RegExpImpl::SetLastInput(elements, *subject);
3992 return RegExpImpl::RE_SUCCESS; 4010 return RegExpImpl::RE_SUCCESS;
3993 } 4011 }
3994 } 4012 }
3995 // No matches at all, return failure or exception result directly. 4013 // No matches at all, return failure or exception result directly.
3996 return result; 4014 return num_matches;
3997 } 4015 }
3998 4016
3999 4017
4000 // This is only called for StringReplaceGlobalRegExpWithFunction. This sets 4018 // This is only called for StringReplaceGlobalRegExpWithFunction. This sets
4001 // lastMatchInfoOverride to maintain the last match info, so we don't need to 4019 // lastMatchInfoOverride to maintain the last match info, so we don't need to
4002 // set any other last match array info. 4020 // set any other last match array info.
4003 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) { 4021 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
4004 ASSERT(args.length() == 4); 4022 ASSERT(args.length() == 4);
4005 HandleScope handles(isolate); 4023 HandleScope handles(isolate);
4006 4024
(...skipping 21 matching lines...) Expand all
4028 ASSERT(pattern->IsFlat()); 4046 ASSERT(pattern->IsFlat());
4029 if (SearchStringMultiple(isolate, subject, pattern, 4047 if (SearchStringMultiple(isolate, subject, pattern,
4030 last_match_info, &builder)) { 4048 last_match_info, &builder)) {
4031 return *builder.ToJSArray(result_array); 4049 return *builder.ToJSArray(result_array);
4032 } 4050 }
4033 return isolate->heap()->null_value(); 4051 return isolate->heap()->null_value();
4034 } 4052 }
4035 4053
4036 ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP); 4054 ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
4037 4055
4038 RegExpImpl::IrregexpResult result; 4056 int result;
4039 if (regexp->CaptureCount() == 0) { 4057 if (regexp->CaptureCount() == 0) {
4040 result = SearchRegExpNoCaptureMultiple(isolate, 4058 result = SearchRegExpNoCaptureMultiple(isolate,
4041 subject, 4059 subject,
4042 regexp, 4060 regexp,
4043 last_match_info, 4061 last_match_info,
4044 &builder); 4062 &builder);
4045 } else { 4063 } else {
4046 result = SearchRegExpMultiple(isolate, 4064 result = SearchRegExpMultiple(isolate,
4047 subject, 4065 subject,
4048 regexp, 4066 regexp,
(...skipping 9456 matching lines...) Expand 10 before | Expand all | Expand 10 after
13505 // Handle last resort GC and make sure to allow future allocations 13523 // Handle last resort GC and make sure to allow future allocations
13506 // to grow the heap without causing GCs (if possible). 13524 // to grow the heap without causing GCs (if possible).
13507 isolate->counters()->gc_last_resort_from_js()->Increment(); 13525 isolate->counters()->gc_last_resort_from_js()->Increment();
13508 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, 13526 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
13509 "Runtime::PerformGC"); 13527 "Runtime::PerformGC");
13510 } 13528 }
13511 } 13529 }
13512 13530
13513 13531
13514 } } // namespace v8::internal 13532 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698