Chromium Code Reviews| 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( |
|
Erik Corry
2012/05/11 11:01:00
I wonder if we can unify this and SearchRegExpMult
Yang
2012/05/16 14:58:47
I'll try this in another CL.
| |
| 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 int match_start = -1; | 3805 int match_start = -1; |
| 3806 int match_end = 0; | 3806 int match_end = 0; |
| 3807 int pos = 0; | 3807 int pos = 0; |
| 3808 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject); | 3808 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject); |
| 3809 if (required_registers < 0) return RegExpImpl::RE_EXCEPTION; | 3809 if (required_registers < 0) return RegExpImpl::RE_EXCEPTION; |
| 3810 | 3810 |
| 3811 OffsetsVector registers(required_registers, isolate); | 3811 OffsetsVector registers(OffsetsVector::kStaticOffsetsVectorSize, isolate); |
| 3812 static const int max_result_sets = | |
| 3813 OffsetsVector::kStaticOffsetsVectorSize / 2; | |
| 3812 Vector<int32_t> register_vector(registers.vector(), registers.length()); | 3814 Vector<int32_t> register_vector(registers.vector(), registers.length()); |
| 3813 int subject_length = subject->length(); | 3815 int subject_length = subject->length(); |
| 3814 bool first = true; | 3816 bool first = true; |
| 3815 | |
| 3816 for (;;) { // Break on failure, return on exception. | 3817 for (;;) { // Break on failure, return on exception. |
| 3817 RegExpImpl::IrregexpResult result = | 3818 int result = |
|
Erik Corry
2012/05/11 11:01:00
How about giving this variable a name like number_
Yang
2012/05/16 14:58:47
Done.
| |
| 3818 RegExpImpl::IrregexpExecOnce(regexp, | 3819 RegExpImpl::IrregexpExecOnce(regexp, |
| 3819 subject, | 3820 subject, |
| 3820 pos, | 3821 pos, |
| 3821 register_vector); | 3822 register_vector); |
| 3822 if (result == RegExpImpl::RE_SUCCESS) { | 3823 if (result >= RegExpImpl::RE_SUCCESS) { |
| 3823 match_start = register_vector[0]; | 3824 for (int result_index = 0; result_index < result; result_index++) { |
| 3824 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); | 3825 int32_t* current_result_set = ®ister_vector[result_index * 2]; |
| 3825 if (match_end < match_start) { | 3826 match_start = current_result_set[0]; |
| 3826 ReplacementStringBuilder::AddSubjectSlice(builder, | 3827 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); |
| 3827 match_end, | 3828 if (match_end < match_start) { |
| 3828 match_start); | 3829 ReplacementStringBuilder::AddSubjectSlice(builder, |
| 3830 match_end, | |
| 3831 match_start); | |
| 3832 } | |
| 3833 match_end = current_result_set[1]; | |
| 3834 HandleScope loop_scope(isolate); | |
| 3835 if (!first) { | |
| 3836 builder->Add(*isolate->factory()->NewProperSubString(subject, | |
| 3837 match_start, | |
| 3838 match_end)); | |
| 3839 } else { | |
| 3840 builder->Add(*isolate->factory()->NewSubString(subject, | |
| 3841 match_start, | |
| 3842 match_end)); | |
| 3843 } | |
| 3844 first = false; | |
| 3829 } | 3845 } |
| 3830 match_end = register_vector[1]; | 3846 |
| 3831 HandleScope loop_scope(isolate); | 3847 // If we did not get the maximum number of resultsets, we can stop here |
| 3832 if (!first) { | 3848 // since there are no matches left. |
| 3833 builder->Add(*isolate->factory()->NewProperSubString(subject, | 3849 if (result < max_result_sets) break; |
| 3834 match_start, | 3850 |
| 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) { | 3851 if (match_start != match_end) { |
|
Erik Corry
2012/05/11 11:01:00
I don't see this logic replicated in the regexp-ma
| |
| 3842 pos = match_end; | 3852 pos = match_end; |
| 3843 } else { | 3853 } else { |
| 3844 pos = match_end + 1; | 3854 pos = match_end + 1; |
| 3845 if (pos > subject_length) break; | 3855 if (pos > subject_length) { |
|
Erik Corry
2012/05/11 11:01:00
unneeded edit
| |
| 3856 break; | |
| 3857 } | |
| 3846 } | 3858 } |
| 3847 } else if (result == RegExpImpl::RE_FAILURE) { | 3859 } else if (result == RegExpImpl::RE_FAILURE) { |
| 3848 break; | 3860 break; |
| 3849 } else { | 3861 } else { |
| 3850 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION); | 3862 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION); |
| 3851 return result; | 3863 return result; |
| 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_result_set = RegExpImpl::IrregexpPrepare(regexp, subject); |
| 3884 if (required_registers < 0) return RegExpImpl::RE_EXCEPTION; | 3895 if (registers_per_result_set < 0) return RegExpImpl::RE_EXCEPTION; |
| 3885 | 3896 |
| 3886 OffsetsVector registers(required_registers, isolate); | 3897 int num_registers = Min(OffsetsVector::kStaticOffsetsVectorSize, |
| 3898 registers_per_result_set); | |
| 3899 int max_result_sets = num_registers / registers_per_result_set; | |
| 3900 OffsetsVector registers(OffsetsVector::kStaticOffsetsVectorSize, isolate); | |
| 3887 Vector<int32_t> register_vector(registers.vector(), registers.length()); | 3901 Vector<int32_t> register_vector(registers.vector(), registers.length()); |
| 3888 | 3902 |
| 3889 RegExpImpl::IrregexpResult result = | 3903 int result = RegExpImpl::IrregexpExecOnce(regexp, |
| 3890 RegExpImpl::IrregexpExecOnce(regexp, | 3904 subject, |
| 3891 subject, | 3905 0, |
| 3892 0, | 3906 register_vector); |
| 3893 register_vector); | |
| 3894 | 3907 |
| 3895 int capture_count = regexp->CaptureCount(); | 3908 int capture_count = regexp->CaptureCount(); |
| 3896 int subject_length = subject->length(); | 3909 int subject_length = subject->length(); |
| 3897 | 3910 |
| 3898 // Position to search from. | 3911 // Position to search from. |
| 3899 int pos = 0; | 3912 int pos = 0; |
| 3900 // End of previous match. Differs from pos if match was empty. | 3913 // End of previous match. Differs from pos if match was empty. |
| 3901 int match_end = 0; | 3914 int match_end = 0; |
| 3902 if (result == RegExpImpl::RE_SUCCESS) { | 3915 if (result >= RegExpImpl::RE_SUCCESS) { |
| 3903 bool first = true; | 3916 bool first = true; |
| 3904 do { | 3917 do { |
| 3905 int match_start = register_vector[0]; | 3918 int match_start = 0; |
| 3906 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); | 3919 for (int result_index = 0; result_index < result; result_index++) { |
| 3907 if (match_end < match_start) { | 3920 int32_t* current_result_set = |
| 3908 ReplacementStringBuilder::AddSubjectSlice(builder, | 3921 ®ister_vector[result_index * registers_per_result_set]; |
| 3909 match_end, | 3922 match_start = current_result_set[0]; |
| 3910 match_start); | 3923 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); |
| 3924 if (match_end < match_start) { | |
| 3925 ReplacementStringBuilder::AddSubjectSlice(builder, | |
| 3926 match_end, | |
| 3927 match_start); | |
| 3928 } | |
| 3929 match_end = current_result_set[1]; | |
| 3930 | |
| 3931 { | |
| 3932 // Avoid accumulating new handles inside loop. | |
| 3933 HandleScope temp_scope(isolate); | |
| 3934 // Arguments array to replace function is match, captures, index and | |
| 3935 // subject, i.e., 3 + capture count in total. | |
| 3936 Handle<FixedArray> elements = | |
| 3937 isolate->factory()->NewFixedArray(3 + capture_count); | |
| 3938 Handle<String> match; | |
| 3939 if (!first) { | |
| 3940 match = isolate->factory()->NewProperSubString(subject, | |
|
Erik Corry
2012/05/11 11:01:00
Not sure why we need NewProperSubString here.
Yang
2012/05/16 14:58:47
For every substring save for the first one we know
| |
| 3941 match_start, | |
| 3942 match_end); | |
| 3943 } else { | |
| 3944 match = isolate->factory()->NewSubString(subject, | |
| 3945 match_start, | |
| 3946 match_end); | |
| 3947 } | |
| 3948 elements->set(0, *match); | |
| 3949 for (int i = 1; i <= capture_count; i++) { | |
|
Erik Corry
2012/05/11 11:01:00
I think you could just start this loop at 0 and re
Yang
2012/05/16 14:58:47
After removing the call to NewSubString here (firs
| |
| 3950 int start = current_result_set[i * 2]; | |
| 3951 if (start >= 0) { | |
| 3952 int end = current_result_set[i * 2 + 1]; | |
| 3953 ASSERT(start <= end); | |
| 3954 Handle<String> substring; | |
| 3955 if (!first) { | |
| 3956 substring = isolate->factory()->NewProperSubString(subject, | |
| 3957 start, | |
| 3958 end); | |
| 3959 } else { | |
| 3960 substring = isolate->factory()->NewSubString(subject, | |
| 3961 start, | |
| 3962 end); | |
| 3963 } | |
| 3964 elements->set(i, *substring); | |
| 3965 } else { | |
| 3966 ASSERT(current_result_set[i * 2 + 1] < 0); | |
| 3967 elements->set(i, isolate->heap()->undefined_value()); | |
| 3968 } | |
| 3969 } | |
| 3970 elements->set(capture_count + 1, Smi::FromInt(match_start)); | |
| 3971 elements->set(capture_count + 2, *subject); | |
| 3972 builder->Add(*isolate->factory()->NewJSArrayWithElements(elements)); | |
| 3973 } | |
| 3911 } | 3974 } |
| 3912 match_end = register_vector[1]; | |
| 3913 | 3975 |
| 3914 { | 3976 // If we did not get the maximum number of resultsets, we can stop here |
| 3915 // Avoid accumulating new handles inside loop. | 3977 // since there are no matches left. |
| 3916 HandleScope temp_scope(isolate); | 3978 if (result < max_result_sets) 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 | 3979 |
| 3956 if (match_end > match_start) { | 3980 if (match_end > match_start) { |
| 3957 pos = match_end; | 3981 pos = match_end; |
| 3958 } else { | 3982 } else { |
| 3959 pos = match_end + 1; | 3983 pos = match_end + 1; |
| 3960 if (pos > subject_length) { | 3984 if (pos > subject_length) { |
| 3961 break; | 3985 break; |
| 3962 } | 3986 } |
| 3963 } | 3987 } |
| 3964 | 3988 |
| 3965 result = RegExpImpl::IrregexpExecOnce(regexp, | 3989 result = RegExpImpl::IrregexpExecOnce(regexp, |
| 3966 subject, | 3990 subject, |
| 3967 pos, | 3991 pos, |
| 3968 register_vector); | 3992 register_vector); |
| 3969 first = false; | 3993 first = false; |
| 3970 } while (result == RegExpImpl::RE_SUCCESS); | 3994 } while (result >= RegExpImpl::RE_SUCCESS); |
| 3971 | 3995 |
| 3972 if (result != RegExpImpl::RE_EXCEPTION) { | 3996 if (result != RegExpImpl::RE_EXCEPTION) { |
| 3973 // Finished matching, with at least one match. | 3997 // Finished matching, with at least one match. |
| 3974 if (match_end < subject_length) { | 3998 if (match_end < subject_length) { |
| 3975 ReplacementStringBuilder::AddSubjectSlice(builder, | 3999 ReplacementStringBuilder::AddSubjectSlice(builder, |
| 3976 match_end, | 4000 match_end, |
| 3977 subject_length); | 4001 subject_length); |
| 3978 } | 4002 } |
| 3979 | 4003 |
| 3980 int last_match_capture_count = (capture_count + 1) * 2; | 4004 int last_match_capture_count = (capture_count + 1) * 2; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4028 ASSERT(pattern->IsFlat()); | 4052 ASSERT(pattern->IsFlat()); |
| 4029 if (SearchStringMultiple(isolate, subject, pattern, | 4053 if (SearchStringMultiple(isolate, subject, pattern, |
| 4030 last_match_info, &builder)) { | 4054 last_match_info, &builder)) { |
| 4031 return *builder.ToJSArray(result_array); | 4055 return *builder.ToJSArray(result_array); |
| 4032 } | 4056 } |
| 4033 return isolate->heap()->null_value(); | 4057 return isolate->heap()->null_value(); |
| 4034 } | 4058 } |
| 4035 | 4059 |
| 4036 ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP); | 4060 ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP); |
| 4037 | 4061 |
| 4038 RegExpImpl::IrregexpResult result; | 4062 int result; |
| 4039 if (regexp->CaptureCount() == 0) { | 4063 if (regexp->CaptureCount() == 0) { |
| 4040 result = SearchRegExpNoCaptureMultiple(isolate, | 4064 result = SearchRegExpNoCaptureMultiple(isolate, |
| 4041 subject, | 4065 subject, |
| 4042 regexp, | 4066 regexp, |
| 4043 last_match_info, | 4067 last_match_info, |
| 4044 &builder); | 4068 &builder); |
| 4045 } else { | 4069 } else { |
| 4046 result = SearchRegExpMultiple(isolate, | 4070 result = SearchRegExpMultiple(isolate, |
| 4047 subject, | 4071 subject, |
| 4048 regexp, | 4072 regexp, |
| 4049 last_match_info, | 4073 last_match_info, |
| 4050 &builder); | 4074 &builder); |
| 4051 } | 4075 } |
| 4052 if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array); | 4076 if (result >= RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array); |
| 4053 if (result == RegExpImpl::RE_FAILURE) return isolate->heap()->null_value(); | 4077 if (result == RegExpImpl::RE_FAILURE) return isolate->heap()->null_value(); |
| 4054 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION); | 4078 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION); |
| 4055 return Failure::Exception(); | 4079 return Failure::Exception(); |
| 4056 } | 4080 } |
| 4057 | 4081 |
| 4058 | 4082 |
| 4059 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) { | 4083 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) { |
| 4060 NoHandleAllocation ha; | 4084 NoHandleAllocation ha; |
| 4061 ASSERT(args.length() == 2); | 4085 ASSERT(args.length() == 2); |
| 4062 CONVERT_SMI_ARG_CHECKED(radix, 1); | 4086 CONVERT_SMI_ARG_CHECKED(radix, 1); |
| (...skipping 9442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 13505 // Handle last resort GC and make sure to allow future allocations | 13529 // Handle last resort GC and make sure to allow future allocations |
| 13506 // to grow the heap without causing GCs (if possible). | 13530 // to grow the heap without causing GCs (if possible). |
| 13507 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13531 isolate->counters()->gc_last_resort_from_js()->Increment(); |
| 13508 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 13532 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
| 13509 "Runtime::PerformGC"); | 13533 "Runtime::PerformGC"); |
| 13510 } | 13534 } |
| 13511 } | 13535 } |
| 13512 | 13536 |
| 13513 | 13537 |
| 13514 } } // namespace v8::internal | 13538 } } // namespace v8::internal |
| OLD | NEW |