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

Side by Side Diff: src/builtins/builtins-regexp.cc

Issue 2415103002: [regexp] Turn last match info into a simple FixedArray (Closed)
Patch Set: Don't check instance type before map check Created 4 years, 2 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
« no previous file with comments | « src/bootstrapper.cc ('k') | src/contexts.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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/builtins/builtins-utils.h" 5 #include "src/builtins/builtins-utils.h"
6 #include "src/builtins/builtins.h" 6 #include "src/builtins/builtins.h"
7 7
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/regexp/jsregexp.h" 9 #include "src/regexp/jsregexp.h"
10 #include "src/regexp/regexp-utils.h" 10 #include "src/regexp/regexp-utils.h"
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 language_mode); 243 language_mode);
244 a->Goto(&out); 244 a->Goto(&out);
245 } 245 }
246 246
247 a->Bind(&out); 247 a->Bind(&out);
248 } 248 }
249 249
250 compiler::Node* ConstructNewResultFromMatchInfo(Isolate* isolate, 250 compiler::Node* ConstructNewResultFromMatchInfo(Isolate* isolate,
251 CodeStubAssembler* a, 251 CodeStubAssembler* a,
252 compiler::Node* context, 252 compiler::Node* context,
253 compiler::Node* match_elements, 253 compiler::Node* match_info,
254 compiler::Node* string) { 254 compiler::Node* string) {
255 typedef CodeStubAssembler::Variable Variable; 255 typedef CodeStubAssembler::Variable Variable;
256 typedef CodeStubAssembler::Label Label; 256 typedef CodeStubAssembler::Label Label;
257 typedef compiler::Node Node; 257 typedef compiler::Node Node;
258 258
259 Label out(a); 259 Label out(a);
260 260
261 CodeStubAssembler::ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; 261 CodeStubAssembler::ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
262 Node* const num_indices = a->SmiUntag(a->LoadFixedArrayElement( 262 Node* const num_indices = a->SmiUntag(a->LoadFixedArrayElement(
263 match_elements, a->IntPtrConstant(RegExpImpl::kLastCaptureCount), 0, 263 match_info, a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0,
264 mode)); 264 mode));
265 Node* const num_results = a->SmiTag(a->WordShr(num_indices, 1)); 265 Node* const num_results = a->SmiTag(a->WordShr(num_indices, 1));
266 Node* const start = a->LoadFixedArrayElement( 266 Node* const start = a->LoadFixedArrayElement(
267 match_elements, a->IntPtrConstant(RegExpImpl::kFirstCapture), 0, mode); 267 match_info, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), 0,
268 mode);
268 Node* const end = a->LoadFixedArrayElement( 269 Node* const end = a->LoadFixedArrayElement(
269 match_elements, a->IntPtrConstant(RegExpImpl::kFirstCapture + 1), 0, 270 match_info, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0,
270 mode); 271 mode);
271 272
272 // Calculate the substring of the first match before creating the result array 273 // Calculate the substring of the first match before creating the result array
273 // to avoid an unnecessary write barrier storing the first result. 274 // to avoid an unnecessary write barrier storing the first result.
274 Node* const first = a->SubString(context, string, start, end); 275 Node* const first = a->SubString(context, string, start, end);
275 276
276 Node* const result = 277 Node* const result =
277 a->AllocateRegExpResult(context, num_results, start, string); 278 a->AllocateRegExpResult(context, num_results, start, string);
278 Node* const result_elements = a->LoadElements(result); 279 Node* const result_elements = a->LoadElements(result);
279 280
280 a->StoreFixedArrayElement(result_elements, a->IntPtrConstant(0), first, 281 a->StoreFixedArrayElement(result_elements, a->IntPtrConstant(0), first,
281 SKIP_WRITE_BARRIER); 282 SKIP_WRITE_BARRIER);
282 283
283 a->GotoIf(a->SmiEqual(num_results, a->SmiConstant(Smi::FromInt(1))), &out); 284 a->GotoIf(a->SmiEqual(num_results, a->SmiConstant(Smi::FromInt(1))), &out);
284 285
285 // Store all remaining captures. 286 // Store all remaining captures.
286 Node* const limit = 287 Node* const limit = a->IntPtrAdd(
287 a->IntPtrAdd(a->IntPtrConstant(RegExpImpl::kFirstCapture), num_indices); 288 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), num_indices);
288 289
289 Variable var_from_cursor(a, MachineType::PointerRepresentation()); 290 Variable var_from_cursor(a, MachineType::PointerRepresentation());
290 Variable var_to_cursor(a, MachineType::PointerRepresentation()); 291 Variable var_to_cursor(a, MachineType::PointerRepresentation());
291 292
292 var_from_cursor.Bind(a->IntPtrConstant(RegExpImpl::kFirstCapture + 2)); 293 var_from_cursor.Bind(
294 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 2));
293 var_to_cursor.Bind(a->IntPtrConstant(1)); 295 var_to_cursor.Bind(a->IntPtrConstant(1));
294 296
295 Variable* vars[] = {&var_from_cursor, &var_to_cursor}; 297 Variable* vars[] = {&var_from_cursor, &var_to_cursor};
296 Label loop(a, 2, vars); 298 Label loop(a, 2, vars);
297 299
298 a->Goto(&loop); 300 a->Goto(&loop);
299 a->Bind(&loop); 301 a->Bind(&loop);
300 { 302 {
301 Node* const from_cursor = var_from_cursor.value(); 303 Node* const from_cursor = var_from_cursor.value();
302 Node* const to_cursor = var_to_cursor.value(); 304 Node* const to_cursor = var_to_cursor.value();
303 Node* const start = a->LoadFixedArrayElement(match_elements, from_cursor); 305 Node* const start = a->LoadFixedArrayElement(match_info, from_cursor);
304 306
305 Label next_iter(a); 307 Label next_iter(a);
306 a->GotoIf(a->SmiEqual(start, a->SmiConstant(Smi::FromInt(-1))), &next_iter); 308 a->GotoIf(a->SmiEqual(start, a->SmiConstant(Smi::FromInt(-1))), &next_iter);
307 309
308 Node* const from_cursor_plus1 = 310 Node* const from_cursor_plus1 =
309 a->IntPtrAdd(from_cursor, a->IntPtrConstant(1)); 311 a->IntPtrAdd(from_cursor, a->IntPtrConstant(1));
310 Node* const end = 312 Node* const end = a->LoadFixedArrayElement(match_info, from_cursor_plus1);
311 a->LoadFixedArrayElement(match_elements, from_cursor_plus1);
312 313
313 Node* const capture = a->SubString(context, string, start, end); 314 Node* const capture = a->SubString(context, string, start, end);
314 a->StoreFixedArrayElement(result_elements, to_cursor, capture); 315 a->StoreFixedArrayElement(result_elements, to_cursor, capture);
315 a->Goto(&next_iter); 316 a->Goto(&next_iter);
316 317
317 a->Bind(&next_iter); 318 a->Bind(&next_iter);
318 var_from_cursor.Bind(a->IntPtrAdd(from_cursor, a->IntPtrConstant(2))); 319 var_from_cursor.Bind(a->IntPtrAdd(from_cursor, a->IntPtrConstant(2)));
319 var_to_cursor.Bind(a->IntPtrAdd(to_cursor, a->IntPtrConstant(1))); 320 var_to_cursor.Bind(a->IntPtrAdd(to_cursor, a->IntPtrConstant(1)));
320 a->Branch(a->UintPtrLessThan(var_from_cursor.value(), limit), &loop, &out); 321 a->Branch(a->UintPtrLessThan(var_from_cursor.value(), limit), &loop, &out);
321 } 322 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 { 413 {
413 // Get last match info from the context. 414 // Get last match info from the context.
414 Node* const last_match_info = a->LoadContextElement( 415 Node* const last_match_info = a->LoadContextElement(
415 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 416 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
416 417
417 // Call the exec stub. 418 // Call the exec stub.
418 Callable exec_callable = CodeFactory::RegExpExec(isolate); 419 Callable exec_callable = CodeFactory::RegExpExec(isolate);
419 match_indices = a->CallStub(exec_callable, context, regexp, string, 420 match_indices = a->CallStub(exec_callable, context, regexp, string,
420 var_lastindex.value(), last_match_info); 421 var_lastindex.value(), last_match_info);
421 422
422 // {match_indices} is either null or the RegExpLastMatchInfo array. 423 // {match_indices} is either null or the RegExpMatchInfo array.
423 // Return early if exec failed, possibly updating last index. 424 // Return early if exec failed, possibly updating last index.
424 a->GotoUnless(a->WordEqual(match_indices, null), &successful_match); 425 a->GotoUnless(a->WordEqual(match_indices, null), &successful_match);
425 426
426 Label return_null(a); 427 Label return_null(a);
427 a->GotoUnless(should_update_last_index, &return_null); 428 a->GotoUnless(should_update_last_index, &return_null);
428 429
429 StoreLastIndex(a, context, has_initialmap, regexp, smi_zero); 430 StoreLastIndex(a, context, has_initialmap, regexp, smi_zero);
430 a->Goto(&return_null); 431 a->Goto(&return_null);
431 432
432 a->Bind(&return_null); 433 a->Bind(&return_null);
433 a->Return(null); 434 a->Return(null);
434 } 435 }
435 436
436 Label construct_result(a); 437 Label construct_result(a);
437 a->Bind(&successful_match); 438 a->Bind(&successful_match);
438 { 439 {
439 Node* const match_elements = a->LoadElements(match_indices);
440
441 a->GotoUnless(should_update_last_index, &construct_result); 440 a->GotoUnless(should_update_last_index, &construct_result);
442 441
443 // Update the new last index from {match_indices}. 442 // Update the new last index from {match_indices}.
444 Node* const new_lastindex = a->LoadFixedArrayElement( 443 Node* const new_lastindex = a->LoadFixedArrayElement(
445 match_elements, a->IntPtrConstant(RegExpImpl::kFirstCapture + 1)); 444 match_indices,
445 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1));
446 446
447 StoreLastIndex(a, context, has_initialmap, regexp, new_lastindex); 447 StoreLastIndex(a, context, has_initialmap, regexp, new_lastindex);
448 a->Goto(&construct_result); 448 a->Goto(&construct_result);
449 449
450 a->Bind(&construct_result); 450 a->Bind(&construct_result);
451 { 451 {
452 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context, 452 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context,
453 match_elements, string); 453 match_indices, string);
454 a->Return(result); 454 a->Return(result);
455 } 455 }
456 } 456 }
457 } 457 }
458 458
459 namespace { 459 namespace {
460 460
461 compiler::Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate, 461 compiler::Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate,
462 compiler::Node* context, 462 compiler::Node* context,
463 compiler::Node* value, 463 compiler::Node* value,
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 DEFINE_CAPTURE_GETTER(8) 877 DEFINE_CAPTURE_GETTER(8)
878 DEFINE_CAPTURE_GETTER(9) 878 DEFINE_CAPTURE_GETTER(9)
879 #undef DEFINE_CAPTURE_GETTER 879 #undef DEFINE_CAPTURE_GETTER
880 880
881 // The properties `input` and `$_` are aliases for each other. When this 881 // The properties `input` and `$_` are aliases for each other. When this
882 // value is set, the value it is set to is coerced to a string. 882 // value is set, the value it is set to is coerced to a string.
883 // Getter and setter for the input. 883 // Getter and setter for the input.
884 884
885 BUILTIN(RegExpInputGetter) { 885 BUILTIN(RegExpInputGetter) {
886 HandleScope scope(isolate); 886 HandleScope scope(isolate);
887 Handle<Object> obj = RegExpUtils::GetLastMatchInput( 887 Handle<Object> obj(isolate->regexp_last_match_info()->LastInput(), isolate);
888 isolate, isolate->regexp_last_match_info());
889 return obj->IsUndefined(isolate) ? isolate->heap()->empty_string() 888 return obj->IsUndefined(isolate) ? isolate->heap()->empty_string()
890 : String::cast(*obj); 889 : String::cast(*obj);
891 } 890 }
892 891
893 BUILTIN(RegExpInputSetter) { 892 BUILTIN(RegExpInputSetter) {
894 HandleScope scope(isolate); 893 HandleScope scope(isolate);
895 Handle<Object> value = args.atOrUndefined(isolate, 1); 894 Handle<Object> value = args.atOrUndefined(isolate, 1);
896 Handle<String> str; 895 Handle<String> str;
897 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, str, 896 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, str,
898 Object::ToString(isolate, value)); 897 Object::ToString(isolate, value));
899 RegExpUtils::SetLastMatchField(isolate, isolate->regexp_last_match_info(), 898 isolate->regexp_last_match_info()->SetLastInput(*str);
900 RegExpImpl::kLastInput, str);
901 return isolate->heap()->undefined_value(); 899 return isolate->heap()->undefined_value();
902 } 900 }
903 901
904 // Getters for the static properties lastMatch, lastParen, leftContext, and 902 // Getters for the static properties lastMatch, lastParen, leftContext, and
905 // rightContext of the RegExp constructor. The properties are computed based 903 // rightContext of the RegExp constructor. The properties are computed based
906 // on the captures array of the last successful match and the subject string 904 // on the captures array of the last successful match and the subject string
907 // of the last successful match. 905 // of the last successful match.
908 BUILTIN(RegExpLastMatchGetter) { 906 BUILTIN(RegExpLastMatchGetter) {
909 HandleScope scope(isolate); 907 HandleScope scope(isolate);
910 return *RegExpUtils::GenericCaptureGetter( 908 return *RegExpUtils::GenericCaptureGetter(
911 isolate, isolate->regexp_last_match_info(), 0); 909 isolate, isolate->regexp_last_match_info(), 0);
912 } 910 }
913 911
914 BUILTIN(RegExpLastParenGetter) { 912 BUILTIN(RegExpLastParenGetter) {
915 HandleScope scope(isolate); 913 HandleScope scope(isolate);
916 Handle<JSObject> match_info = isolate->regexp_last_match_info(); 914 Handle<RegExpMatchInfo> match_info = isolate->regexp_last_match_info();
917 const int length = 915 const int length = match_info->NumberOfCaptureRegisters();
918 RegExpUtils::GetLastMatchNumberOfCaptures(isolate, match_info);
919 if (length <= 2) return isolate->heap()->empty_string(); // No captures. 916 if (length <= 2) return isolate->heap()->empty_string(); // No captures.
920 917
921 DCHECK_EQ(0, length % 2); 918 DCHECK_EQ(0, length % 2);
922 const int last_capture = (length / 2) - 1; 919 const int last_capture = (length / 2) - 1;
923 920
924 // We match the SpiderMonkey behavior: return the substring defined by the 921 // We match the SpiderMonkey behavior: return the substring defined by the
925 // last pair (after the first pair) of elements of the capture array even if 922 // last pair (after the first pair) of elements of the capture array even if
926 // it is empty. 923 // it is empty.
927 return *RegExpUtils::GenericCaptureGetter(isolate, match_info, last_capture); 924 return *RegExpUtils::GenericCaptureGetter(isolate, match_info, last_capture);
928 } 925 }
929 926
930 BUILTIN(RegExpLeftContextGetter) { 927 BUILTIN(RegExpLeftContextGetter) {
931 HandleScope scope(isolate); 928 HandleScope scope(isolate);
932 Handle<JSObject> match_info = isolate->regexp_last_match_info(); 929 Handle<RegExpMatchInfo> match_info = isolate->regexp_last_match_info();
933 const int start_index = 930 const int start_index = match_info->Capture(0);
934 RegExpUtils::GetLastMatchCapture(isolate, match_info, 0); 931 Handle<String> last_subject(match_info->LastSubject());
935 Handle<String> last_subject =
936 RegExpUtils::GetLastMatchSubject(isolate, match_info);
937 return *isolate->factory()->NewSubString(last_subject, 0, start_index); 932 return *isolate->factory()->NewSubString(last_subject, 0, start_index);
938 } 933 }
939 934
940 BUILTIN(RegExpRightContextGetter) { 935 BUILTIN(RegExpRightContextGetter) {
941 HandleScope scope(isolate); 936 HandleScope scope(isolate);
942 Handle<JSObject> match_info = isolate->regexp_last_match_info(); 937 Handle<RegExpMatchInfo> match_info = isolate->regexp_last_match_info();
943 const int start_index = 938 const int start_index = match_info->Capture(1);
944 RegExpUtils::GetLastMatchCapture(isolate, match_info, 1); 939 Handle<String> last_subject(match_info->LastSubject());
945 Handle<String> last_subject =
946 RegExpUtils::GetLastMatchSubject(isolate, match_info);
947 const int len = last_subject->length(); 940 const int len = last_subject->length();
948 return *isolate->factory()->NewSubString(last_subject, start_index, len); 941 return *isolate->factory()->NewSubString(last_subject, start_index, len);
949 } 942 }
950 943
951 // ES#sec-regexp.prototype.test 944 // ES#sec-regexp.prototype.test
952 // RegExp.prototype.test ( S ) 945 // RegExp.prototype.test ( S )
953 BUILTIN(RegExpPrototypeTest) { 946 BUILTIN(RegExpPrototypeTest) {
954 HandleScope scope(isolate); 947 HandleScope scope(isolate);
955 CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.test"); 948 CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.test");
956 949
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
1131 Handle<Object> limit_obj) { 1124 Handle<Object> limit_obj) {
1132 Factory* factory = isolate->factory(); 1125 Factory* factory = isolate->factory();
1133 1126
1134 uint32_t limit; 1127 uint32_t limit;
1135 RETURN_ON_EXCEPTION(isolate, ToUint32(isolate, limit_obj, &limit), JSArray); 1128 RETURN_ON_EXCEPTION(isolate, ToUint32(isolate, limit_obj, &limit), JSArray);
1136 1129
1137 const int length = string->length(); 1130 const int length = string->length();
1138 1131
1139 if (limit == 0) return factory->NewJSArray(0); 1132 if (limit == 0) return factory->NewJSArray(0);
1140 1133
1141 Handle<JSObject> last_match_info = isolate->regexp_last_match_info(); 1134 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
1142 1135
1143 if (length == 0) { 1136 if (length == 0) {
1144 Handle<Object> match_indices; 1137 Handle<Object> match_indices;
1145 ASSIGN_RETURN_ON_EXCEPTION( 1138 ASSIGN_RETURN_ON_EXCEPTION(
1146 isolate, match_indices, 1139 isolate, match_indices,
1147 RegExpImpl::Exec(regexp, string, 0, last_match_info), JSArray); 1140 RegExpImpl::Exec(regexp, string, 0, last_match_info), JSArray);
1148 1141
1149 if (!match_indices->IsNull(isolate)) return factory->NewJSArray(0); 1142 if (!match_indices->IsNull(isolate)) return factory->NewJSArray(0);
1150 1143
1151 Handle<FixedArray> elems = factory->NewUninitializedFixedArray(1); 1144 Handle<FixedArray> elems = factory->NewUninitializedFixedArray(1);
(...skipping 13 matching lines...) Expand all
1165 if (start_index == length) { 1158 if (start_index == length) {
1166 Handle<String> substr = 1159 Handle<String> substr =
1167 factory->NewSubString(string, current_index, length); 1160 factory->NewSubString(string, current_index, length);
1168 elems = FixedArray::SetAndGrow(elems, num_elems++, substr); 1161 elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
1169 break; 1162 break;
1170 } 1163 }
1171 1164
1172 Handle<Object> match_indices_obj; 1165 Handle<Object> match_indices_obj;
1173 ASSIGN_RETURN_ON_EXCEPTION( 1166 ASSIGN_RETURN_ON_EXCEPTION(
1174 isolate, match_indices_obj, 1167 isolate, match_indices_obj,
1175 RegExpImpl::Exec(regexp, string, start_index, last_match_info), 1168 RegExpImpl::Exec(regexp, string, start_index,
1169 isolate->regexp_last_match_info()),
1176 JSArray); 1170 JSArray);
1177 1171
1178 if (match_indices_obj->IsNull(isolate)) { 1172 if (match_indices_obj->IsNull(isolate)) {
1179 Handle<String> substr = 1173 Handle<String> substr =
1180 factory->NewSubString(string, current_index, length); 1174 factory->NewSubString(string, current_index, length);
1181 elems = FixedArray::SetAndGrow(elems, num_elems++, substr); 1175 elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
1182 break; 1176 break;
1183 } 1177 }
1184 1178
1185 auto match_indices = Handle<JSReceiver>::cast(match_indices_obj); 1179 auto match_indices = Handle<RegExpMatchInfo>::cast(match_indices_obj);
1186 1180
1187 Handle<Object> start_match_obj = 1181 start_match = match_indices->Capture(0);
1188 JSReceiver::GetElement(isolate, match_indices,
1189 RegExpImpl::kFirstCapture)
1190 .ToHandleChecked();
1191 start_match = Handle<Smi>::cast(start_match_obj)->value();
1192 1182
1193 if (start_match == length) { 1183 if (start_match == length) {
1194 Handle<String> substr = 1184 Handle<String> substr =
1195 factory->NewSubString(string, current_index, length); 1185 factory->NewSubString(string, current_index, length);
1196 elems = FixedArray::SetAndGrow(elems, num_elems++, substr); 1186 elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
1197 break; 1187 break;
1198 } 1188 }
1199 1189
1200 Handle<Object> end_index_obj = 1190 const int end_index = match_indices->Capture(1);
1201 JSReceiver::GetElement(isolate, match_indices,
1202 RegExpImpl::kFirstCapture + 1)
1203 .ToHandleChecked();
1204 const int end_index = Handle<Smi>::cast(end_index_obj)->value();
1205 1191
1206 if (start_index == end_index && end_index == current_index) { 1192 if (start_index == end_index && end_index == current_index) {
1207 const bool unicode = (regexp->GetFlags() & JSRegExp::kUnicode) != 0; 1193 const bool unicode = (regexp->GetFlags() & JSRegExp::kUnicode) != 0;
1208 if (unicode && AtSurrogatePair(isolate, string, start_index)) { 1194 if (unicode && AtSurrogatePair(isolate, string, start_index)) {
1209 start_index += 2; 1195 start_index += 2;
1210 } else { 1196 } else {
1211 start_index += 1; 1197 start_index += 1;
1212 } 1198 }
1213 continue; 1199 continue;
1214 } 1200 }
1215 1201
1216 { 1202 {
1217 Handle<String> substr = 1203 Handle<String> substr =
1218 factory->NewSubString(string, current_index, start_match); 1204 factory->NewSubString(string, current_index, start_match);
1219 elems = FixedArray::SetAndGrow(elems, num_elems++, substr); 1205 elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
1220 } 1206 }
1221 1207
1222 if (num_elems == limit) break; 1208 if (num_elems == limit) break;
1223 1209
1224 Handle<Object> num_captures_obj = 1210 for (int i = 2; i < match_indices->NumberOfCaptureRegisters(); i += 2) {
1225 JSReceiver::GetElement(isolate, match_indices, 1211 const int start = match_indices->Capture(i);
1226 RegExpImpl::kLastCaptureCount) 1212 const int end = match_indices->Capture(i + 1);
1227 .ToHandleChecked();
1228 const int match_indices_len = Handle<Smi>::cast(num_captures_obj)->value() +
1229 RegExpImpl::kFirstCapture;
1230
1231 for (int i = RegExpImpl::kFirstCapture + 2; i < match_indices_len;) {
1232 Handle<Object> start_obj =
1233 JSReceiver::GetElement(isolate, match_indices, i++).ToHandleChecked();
1234 const int start = Handle<Smi>::cast(start_obj)->value();
1235
1236 Handle<Object> end_obj =
1237 JSReceiver::GetElement(isolate, match_indices, i++).ToHandleChecked();
1238 const int end = Handle<Smi>::cast(end_obj)->value();
1239 1213
1240 if (end != -1) { 1214 if (end != -1) {
1241 Handle<String> substr = factory->NewSubString(string, start, end); 1215 Handle<String> substr = factory->NewSubString(string, start, end);
1242 elems = FixedArray::SetAndGrow(elems, num_elems++, substr); 1216 elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
1243 } else { 1217 } else {
1244 elems = FixedArray::SetAndGrow(elems, num_elems++, 1218 elems = FixedArray::SetAndGrow(elems, num_elems++,
1245 factory->undefined_value()); 1219 factory->undefined_value());
1246 } 1220 }
1247 1221
1248 if (num_elems == limit) { 1222 if (num_elems == limit) {
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
1524 1498
1525 a->Bind(&if_didnotmatch); 1499 a->Bind(&if_didnotmatch);
1526 { 1500 {
1527 FastStoreLastIndex(a, context, regexp, smi_zero); 1501 FastStoreLastIndex(a, context, regexp, smi_zero);
1528 var_result.Bind(subject_string); 1502 var_result.Bind(subject_string);
1529 a->Goto(&out); 1503 a->Goto(&out);
1530 } 1504 }
1531 1505
1532 a->Bind(&if_matched); 1506 a->Bind(&if_matched);
1533 { 1507 {
1534 Node* const match_elements = a->LoadElements(match_indices);
1535 CodeStubAssembler::ParameterMode mode = 1508 CodeStubAssembler::ParameterMode mode =
1536 CodeStubAssembler::INTPTR_PARAMETERS; 1509 CodeStubAssembler::INTPTR_PARAMETERS;
1537 1510
1538 Node* const subject_start = smi_zero; 1511 Node* const subject_start = smi_zero;
1539 Node* const match_start = a->LoadFixedArrayElement( 1512 Node* const match_start = a->LoadFixedArrayElement(
1540 match_elements, a->IntPtrConstant(RegExpImpl::kFirstCapture), 0, 1513 match_indices, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex),
1541 mode); 1514 0, mode);
1542 Node* const match_end = a->LoadFixedArrayElement( 1515 Node* const match_end = a->LoadFixedArrayElement(
1543 match_elements, a->IntPtrConstant(RegExpImpl::kFirstCapture + 1), 0, 1516 match_indices,
1544 mode); 1517 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, mode);
1545 Node* const subject_end = a->LoadStringLength(subject_string); 1518 Node* const subject_end = a->LoadStringLength(subject_string);
1546 1519
1547 Label if_replaceisempty(a), if_replaceisnotempty(a); 1520 Label if_replaceisempty(a), if_replaceisnotempty(a);
1548 Node* const replace_length = a->LoadStringLength(replace_string); 1521 Node* const replace_length = a->LoadStringLength(replace_string);
1549 a->Branch(a->SmiEqual(replace_length, smi_zero), &if_replaceisempty, 1522 a->Branch(a->SmiEqual(replace_length, smi_zero), &if_replaceisempty,
1550 &if_replaceisnotempty); 1523 &if_replaceisnotempty);
1551 1524
1552 a->Bind(&if_replaceisempty); 1525 a->Bind(&if_replaceisempty);
1553 { 1526 {
1554 // TODO(jgruber): We could skip many of the checks that using SubString 1527 // TODO(jgruber): We could skip many of the checks that using SubString
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1648 } 1621 }
1649 1622
1650 a->Bind(&runtime); 1623 a->Bind(&runtime);
1651 { 1624 {
1652 Node* const result = a->CallRuntime(Runtime::kRegExpReplace, context, 1625 Node* const result = a->CallRuntime(Runtime::kRegExpReplace, context,
1653 receiver, string, replace_value); 1626 receiver, string, replace_value);
1654 a->Return(result); 1627 a->Return(result);
1655 } 1628 }
1656 } 1629 }
1657 1630
1658 namespace {
1659
1660 // TODO(jgruber): Replace this with a FixedArray.
1661 compiler::Node* GetInternalMatchInfo(CodeStubAssembler* a,
1662 compiler::Node* context) {
1663 typedef compiler::Node Node;
1664
1665 const ElementsKind elements_kind = FAST_ELEMENTS;
1666 Node* const native_context = a->LoadNativeContext(context);
1667 Node* const array_map =
1668 a->LoadJSArrayElementsMap(elements_kind, native_context);
1669 Node* const capacity = a->IntPtrConstant(RegExpImpl::kLastMatchOverhead + 2);
1670 Node* const allocation_site = nullptr;
1671
1672 Node* const smi_zero = a->SmiConstant(Smi::kZero);
1673
1674 return a->AllocateJSArray(elements_kind, array_map, capacity, smi_zero,
1675 allocation_site,
1676 CodeStubAssembler::INTPTR_PARAMETERS);
1677 }
1678
1679 } // namespace
1680
1681 // Simple string matching functionality for internal use which does not modify 1631 // Simple string matching functionality for internal use which does not modify
1682 // the last match info. 1632 // the last match info.
1683 void Builtins::Generate_RegExpInternalMatch(CodeStubAssembler* a) { 1633 void Builtins::Generate_RegExpInternalMatch(CodeStubAssembler* a) {
1684 typedef CodeStubAssembler::Label Label; 1634 typedef CodeStubAssembler::Label Label;
1685 typedef compiler::Node Node; 1635 typedef compiler::Node Node;
1686 1636
1687 Isolate* const isolate = a->isolate(); 1637 Isolate* const isolate = a->isolate();
1688 1638
1689 Node* const regexp = a->Parameter(1); 1639 Node* const regexp = a->Parameter(1);
1690 Node* const string = a->Parameter(2); 1640 Node* const string = a->Parameter(2);
1691 Node* const context = a->Parameter(5); 1641 Node* const context = a->Parameter(5);
1692 1642
1693 Node* const null = a->NullConstant(); 1643 Node* const null = a->NullConstant();
1694 Node* const smi_zero = a->SmiConstant(Smi::FromInt(0)); 1644 Node* const smi_zero = a->SmiConstant(Smi::FromInt(0));
1695 Node* const internal_match_info = GetInternalMatchInfo(a, context); 1645
1646 Node* const native_context = a->LoadNativeContext(context);
1647 Node* const internal_match_info = a->LoadContextElement(
1648 native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX);
1696 1649
1697 Callable exec_callable = CodeFactory::RegExpExec(isolate); 1650 Callable exec_callable = CodeFactory::RegExpExec(isolate);
1698 Node* const match_indices = a->CallStub( 1651 Node* const match_indices = a->CallStub(
1699 exec_callable, context, regexp, string, smi_zero, internal_match_info); 1652 exec_callable, context, regexp, string, smi_zero, internal_match_info);
1700 1653
1701 Label if_matched(a), if_didnotmatch(a); 1654 Label if_matched(a), if_didnotmatch(a);
1702 a->Branch(a->WordEqual(match_indices, null), &if_didnotmatch, &if_matched); 1655 a->Branch(a->WordEqual(match_indices, null), &if_didnotmatch, &if_matched);
1703 1656
1704 a->Bind(&if_didnotmatch); 1657 a->Bind(&if_didnotmatch);
1705 a->Return(null); 1658 a->Return(null);
1706 1659
1707 a->Bind(&if_matched); 1660 a->Bind(&if_matched);
1708 { 1661 {
1709 Node* const match_elements = a->LoadElements(match_indices);
1710 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context, 1662 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context,
1711 match_elements, string); 1663 match_indices, string);
1712 a->Return(result); 1664 a->Return(result);
1713 } 1665 }
1714 } 1666 }
1715 1667
1716 } // namespace internal 1668 } // namespace internal
1717 } // namespace v8 1669 } // namespace v8
OLDNEW
« no previous file with comments | « src/bootstrapper.cc ('k') | src/contexts.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698