OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/runtime/runtime-utils.h" | 5 #include "src/runtime/runtime-utils.h" |
6 | 6 |
7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
8 #include "src/conversions-inl.h" | 8 #include "src/conversions-inl.h" |
9 #include "src/isolate-inl.h" | 9 #include "src/isolate-inl.h" |
10 #include "src/messages.h" | 10 #include "src/messages.h" |
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
686 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); | 686 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); |
687 CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1); | 687 CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1); |
688 CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]); | 688 CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]); |
689 RUNTIME_ASSERT(limit > 0); | 689 RUNTIME_ASSERT(limit > 0); |
690 | 690 |
691 int subject_length = subject->length(); | 691 int subject_length = subject->length(); |
692 int pattern_length = pattern->length(); | 692 int pattern_length = pattern->length(); |
693 RUNTIME_ASSERT(pattern_length > 0); | 693 RUNTIME_ASSERT(pattern_length > 0); |
694 | 694 |
695 if (limit == 0xffffffffu) { | 695 if (limit == 0xffffffffu) { |
696 FixedArray* last_match_cache_unused; | |
696 Handle<Object> cached_answer( | 697 Handle<Object> cached_answer( |
697 RegExpResultsCache::Lookup(isolate->heap(), *subject, *pattern, | 698 RegExpResultsCache::Lookup(isolate->heap(), *subject, *pattern, |
699 &last_match_cache_unused, | |
698 RegExpResultsCache::STRING_SPLIT_SUBSTRINGS), | 700 RegExpResultsCache::STRING_SPLIT_SUBSTRINGS), |
699 isolate); | 701 isolate); |
700 if (*cached_answer != Smi::FromInt(0)) { | 702 if (*cached_answer != Smi::FromInt(0)) { |
701 // The cache FixedArray is a COW-array and can therefore be reused. | 703 // The cache FixedArray is a COW-array and can therefore be reused. |
702 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements( | 704 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements( |
703 Handle<FixedArray>::cast(cached_answer)); | 705 Handle<FixedArray>::cast(cached_answer)); |
704 return *result; | 706 return *result; |
705 } | 707 } |
706 } | 708 } |
707 | 709 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
750 Handle<String> substring = | 752 Handle<String> substring = |
751 isolate->factory()->NewProperSubString(subject, part_start, part_end); | 753 isolate->factory()->NewProperSubString(subject, part_start, part_end); |
752 elements->set(i, *substring); | 754 elements->set(i, *substring); |
753 part_start = part_end + pattern_length; | 755 part_start = part_end + pattern_length; |
754 } | 756 } |
755 } | 757 } |
756 | 758 |
757 if (limit == 0xffffffffu) { | 759 if (limit == 0xffffffffu) { |
758 if (result->HasFastObjectElements()) { | 760 if (result->HasFastObjectElements()) { |
759 RegExpResultsCache::Enter(isolate, subject, pattern, elements, | 761 RegExpResultsCache::Enter(isolate, subject, pattern, elements, |
762 isolate->factory()->empty_fixed_array(), | |
760 RegExpResultsCache::STRING_SPLIT_SUBSTRINGS); | 763 RegExpResultsCache::STRING_SPLIT_SUBSTRINGS); |
761 } | 764 } |
762 } | 765 } |
763 | 766 |
764 return *result; | 767 return *result; |
765 } | 768 } |
766 | 769 |
767 | 770 |
768 RUNTIME_FUNCTION(Runtime_RegExpExec) { | 771 RUNTIME_FUNCTION(Runtime_RegExpExec) { |
769 HandleScope scope(isolate); | 772 HandleScope scope(isolate); |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1010 Handle<JSArray> result_array) { | 1013 Handle<JSArray> result_array) { |
1011 DCHECK(subject->IsFlat()); | 1014 DCHECK(subject->IsFlat()); |
1012 DCHECK_NE(has_capture, regexp->CaptureCount() == 0); | 1015 DCHECK_NE(has_capture, regexp->CaptureCount() == 0); |
1013 | 1016 |
1014 int capture_count = regexp->CaptureCount(); | 1017 int capture_count = regexp->CaptureCount(); |
1015 int subject_length = subject->length(); | 1018 int subject_length = subject->length(); |
1016 | 1019 |
1017 static const int kMinLengthToCache = 0x1000; | 1020 static const int kMinLengthToCache = 0x1000; |
1018 | 1021 |
1019 if (subject_length > kMinLengthToCache) { | 1022 if (subject_length > kMinLengthToCache) { |
1020 Handle<Object> cached_answer( | 1023 FixedArray* last_match_cache; |
1021 RegExpResultsCache::Lookup(isolate->heap(), *subject, regexp->data(), | 1024 Object* cached_answer = RegExpResultsCache::Lookup( |
1022 RegExpResultsCache::REGEXP_MULTIPLE_INDICES), | 1025 isolate->heap(), *subject, regexp->data(), &last_match_cache, |
1023 isolate); | 1026 RegExpResultsCache::REGEXP_MULTIPLE_INDICES); |
1024 if (*cached_answer != Smi::FromInt(0)) { | 1027 if (cached_answer->IsFixedArray()) { |
1028 int capture_registers = (capture_count + 1) * 2; | |
1029 int32_t* last_match = NewArray<int32_t>(capture_registers); | |
1030 for (int i = 0; i < capture_registers; i++) { | |
1031 last_match[i] = Smi::cast(last_match_cache->get(i))->value(); | |
1032 } | |
1025 Handle<FixedArray> cached_fixed_array = | 1033 Handle<FixedArray> cached_fixed_array = |
1026 Handle<FixedArray>(FixedArray::cast(*cached_answer)); | 1034 Handle<FixedArray>(FixedArray::cast(cached_answer)); |
1027 // The cache FixedArray is a COW-array and can therefore be reused. | 1035 // The cache FixedArray is a COW-array and can therefore be reused. |
1028 JSArray::SetContent(result_array, cached_fixed_array); | 1036 JSArray::SetContent(result_array, cached_fixed_array); |
1029 // The actual length of the result array is stored in the last element of | |
1030 // the backing store (the backing FixedArray may have a larger capacity). | |
1031 Object* cached_fixed_array_last_element = | |
1032 cached_fixed_array->get(cached_fixed_array->length() - 1); | |
1033 Smi* js_array_length = Smi::cast(cached_fixed_array_last_element); | |
1034 result_array->set_length(js_array_length); | |
1035 RegExpImpl::SetLastMatchInfo(last_match_array, subject, capture_count, | 1037 RegExpImpl::SetLastMatchInfo(last_match_array, subject, capture_count, |
1036 NULL); | 1038 last_match); |
1039 DeleteArray(last_match); | |
1037 return *result_array; | 1040 return *result_array; |
1038 } | 1041 } |
1039 } | 1042 } |
1040 | 1043 |
1041 RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate); | 1044 RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate); |
1042 if (global_cache.HasException()) return isolate->heap()->exception(); | 1045 if (global_cache.HasException()) return isolate->heap()->exception(); |
1043 | 1046 |
1044 // Ensured in Runtime_RegExpExecMultiple. | 1047 // Ensured in Runtime_RegExpExecMultiple. |
1045 DCHECK(result_array->HasFastObjectElements()); | 1048 DCHECK(result_array->HasFastObjectElements()); |
1046 Handle<FixedArray> result_elements( | 1049 Handle<FixedArray> result_elements( |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1114 if (global_cache.HasException()) return isolate->heap()->exception(); | 1117 if (global_cache.HasException()) return isolate->heap()->exception(); |
1115 | 1118 |
1116 if (match_start >= 0) { | 1119 if (match_start >= 0) { |
1117 // Finished matching, with at least one match. | 1120 // Finished matching, with at least one match. |
1118 if (match_end < subject_length) { | 1121 if (match_end < subject_length) { |
1119 ReplacementStringBuilder::AddSubjectSlice(&builder, match_end, | 1122 ReplacementStringBuilder::AddSubjectSlice(&builder, match_end, |
1120 subject_length); | 1123 subject_length); |
1121 } | 1124 } |
1122 | 1125 |
1123 RegExpImpl::SetLastMatchInfo(last_match_array, subject, capture_count, | 1126 RegExpImpl::SetLastMatchInfo(last_match_array, subject, capture_count, |
1124 NULL); | 1127 global_cache.LastSuccessfulMatch()); |
1125 | 1128 |
1126 if (subject_length > kMinLengthToCache) { | 1129 if (subject_length > kMinLengthToCache) { |
1127 // Store the length of the result array into the last element of the | 1130 // Store the last successful match into the array for caching. |
1128 // backing FixedArray. | 1131 // TODO(yangguo): do not expose last match to JS and simplify caching. |
1129 builder.EnsureCapacity(1); | 1132 int capture_registers = (capture_count + 1) * 2; |
1130 Handle<FixedArray> fixed_array = builder.array(); | 1133 Handle<FixedArray> last_match_cache = |
1131 fixed_array->set(fixed_array->length() - 1, | 1134 isolate->factory()->NewFixedArray(capture_registers); |
1132 Smi::FromInt(builder.length())); | 1135 int32_t* last_match = global_cache.LastSuccessfulMatch(); |
1136 for (int i = 0; i < capture_registers; i++) { | |
1137 last_match_cache->set(i, Smi::FromInt(last_match[i])); | |
1138 } | |
1139 Handle<FixedArray> result_array = builder.array(); | |
brucedawson
2015/10/28 17:19:36
I'm worried about this variable declaration. The r
Yang
2015/10/29 12:55:27
Thanks. See https://codereview.chromium.org/140721
| |
1140 result_array->Shrink(builder.length()); | |
1133 // Cache the result and turn the FixedArray into a COW array. | 1141 // Cache the result and turn the FixedArray into a COW array. |
1134 RegExpResultsCache::Enter(isolate, subject, | 1142 RegExpResultsCache::Enter( |
1135 handle(regexp->data(), isolate), fixed_array, | 1143 isolate, subject, handle(regexp->data(), isolate), result_array, |
1136 RegExpResultsCache::REGEXP_MULTIPLE_INDICES); | 1144 last_match_cache, RegExpResultsCache::REGEXP_MULTIPLE_INDICES); |
1137 } | 1145 } |
1138 return *builder.ToJSArray(result_array); | 1146 return *builder.ToJSArray(result_array); |
1139 } else { | 1147 } else { |
1140 return isolate->heap()->null_value(); // No matches at all. | 1148 return isolate->heap()->null_value(); // No matches at all. |
1141 } | 1149 } |
1142 } | 1150 } |
1143 | 1151 |
1144 | 1152 |
1145 // This is only called for StringReplaceGlobalRegExpWithFunction. This sets | 1153 // This is only called for StringReplaceGlobalRegExpWithFunction. This sets |
1146 // lastMatchInfoOverride to maintain the last match info, so we don't need to | 1154 // lastMatchInfoOverride to maintain the last match info, so we don't need to |
1147 // set any other last match array info. | 1155 // set any other last match array info. |
1148 RUNTIME_FUNCTION(Runtime_RegExpExecMultiple) { | 1156 RUNTIME_FUNCTION(Runtime_RegExpExecMultiple) { |
1149 HandleScope handles(isolate); | 1157 HandleScope handles(isolate); |
1150 DCHECK(args.length() == 4); | 1158 DCHECK(args.length() == 4); |
1151 | 1159 |
1160 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); | |
1152 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); | 1161 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); |
1153 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); | |
1154 CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2); | 1162 CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2); |
1155 CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3); | 1163 CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3); |
1156 RUNTIME_ASSERT(last_match_info->HasFastObjectElements()); | 1164 RUNTIME_ASSERT(last_match_info->HasFastObjectElements()); |
1157 RUNTIME_ASSERT(result_array->HasFastObjectElements()); | 1165 RUNTIME_ASSERT(result_array->HasFastObjectElements()); |
1158 | 1166 |
1159 subject = String::Flatten(subject); | 1167 subject = String::Flatten(subject); |
1160 RUNTIME_ASSERT(regexp->GetFlags().is_global()); | 1168 RUNTIME_ASSERT(regexp->GetFlags().is_global()); |
1161 | 1169 |
1162 if (regexp->CaptureCount() == 0) { | 1170 if (regexp->CaptureCount() == 0) { |
1163 return SearchRegExpMultiple<false>(isolate, subject, regexp, | 1171 return SearchRegExpMultiple<false>(isolate, subject, regexp, |
(...skipping 15 matching lines...) Expand all Loading... | |
1179 | 1187 |
1180 | 1188 |
1181 RUNTIME_FUNCTION(Runtime_IsRegExp) { | 1189 RUNTIME_FUNCTION(Runtime_IsRegExp) { |
1182 SealHandleScope shs(isolate); | 1190 SealHandleScope shs(isolate); |
1183 DCHECK(args.length() == 1); | 1191 DCHECK(args.length() == 1); |
1184 CONVERT_ARG_CHECKED(Object, obj, 0); | 1192 CONVERT_ARG_CHECKED(Object, obj, 0); |
1185 return isolate->heap()->ToBoolean(obj->IsJSRegExp()); | 1193 return isolate->heap()->ToBoolean(obj->IsJSRegExp()); |
1186 } | 1194 } |
1187 } // namespace internal | 1195 } // namespace internal |
1188 } // namespace v8 | 1196 } // namespace v8 |
OLD | NEW |