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 955 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
966 virtual ~VectorBackedMatch() {} | 966 virtual ~VectorBackedMatch() {} |
967 | 967 |
968 private: | 968 private: |
969 Isolate* isolate_; | 969 Isolate* isolate_; |
970 Handle<String> subject_; | 970 Handle<String> subject_; |
971 Handle<String> match_; | 971 Handle<String> match_; |
972 const int match_position_; | 972 const int match_position_; |
973 ZoneVector<Handle<Object>>* captures_; | 973 ZoneVector<Handle<Object>>* captures_; |
974 }; | 974 }; |
975 | 975 |
976 // Only called from RegExpExecMultiple so it doesn't need to maintain | 976 // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain |
977 // separate last match info. See comment on that function. | 977 // separate last match info. See comment on that function. |
978 template <bool has_capture> | 978 template <bool has_capture> |
979 MaybeHandle<Object> SearchRegExpMultiple( | 979 static Object* SearchRegExpMultiple(Isolate* isolate, Handle<String> subject, |
980 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp, | 980 Handle<JSRegExp> regexp, |
981 Handle<RegExpMatchInfo> last_match_array, | 981 Handle<RegExpMatchInfo> last_match_array, |
982 Handle<FixedArray> result_elements) { | 982 Handle<JSArray> result_array) { |
983 DCHECK(subject->IsFlat()); | 983 DCHECK(subject->IsFlat()); |
984 DCHECK_NE(has_capture, regexp->CaptureCount() == 0); | 984 DCHECK_NE(has_capture, regexp->CaptureCount() == 0); |
985 | 985 |
986 int capture_count = regexp->CaptureCount(); | 986 int capture_count = regexp->CaptureCount(); |
987 int subject_length = subject->length(); | 987 int subject_length = subject->length(); |
988 | 988 |
989 static const int kMinLengthToCache = 0x1000; | 989 static const int kMinLengthToCache = 0x1000; |
990 | 990 |
991 if (subject_length > kMinLengthToCache) { | 991 if (subject_length > kMinLengthToCache) { |
992 FixedArray* last_match_cache; | 992 FixedArray* last_match_cache; |
993 Object* cached_answer = RegExpResultsCache::Lookup( | 993 Object* cached_answer = RegExpResultsCache::Lookup( |
994 isolate->heap(), *subject, regexp->data(), &last_match_cache, | 994 isolate->heap(), *subject, regexp->data(), &last_match_cache, |
995 RegExpResultsCache::REGEXP_MULTIPLE_INDICES); | 995 RegExpResultsCache::REGEXP_MULTIPLE_INDICES); |
996 if (cached_answer->IsFixedArray()) { | 996 if (cached_answer->IsFixedArray()) { |
997 int capture_registers = (capture_count + 1) * 2; | 997 int capture_registers = (capture_count + 1) * 2; |
998 int32_t* last_match = NewArray<int32_t>(capture_registers); | 998 int32_t* last_match = NewArray<int32_t>(capture_registers); |
999 for (int i = 0; i < capture_registers; i++) { | 999 for (int i = 0; i < capture_registers; i++) { |
1000 last_match[i] = Smi::cast(last_match_cache->get(i))->value(); | 1000 last_match[i] = Smi::cast(last_match_cache->get(i))->value(); |
1001 } | 1001 } |
1002 Handle<FixedArray> cached_fixed_array(FixedArray::cast(cached_answer)); | 1002 Handle<FixedArray> cached_fixed_array = |
1003 Handle<FixedArray>(FixedArray::cast(cached_answer)); | |
1004 // The cache FixedArray is a COW-array and we need to return a copy. | |
jgruber
2016/10/19 16:39:13
It might not make sense anymore for the result cac
Yang
2016/10/20 09:53:14
I'd simply introduce a version of SBC that only ta
jgruber
2016/10/20 10:58:30
That would work, I'm just not sure what we would g
| |
1005 Handle<FixedArray> copied_fixed_array = | |
1006 isolate->factory()->CopyFixedArrayWithMap( | |
1007 cached_fixed_array, isolate->factory()->fixed_array_map()); | |
1008 JSArray::SetContent(result_array, copied_fixed_array); | |
1003 RegExpImpl::SetLastMatchInfo(last_match_array, subject, capture_count, | 1009 RegExpImpl::SetLastMatchInfo(last_match_array, subject, capture_count, |
1004 last_match); | 1010 last_match); |
1005 DeleteArray(last_match); | 1011 DeleteArray(last_match); |
1006 // The cache FixedArray is a COW-array and we need to return a copy. | 1012 return *result_array; |
1007 return isolate->factory()->CopyFixedArrayWithMap( | |
1008 cached_fixed_array, isolate->factory()->fixed_array_map()); | |
1009 } | 1013 } |
1010 } | 1014 } |
1011 | 1015 |
1012 RegExpImpl::GlobalCache global_cache(regexp, subject, isolate); | 1016 RegExpImpl::GlobalCache global_cache(regexp, subject, isolate); |
1013 if (global_cache.HasException()) return MaybeHandle<Object>(); | 1017 if (global_cache.HasException()) return isolate->heap()->exception(); |
1014 | 1018 |
1015 // Ensured in Runtime_RegExpExecMultiple. | 1019 // Ensured in Runtime_RegExpExecMultiple. |
1020 DCHECK(result_array->HasFastObjectElements()); | |
1021 Handle<FixedArray> result_elements( | |
1022 FixedArray::cast(result_array->elements())); | |
1016 if (result_elements->length() < 16) { | 1023 if (result_elements->length() < 16) { |
1017 result_elements = isolate->factory()->NewFixedArrayWithHoles(16); | 1024 result_elements = isolate->factory()->NewFixedArrayWithHoles(16); |
1018 } | 1025 } |
1019 | 1026 |
1020 FixedArrayBuilder builder(result_elements); | 1027 FixedArrayBuilder builder(result_elements); |
1021 | 1028 |
1022 // Position to search from. | 1029 // Position to search from. |
1023 int match_start = -1; | 1030 int match_start = -1; |
1024 int match_end = 0; | 1031 int match_end = 0; |
1025 bool first = true; | 1032 bool first = true; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1072 } | 1079 } |
1073 elements->set(capture_count + 1, Smi::FromInt(match_start)); | 1080 elements->set(capture_count + 1, Smi::FromInt(match_start)); |
1074 elements->set(capture_count + 2, *subject); | 1081 elements->set(capture_count + 2, *subject); |
1075 builder.Add(*isolate->factory()->NewJSArrayWithElements(elements)); | 1082 builder.Add(*isolate->factory()->NewJSArrayWithElements(elements)); |
1076 } else { | 1083 } else { |
1077 builder.Add(*match); | 1084 builder.Add(*match); |
1078 } | 1085 } |
1079 } | 1086 } |
1080 } | 1087 } |
1081 | 1088 |
1082 if (global_cache.HasException()) return MaybeHandle<Object>(); | 1089 if (global_cache.HasException()) return isolate->heap()->exception(); |
1083 | 1090 |
1084 if (match_start >= 0) { | 1091 if (match_start >= 0) { |
1085 // Finished matching, with at least one match. | 1092 // Finished matching, with at least one match. |
1086 if (match_end < subject_length) { | 1093 if (match_end < subject_length) { |
1087 ReplacementStringBuilder::AddSubjectSlice(&builder, match_end, | 1094 ReplacementStringBuilder::AddSubjectSlice(&builder, match_end, |
1088 subject_length); | 1095 subject_length); |
1089 } | 1096 } |
1090 | 1097 |
1091 RegExpImpl::SetLastMatchInfo(last_match_array, subject, capture_count, | 1098 RegExpImpl::SetLastMatchInfo(last_match_array, subject, capture_count, |
1092 global_cache.LastSuccessfulMatch()); | 1099 global_cache.LastSuccessfulMatch()); |
1093 | 1100 |
1094 Handle<FixedArray> result_fixed_array = builder.array(); | |
1095 result_fixed_array->Shrink(builder.length()); | |
1096 | |
1097 if (subject_length > kMinLengthToCache) { | 1101 if (subject_length > kMinLengthToCache) { |
1098 // Store the last successful match into the array for caching. | 1102 // Store the last successful match into the array for caching. |
1099 // TODO(yangguo): do not expose last match to JS and simplify caching. | 1103 // TODO(yangguo): do not expose last match to JS and simplify caching. |
1100 int capture_registers = (capture_count + 1) * 2; | 1104 int capture_registers = (capture_count + 1) * 2; |
1101 Handle<FixedArray> last_match_cache = | 1105 Handle<FixedArray> last_match_cache = |
1102 isolate->factory()->NewFixedArray(capture_registers); | 1106 isolate->factory()->NewFixedArray(capture_registers); |
1103 int32_t* last_match = global_cache.LastSuccessfulMatch(); | 1107 int32_t* last_match = global_cache.LastSuccessfulMatch(); |
1104 for (int i = 0; i < capture_registers; i++) { | 1108 for (int i = 0; i < capture_registers; i++) { |
1105 last_match_cache->set(i, Smi::FromInt(last_match[i])); | 1109 last_match_cache->set(i, Smi::FromInt(last_match[i])); |
1106 } | 1110 } |
1107 // Cache the result and turn the FixedArray into a COW array. | 1111 Handle<FixedArray> result_fixed_array = builder.array(); |
1112 result_fixed_array->Shrink(builder.length()); | |
1113 // Cache the result and copy the FixedArray into a COW array. | |
1114 Handle<FixedArray> copied_fixed_array = | |
1115 isolate->factory()->CopyFixedArrayWithMap( | |
1116 result_fixed_array, isolate->factory()->fixed_array_map()); | |
1108 RegExpResultsCache::Enter( | 1117 RegExpResultsCache::Enter( |
1109 isolate, subject, handle(regexp->data(), isolate), result_fixed_array, | 1118 isolate, subject, handle(regexp->data(), isolate), copied_fixed_array, |
1110 last_match_cache, RegExpResultsCache::REGEXP_MULTIPLE_INDICES); | 1119 last_match_cache, RegExpResultsCache::REGEXP_MULTIPLE_INDICES); |
1111 } | 1120 } |
1112 // The cache FixedArray is a COW-array and we need to return a copy. | 1121 return *builder.ToJSArray(result_array); |
1113 return isolate->factory()->CopyFixedArrayWithMap( | |
1114 result_fixed_array, isolate->factory()->fixed_array_map()); | |
1115 } else { | 1122 } else { |
1116 return isolate->factory()->null_value(); // No matches at all. | 1123 return isolate->heap()->null_value(); // No matches at all. |
1117 } | 1124 } |
1118 } | 1125 } |
1119 | 1126 |
1120 // This is only called for StringReplaceGlobalRegExpWithFunction. This sets | |
1121 // lastMatchInfoOverride to maintain the last match info, so we don't need to | |
1122 // set any other last match array info. | |
1123 MaybeHandle<Object> RegExpExecMultiple(Isolate* isolate, | |
1124 Handle<JSRegExp> regexp, | |
1125 Handle<String> subject, | |
1126 Handle<RegExpMatchInfo> last_match_info, | |
1127 Handle<FixedArray> result_array) { | |
1128 subject = String::Flatten(subject); | |
1129 CHECK(regexp->GetFlags() & JSRegExp::kGlobal); | |
1130 | |
1131 if (regexp->CaptureCount() == 0) { | |
1132 return SearchRegExpMultiple<false>(isolate, subject, regexp, | |
1133 last_match_info, result_array); | |
1134 } else { | |
1135 return SearchRegExpMultiple<true>(isolate, subject, regexp, last_match_info, | |
1136 result_array); | |
1137 } | |
1138 } | |
1139 | |
1140 // Helper function for replacing regular expressions with the result of a | |
1141 // function application in String.prototype.replace. | |
1142 MaybeHandle<String> StringReplaceGlobalRegExpWithFunction( | |
1143 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp, | |
1144 Handle<Object> replace_obj) { | |
1145 Factory* factory = isolate->factory(); | |
1146 | |
1147 // TODO(jgruber): Convert result_array into a List<Handle<Object>> (or | |
1148 // similar) and adapt / remove FixedArrayBuilder. | |
1149 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info(); | |
1150 Handle<FixedArray> result_array = factory->NewFixedArrayWithHoles(16); | |
1151 | |
1152 Handle<Object> res; | |
1153 ASSIGN_RETURN_ON_EXCEPTION(isolate, res, | |
1154 RegExpExecMultiple(isolate, regexp, subject, | |
1155 last_match_info, result_array), | |
1156 String); | |
1157 | |
1158 // Reload the last match info since it might have changed in the meantime. | |
1159 last_match_info = isolate->regexp_last_match_info(); | |
1160 | |
1161 if (res->IsNull(isolate)) return subject; // No matches at all. | |
1162 | |
1163 result_array = Handle<FixedArray>::cast(res); | |
1164 const int result_length = result_array->length(); | |
1165 | |
1166 const int num_captures = last_match_info->NumberOfCaptureRegisters() / 2; | |
1167 if (num_captures == 1) { | |
1168 // If the number of captures is one then there are no explicit captures in | |
1169 // the regexp, just the implicit capture that captures the whole match. In | |
1170 // this case we can simplify quite a bit and end up with something faster. | |
1171 // The builder will consist of some integers that indicate slices of the | |
1172 // input string and some replacements that were returned from the replace | |
1173 // function. | |
1174 int match_start = 0; | |
1175 for (int i = 0; i < result_length; i++) { | |
1176 Handle<Object> elem = FixedArray::get(*result_array, i, isolate); | |
1177 if (elem->IsSmi()) { | |
1178 // Integers represent slices of the original string. | |
1179 // TODO(jgruber): Maybe we don't need this weird encoding anymore (in | |
1180 // preparation to invoking StringBuilderConcat), but can just copy into | |
1181 // the result string with the IncrementalStringBuilder as we go? | |
1182 const int elem_value = Handle<Smi>::cast(elem)->value(); | |
1183 if (elem_value > 0) { | |
1184 match_start = (elem_value >> 11) + (elem_value & 0x7ff); | |
1185 } else { | |
1186 Handle<Object> next_elem = | |
1187 FixedArray::get(*result_array, ++i, isolate); | |
1188 const int next_elem_value = Handle<Smi>::cast(next_elem)->value(); | |
1189 match_start = next_elem_value - elem_value; | |
1190 } | |
1191 } else { | |
1192 DCHECK(elem->IsString()); | |
1193 Handle<String> elem_string = Handle<String>::cast(elem); | |
1194 | |
1195 // Overwrite the i'th element in the results with the string we got | |
1196 // back from the callback function. | |
1197 const int argc = 3; | |
1198 ScopedVector<Handle<Object>> argv(argc); | |
1199 | |
1200 argv[0] = elem_string; | |
1201 argv[1] = handle(Smi::FromInt(match_start), isolate); | |
1202 argv[2] = subject; | |
1203 | |
1204 Handle<Object> replacement_obj; | |
1205 ASSIGN_RETURN_ON_EXCEPTION( | |
1206 isolate, replacement_obj, | |
1207 Execution::Call(isolate, replace_obj, factory->undefined_value(), | |
1208 argc, argv.start()), | |
1209 String); | |
1210 | |
1211 Handle<String> replacement; | |
1212 ASSIGN_RETURN_ON_EXCEPTION(isolate, replacement, | |
1213 Object::ToString(isolate, replacement_obj), | |
1214 String); | |
1215 | |
1216 result_array->set(i, *replacement); | |
1217 match_start += elem_string->length(); | |
1218 } | |
1219 } | |
1220 } else { | |
1221 DCHECK(num_captures > 1); | |
1222 for (int i = 0; i < result_length; i++) { | |
1223 Handle<Object> elem = FixedArray::get(*result_array, i, isolate); | |
1224 if (elem->IsSmi()) continue; | |
1225 | |
1226 // TODO(jgruber): We can skip this whole round-trip through a JS array | |
1227 // for result_array. | |
1228 Handle<JSArray> elem_array = Handle<JSArray>::cast(elem); | |
1229 Handle<FixedArray> elem_array_elems( | |
1230 FixedArray::cast(elem_array->elements()), isolate); | |
1231 | |
1232 const int argc = elem_array_elems->length(); | |
1233 ScopedVector<Handle<Object>> argv(argc); | |
1234 | |
1235 for (int j = 0; j < argc; j++) { | |
1236 argv[j] = FixedArray::get(*elem_array_elems, j, isolate); | |
1237 } | |
1238 | |
1239 // TODO(jgruber): This call is another pattern we could refactor. | |
1240 Handle<Object> replacement_obj; | |
1241 ASSIGN_RETURN_ON_EXCEPTION( | |
1242 isolate, replacement_obj, | |
1243 Execution::Call(isolate, replace_obj, factory->undefined_value(), | |
1244 argc, argv.start()), | |
1245 String); | |
1246 | |
1247 Handle<String> replacement; | |
1248 ASSIGN_RETURN_ON_EXCEPTION(isolate, replacement, | |
1249 Object::ToString(isolate, replacement_obj), | |
1250 String); | |
1251 | |
1252 result_array->set(i, *replacement); | |
1253 } | |
1254 } | |
1255 | |
1256 if (result_length == 0) { | |
1257 return factory->empty_string(); | |
1258 } else if (result_length == 1) { | |
1259 Handle<Object> first = FixedArray::get(*result_array, 0, isolate); | |
1260 if (first->IsString()) return Handle<String>::cast(first); | |
1261 } | |
1262 | |
1263 bool one_byte = subject->HasOnlyOneByteChars(); | |
1264 const int length = StringBuilderConcatLength(subject->length(), *result_array, | |
1265 result_length, &one_byte); | |
1266 | |
1267 if (length == -1) { | |
1268 isolate->Throw(isolate->heap()->illegal_argument_string()); | |
1269 return MaybeHandle<String>(); | |
1270 } | |
1271 | |
1272 if (one_byte) { | |
1273 Handle<SeqOneByteString> answer; | |
1274 ASSIGN_RETURN_ON_EXCEPTION(isolate, answer, | |
1275 isolate->factory()->NewRawOneByteString(length), | |
1276 String); | |
1277 StringBuilderConcatHelper(*subject, answer->GetChars(), *result_array, | |
1278 result_length); | |
1279 return answer; | |
1280 } else { | |
1281 DCHECK(!one_byte); | |
1282 Handle<SeqTwoByteString> answer; | |
1283 ASSIGN_RETURN_ON_EXCEPTION(isolate, answer, | |
1284 isolate->factory()->NewRawTwoByteString(length), | |
1285 String); | |
1286 StringBuilderConcatHelper(*subject, answer->GetChars(), *result_array, | |
1287 result_length); | |
1288 return answer; | |
1289 } | |
1290 | |
1291 UNREACHABLE(); | |
1292 return MaybeHandle<String>(); | |
1293 } | |
1294 | |
1295 MaybeHandle<String> StringReplaceNonGlobalRegExpWithFunction( | 1127 MaybeHandle<String> StringReplaceNonGlobalRegExpWithFunction( |
1296 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp, | 1128 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp, |
1297 Handle<Object> replace_obj) { | 1129 Handle<Object> replace_obj) { |
1298 Factory* factory = isolate->factory(); | 1130 Factory* factory = isolate->factory(); |
1299 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info(); | 1131 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info(); |
1300 | 1132 |
1301 // TODO(jgruber): This is a pattern we could refactor. | 1133 // TODO(jgruber): This is a pattern we could refactor. |
1302 Handle<Object> match_indices_obj; | 1134 Handle<Object> match_indices_obj; |
1303 ASSIGN_RETURN_ON_EXCEPTION( | 1135 ASSIGN_RETURN_ON_EXCEPTION( |
1304 isolate, match_indices_obj, | 1136 isolate, match_indices_obj, |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1437 Object* result = StringReplaceGlobalRegExpWithString( | 1269 Object* result = StringReplaceGlobalRegExpWithString( |
1438 isolate, string, regexp, replace, last_match_info); | 1270 isolate, string, regexp, replace, last_match_info); |
1439 if (result->IsString()) { | 1271 if (result->IsString()) { |
1440 return handle(String::cast(result), isolate); | 1272 return handle(String::cast(result), isolate); |
1441 } else { | 1273 } else { |
1442 return MaybeHandle<String>(); | 1274 return MaybeHandle<String>(); |
1443 } | 1275 } |
1444 } | 1276 } |
1445 } else { | 1277 } else { |
1446 DCHECK(functional_replace); | 1278 DCHECK(functional_replace); |
1447 if (global) { | 1279 DCHECK(!global); // Handled as fast path. |
jgruber
2016/10/19 16:39:13
The entire functional_replace branch should be rem
| |
1448 // Global regexp search, function replace. | 1280 // Non-global regexp search, function replace. |
1449 return StringReplaceGlobalRegExpWithFunction(isolate, string, regexp, | 1281 return StringReplaceNonGlobalRegExpWithFunction(isolate, string, regexp, |
1450 replace_obj); | 1282 replace_obj); |
1451 } else { | |
1452 // Non-global regexp search, function replace. | |
1453 return StringReplaceNonGlobalRegExpWithFunction(isolate, string, regexp, | |
1454 replace_obj); | |
1455 } | |
1456 } | 1283 } |
1457 | 1284 |
1458 UNREACHABLE(); | 1285 UNREACHABLE(); |
1459 return MaybeHandle<String>(); | 1286 return MaybeHandle<String>(); |
1460 } | 1287 } |
1461 | 1288 |
1462 } // namespace | 1289 } // namespace |
1463 | 1290 |
1464 RUNTIME_FUNCTION(Runtime_StringReplaceGlobalRegExpWithFunction) { | 1291 // This is only called for StringReplaceGlobalRegExpWithFunction. |
1465 HandleScope scope(isolate); | 1292 RUNTIME_FUNCTION(Runtime_RegExpExecMultiple) { |
1466 DCHECK(args.length() == 3); | 1293 HandleScope handles(isolate); |
1294 DCHECK(args.length() == 4); | |
1467 | 1295 |
1468 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); | 1296 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); |
1469 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); | 1297 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); |
1470 CONVERT_ARG_HANDLE_CHECKED(JSObject, replace, 2); | 1298 CONVERT_ARG_HANDLE_CHECKED(RegExpMatchInfo, last_match_info, 2); |
1299 CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3); | |
jgruber
2016/10/19 16:39:13
Reusing the result array does not seem to make any
Yang
2016/10/20 09:53:14
I wonder whether we need a JSArray for this at all
jgruber
2016/10/20 10:58:30
Sure. I kept the JSArray return type for now becau
| |
1300 CHECK(result_array->HasFastObjectElements()); | |
1471 | 1301 |
1472 RETURN_RESULT_OR_FAILURE(isolate, StringReplaceGlobalRegExpWithFunction( | 1302 subject = String::Flatten(subject); |
1473 isolate, subject, regexp, replace)); | 1303 CHECK(regexp->GetFlags() & JSRegExp::kGlobal); |
1304 | |
1305 if (regexp->CaptureCount() == 0) { | |
1306 return SearchRegExpMultiple<false>(isolate, subject, regexp, | |
1307 last_match_info, result_array); | |
1308 } else { | |
1309 return SearchRegExpMultiple<true>(isolate, subject, regexp, last_match_info, | |
1310 result_array); | |
1311 } | |
1474 } | 1312 } |
1475 | 1313 |
1476 RUNTIME_FUNCTION(Runtime_StringReplaceNonGlobalRegExpWithFunction) { | 1314 RUNTIME_FUNCTION(Runtime_StringReplaceNonGlobalRegExpWithFunction) { |
1477 HandleScope scope(isolate); | 1315 HandleScope scope(isolate); |
1478 DCHECK(args.length() == 3); | 1316 DCHECK(args.length() == 3); |
1479 | 1317 |
1480 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); | 1318 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); |
1481 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); | 1319 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); |
1482 CONVERT_ARG_HANDLE_CHECKED(JSObject, replace, 2); | 1320 CONVERT_ARG_HANDLE_CHECKED(JSObject, replace, 2); |
1483 | 1321 |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1681 | 1519 |
1682 RUNTIME_FUNCTION(Runtime_IsRegExp) { | 1520 RUNTIME_FUNCTION(Runtime_IsRegExp) { |
1683 SealHandleScope shs(isolate); | 1521 SealHandleScope shs(isolate); |
1684 DCHECK(args.length() == 1); | 1522 DCHECK(args.length() == 1); |
1685 CONVERT_ARG_CHECKED(Object, obj, 0); | 1523 CONVERT_ARG_CHECKED(Object, obj, 0); |
1686 return isolate->heap()->ToBoolean(obj->IsJSRegExp()); | 1524 return isolate->heap()->ToBoolean(obj->IsJSRegExp()); |
1687 } | 1525 } |
1688 | 1526 |
1689 } // namespace internal | 1527 } // namespace internal |
1690 } // namespace v8 | 1528 } // namespace v8 |
OLD | NEW |