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 3777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 = ®ister_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 ®ister_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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |