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

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

Issue 2527963002: [regexp] Migrate @@match to TurboFan (Closed)
Patch Set: Remove unused variable Created 4 years 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/builtins/builtins.h ('k') | no next file » | 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 531 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 Node* const proto_map = a->LoadMap(a->LoadMapPrototype(map)); 542 Node* const proto_map = a->LoadMap(a->LoadMapPrototype(map));
543 Node* const proto_has_initialmap = 543 Node* const proto_has_initialmap =
544 a->WordEqual(proto_map, initial_proto_initial_map); 544 a->WordEqual(proto_map, initial_proto_initial_map);
545 545
546 // TODO(ishell): Update this check once map changes for constant field 546 // TODO(ishell): Update this check once map changes for constant field
547 // tracking are landing. 547 // tracking are landing.
548 548
549 a->Branch(proto_has_initialmap, if_isunmodified, if_ismodified); 549 a->Branch(proto_has_initialmap, if_isunmodified, if_ismodified);
550 } 550 }
551 551
552 void BranchIfFastRegExpResult(CodeStubAssembler* a, Node* context, Node* map,
553 CLabel* if_isunmodified, CLabel* if_ismodified) {
554 Node* const native_context = a->LoadNativeContext(context);
555 Node* const initial_regexp_result_map =
556 a->LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX);
557
558 a->Branch(a->WordEqual(map, initial_regexp_result_map), if_isunmodified,
559 if_ismodified);
560 }
561
552 } // namespace 562 } // namespace
553 563
554 void Builtins::Generate_RegExpPrototypeFlagsGetter(CodeAssemblerState* state) { 564 void Builtins::Generate_RegExpPrototypeFlagsGetter(CodeAssemblerState* state) {
555 CodeStubAssembler a(state); 565 CodeStubAssembler a(state);
556 566
557 Node* const receiver = a.Parameter(0); 567 Node* const receiver = a.Parameter(0);
558 Node* const context = a.Parameter(3); 568 Node* const context = a.Parameter(3);
559 569
560 Isolate* isolate = a.isolate(); 570 Isolate* isolate = a.isolate();
561 Node* const int_zero = a.IntPtrConstant(0); 571 Node* const int_zero = a.IntPtrConstant(0);
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 Node* FastFlagGetter(CodeStubAssembler* a, Node* const regexp, 766 Node* FastFlagGetter(CodeStubAssembler* a, Node* const regexp,
757 JSRegExp::Flag flag) { 767 JSRegExp::Flag flag) {
758 Node* const smi_zero = a->SmiConstant(Smi::kZero); 768 Node* const smi_zero = a->SmiConstant(Smi::kZero);
759 Node* const flags = a->LoadObjectField(regexp, JSRegExp::kFlagsOffset); 769 Node* const flags = a->LoadObjectField(regexp, JSRegExp::kFlagsOffset);
760 Node* const mask = a->SmiConstant(Smi::FromInt(flag)); 770 Node* const mask = a->SmiConstant(Smi::FromInt(flag));
761 Node* const is_flag_set = a->WordNotEqual(a->WordAnd(flags, mask), smi_zero); 771 Node* const is_flag_set = a->WordNotEqual(a->WordAnd(flags, mask), smi_zero);
762 772
763 return is_flag_set; 773 return is_flag_set;
764 } 774 }
765 775
776 // Load through the GetProperty stub.
777 compiler::Node* SlowFlagGetter(CodeStubAssembler* a,
778 compiler::Node* const context,
779 compiler::Node* const regexp,
780 JSRegExp::Flag flag) {
781 Factory* factory = a->isolate()->factory();
782
783 CLabel out(a);
784 CVariable var_result(a, MachineType::PointerRepresentation());
785
786 Node* name;
787
788 switch (flag) {
789 case JSRegExp::kGlobal:
790 name = a->HeapConstant(factory->global_string());
791 break;
792 case JSRegExp::kIgnoreCase:
793 name = a->HeapConstant(factory->ignoreCase_string());
794 break;
795 case JSRegExp::kMultiline:
796 name = a->HeapConstant(factory->multiline_string());
797 break;
798 case JSRegExp::kSticky:
799 name = a->HeapConstant(factory->sticky_string());
800 break;
801 case JSRegExp::kUnicode:
802 name = a->HeapConstant(factory->unicode_string());
803 break;
804 default:
805 UNREACHABLE();
806 }
807
808 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
809 Node* const value = a->CallStub(getproperty_callable, context, regexp, name);
810
811 CLabel if_true(a), if_false(a);
812 a->BranchIfToBooleanIsTrue(value, &if_true, &if_false);
813
814 a->Bind(&if_true);
815 {
816 var_result.Bind(a->IntPtrConstant(1));
817 a->Goto(&out);
818 }
819
820 a->Bind(&if_false);
821 {
822 var_result.Bind(a->IntPtrConstant(0));
823 a->Goto(&out);
824 }
825
826 a->Bind(&out);
827 return var_result.value();
828 }
829
830 compiler::Node* FlagGetter(CodeStubAssembler* a, compiler::Node* const context,
831 compiler::Node* const regexp, JSRegExp::Flag flag,
832 bool is_fastpath) {
833 return is_fastpath ? FastFlagGetter(a, regexp, flag)
834 : SlowFlagGetter(a, context, regexp, flag);
835 }
836
766 void Generate_FlagGetter(CodeStubAssembler* a, JSRegExp::Flag flag, 837 void Generate_FlagGetter(CodeStubAssembler* a, JSRegExp::Flag flag,
767 v8::Isolate::UseCounterFeature counter, 838 v8::Isolate::UseCounterFeature counter,
768 const char* method_name) { 839 const char* method_name) {
769 Node* const receiver = a->Parameter(0); 840 Node* const receiver = a->Parameter(0);
770 Node* const context = a->Parameter(3); 841 Node* const context = a->Parameter(3);
771 842
772 Isolate* isolate = a->isolate(); 843 Isolate* isolate = a->isolate();
773 844
774 // Check whether we have an unmodified regexp instance. 845 // Check whether we have an unmodified regexp instance.
775 CLabel if_isunmodifiedjsregexp(a), 846 CLabel if_isunmodifiedjsregexp(a),
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
1042 1113
1043 // Call exec. 1114 // Call exec.
1044 Node* const match_indices = RegExpExec(&a, context, receiver, string); 1115 Node* const match_indices = RegExpExec(&a, context, receiver, string);
1045 1116
1046 // Return true iff exec matched successfully. 1117 // Return true iff exec matched successfully.
1047 Node* const result = a.Select(a.WordEqual(match_indices, a.NullConstant()), 1118 Node* const result = a.Select(a.WordEqual(match_indices, a.NullConstant()),
1048 a.FalseConstant(), a.TrueConstant()); 1119 a.FalseConstant(), a.TrueConstant());
1049 a.Return(result); 1120 a.Return(result);
1050 } 1121 }
1051 1122
1123 namespace {
1124
1125 Node* AdvanceStringIndex(CodeStubAssembler* a, Node* const string,
1126 Node* const index, Node* const is_unicode) {
1127 CVariable var_result(a, MachineRepresentation::kTagged);
1128
1129 // Default to last_index + 1.
1130 Node* const index_plus_one = a->SmiAdd(index, a->SmiConstant(1));
1131 var_result.Bind(index_plus_one);
1132
1133 CLabel if_isunicode(a), out(a);
1134 a->Branch(is_unicode, &if_isunicode, &out);
1135
1136 a->Bind(&if_isunicode);
1137 {
1138 Node* const string_length = a->LoadStringLength(string);
1139 a->GotoUnless(a->SmiLessThan(index_plus_one, string_length), &out);
1140
1141 Node* const lead = a->StringCharCodeAt(string, index);
1142 a->GotoUnless(a->Word32Equal(a->Word32And(lead, a->Int32Constant(0xFC00)),
1143 a->Int32Constant(0xD800)),
1144 &out);
1145
1146 Node* const trail = a->StringCharCodeAt(string, index_plus_one);
1147 a->GotoUnless(a->Word32Equal(a->Word32And(trail, a->Int32Constant(0xFC00)),
1148 a->Int32Constant(0xDC00)),
1149 &out);
1150
1151 // At a surrogate pair, return index + 2.
1152 Node* const index_plus_two = a->SmiAdd(index, a->SmiConstant(2));
1153 var_result.Bind(index_plus_two);
1154
1155 a->Goto(&out);
1156 }
1157
1158 a->Bind(&out);
1159 return var_result.value();
1160 }
1161
1162 // Utility class implementing a growable fixed array through CSA.
1163 class GrowableFixedArray {
1164 public:
1165 explicit GrowableFixedArray(CodeStubAssembler* a)
1166 : assembler_(a),
1167 var_array_(a, MachineRepresentation::kTagged),
1168 var_length_(a, MachineType::PointerRepresentation()),
1169 var_capacity_(a, MachineType::PointerRepresentation()) {
1170 Initialize();
1171 }
1172
1173 Node* length() const { return var_length_.value(); }
1174
1175 CVariable* var_array() { return &var_array_; }
1176 CVariable* var_length() { return &var_length_; }
1177 CVariable* var_capacity() { return &var_capacity_; }
1178
1179 void Push(Node* const value) {
1180 CodeStubAssembler* a = assembler_;
1181
1182 const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER;
1183 const CodeStubAssembler::ParameterMode mode =
1184 CodeStubAssembler::INTPTR_PARAMETERS;
1185
1186 Node* const length = var_length_.value();
1187 Node* const capacity = var_capacity_.value();
1188
1189 CLabel grow(a), store(a);
1190 a->Branch(a->IntPtrEqual(capacity, length), &grow, &store);
1191
1192 a->Bind(&grow);
1193 {
1194 Node* const new_capacity = NewCapacity(a, capacity);
1195 Node* const new_array = GrowFixedArray(capacity, new_capacity, mode);
1196
1197 var_capacity_.Bind(new_capacity);
1198 var_array_.Bind(new_array);
1199 a->Goto(&store);
1200 }
1201
1202 a->Bind(&store);
1203 {
1204 Node* const array = var_array_.value();
1205 a->StoreFixedArrayElement(array, length, value, barrier_mode, 0, mode);
1206
1207 Node* const new_length = a->IntPtrAdd(length, a->IntPtrConstant(1));
1208 var_length_.Bind(new_length);
1209 }
1210 }
1211
1212 Node* ToJSArray(Node* const context) {
1213 CodeStubAssembler* a = assembler_;
1214
1215 const ElementsKind kind = FAST_ELEMENTS;
1216
1217 Node* const native_context = a->LoadNativeContext(context);
1218 Node* const array_map = a->LoadJSArrayElementsMap(kind, native_context);
1219
1220 Node* const result_length = a->SmiTag(length());
1221 Node* const result = a->AllocateUninitializedJSArrayWithoutElements(
1222 kind, array_map, result_length, nullptr);
1223
1224 // Note: We do not currently shrink the fixed array.
1225
1226 a->StoreObjectField(result, JSObject::kElementsOffset, var_array_.value());
1227
1228 return result;
1229 }
1230
1231 private:
1232 void Initialize() {
1233 CodeStubAssembler* a = assembler_;
1234
1235 const ElementsKind kind = FAST_ELEMENTS;
1236 const CodeStubAssembler::ParameterMode mode =
1237 CodeStubAssembler::INTPTR_PARAMETERS;
1238
1239 static const int kInitialArraySize = 8;
1240 Node* const capacity = a->IntPtrConstant(kInitialArraySize);
1241 Node* const array = a->AllocateFixedArray(kind, capacity, mode);
1242
1243 a->FillFixedArrayWithValue(kind, array, a->IntPtrConstant(0), capacity,
1244 Heap::kTheHoleValueRootIndex, mode);
1245
1246 var_array_.Bind(array);
1247 var_capacity_.Bind(capacity);
1248 var_length_.Bind(a->IntPtrConstant(0));
1249 }
1250
1251 Node* NewCapacity(CodeStubAssembler* a, Node* const current_capacity) {
1252 CSA_ASSERT(a, a->IntPtrGreaterThan(current_capacity, a->IntPtrConstant(0)));
1253
1254 // Growth rate is analog to JSObject::NewElementsCapacity:
1255 // new_capacity = (current_capacity + (current_capacity >> 1)) + 16.
1256
1257 Node* const new_capacity = a->IntPtrAdd(
1258 a->IntPtrAdd(current_capacity, a->WordShr(current_capacity, 1)),
1259 a->IntPtrConstant(16));
1260
1261 return new_capacity;
1262 }
1263
1264 Node* GrowFixedArray(Node* const current_capacity, Node* const new_capacity,
1265 CodeStubAssembler::ParameterMode mode) {
1266 DCHECK(mode == CodeStubAssembler::INTPTR_PARAMETERS);
1267
1268 CodeStubAssembler* a = assembler_;
1269
1270 CSA_ASSERT(a, a->IntPtrGreaterThan(current_capacity, a->IntPtrConstant(0)));
1271 CSA_ASSERT(a, a->IntPtrGreaterThan(new_capacity, current_capacity));
1272
1273 const ElementsKind kind = FAST_ELEMENTS;
1274 const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER;
1275
1276 Node* const from_array = var_array_.value();
1277 Node* const to_array = a->AllocateFixedArray(kind, new_capacity, mode);
1278 a->CopyFixedArrayElements(kind, from_array, kind, to_array,
1279 current_capacity, new_capacity, barrier_mode,
1280 mode);
1281
1282 return to_array;
1283 }
1284
1285 private:
1286 CodeStubAssembler* const assembler_;
1287 CVariable var_array_;
1288 CVariable var_length_;
1289 CVariable var_capacity_;
1290 };
1291
1292 void Generate_RegExpPrototypeMatchBody(CodeStubAssembler* a,
1293 Node* const receiver, Node* const string,
1294 Node* const context,
1295 const bool is_fastpath) {
1296 Isolate* const isolate = a->isolate();
1297
1298 Node* const null = a->NullConstant();
1299 Node* const int_zero = a->IntPtrConstant(0);
1300 Node* const smi_zero = a->SmiConstant(Smi::kZero);
1301
1302 Node* const regexp = receiver;
1303 Node* const is_global =
1304 FlagGetter(a, context, regexp, JSRegExp::kGlobal, is_fastpath);
1305
1306 CLabel if_isglobal(a), if_isnotglobal(a);
1307 a->Branch(is_global, &if_isglobal, &if_isnotglobal);
1308
1309 a->Bind(&if_isnotglobal);
1310 {
1311 Node* const result =
1312 is_fastpath ? RegExpPrototypeExecInternal(a, context, regexp, string)
1313 : RegExpExec(a, context, regexp, string);
1314 a->Return(result);
1315 }
1316
1317 a->Bind(&if_isglobal);
1318 {
1319 Node* const is_unicode =
1320 FlagGetter(a, context, regexp, JSRegExp::kUnicode, is_fastpath);
1321
1322 if (is_fastpath) {
1323 FastStoreLastIndex(a, context, regexp, smi_zero);
1324 } else {
1325 SlowStoreLastIndex(a, context, regexp, smi_zero);
1326 }
1327
1328 // Allocate an array to store the resulting match strings.
1329
1330 GrowableFixedArray array(a);
1331
1332 // Loop preparations. Within the loop, collect results from RegExpExec
1333 // and store match strings in the array.
1334
1335 CVariable* vars[] = {array.var_array(), array.var_length(),
1336 array.var_capacity()};
1337 CLabel loop(a, 3, vars), out(a);
1338 a->Goto(&loop);
1339
1340 a->Bind(&loop);
1341 {
1342 Node* const result =
1343 is_fastpath ? RegExpPrototypeExecInternal(a, context, regexp, string)
1344 : RegExpExec(a, context, regexp, string);
1345
1346 CLabel if_didmatch(a), if_didnotmatch(a);
1347 a->Branch(a->WordEqual(result, null), &if_didnotmatch, &if_didmatch);
1348
1349 a->Bind(&if_didnotmatch);
1350 {
1351 // Return null if there were no matches, otherwise just exit the loop.
1352 a->GotoUnless(a->IntPtrEqual(array.length(), int_zero), &out);
1353 a->Return(null);
1354 }
1355
1356 a->Bind(&if_didmatch);
1357 {
1358 Node* match = nullptr;
1359 if (is_fastpath) {
1360 // TODO(jgruber): We could optimize further here and in other
1361 // methods (e.g. @@search) by bypassing RegExp result construction.
1362 Node* const result_fixed_array = a->LoadElements(result);
1363 const CodeStubAssembler::ParameterMode mode =
1364 CodeStubAssembler::INTPTR_PARAMETERS;
1365 match =
1366 a->LoadFixedArrayElement(result_fixed_array, int_zero, 0, mode);
1367
1368 // The match is guaranteed to be a string on the fast path.
1369 CSA_ASSERT(a, a->IsStringInstanceType(a->LoadInstanceType(match)));
1370 } else {
1371 DCHECK(!is_fastpath);
1372
1373 CVariable var_match(a, MachineRepresentation::kTagged);
1374 CLabel fast_result(a), slow_result(a), match_loaded(a);
1375 BranchIfFastRegExpResult(a, context, a->LoadMap(result), &fast_result,
1376 &slow_result);
1377
1378 a->Bind(&fast_result);
1379 {
1380 // TODO(jgruber): We could optimize further here and in other
1381 // methods (e.g. @@search) by bypassing RegExp result construction.
1382 Node* const result_fixed_array = a->LoadElements(result);
1383 const CodeStubAssembler::ParameterMode mode =
1384 CodeStubAssembler::INTPTR_PARAMETERS;
1385 Node* const match =
1386 a->LoadFixedArrayElement(result_fixed_array, int_zero, 0, mode);
1387
1388 // The match is guaranteed to be a string on the fast path.
1389 CSA_ASSERT(a, a->IsStringInstanceType(a->LoadInstanceType(match)));
1390
1391 var_match.Bind(match);
1392 a->Goto(&match_loaded);
1393 }
1394
1395 a->Bind(&slow_result);
1396 {
1397 // TODO(ishell): Use GetElement stub once it's available.
1398 Node* const name = smi_zero;
1399 Callable getproperty_callable = CodeFactory::GetProperty(isolate);
1400 Node* const match =
1401 a->CallStub(getproperty_callable, context, result, name);
1402
1403 var_match.Bind(match);
1404 a->Goto(&match_loaded);
1405 }
1406
1407 a->Bind(&match_loaded);
1408 match = a->ToString(context, var_match.value());
1409 }
1410 DCHECK(match != nullptr);
1411
1412 // Store the match, growing the fixed array if needed.
1413
1414 array.Push(match);
1415
1416 // Advance last index if the match is the empty string.
1417
1418 Node* const match_length = a->LoadStringLength(match);
1419 a->GotoUnless(a->SmiEqual(match_length, smi_zero), &loop);
1420
1421 Node* last_index = is_fastpath ? FastLoadLastIndex(a, context, regexp)
1422 : SlowLoadLastIndex(a, context, regexp);
1423
1424 Callable tolength_callable = CodeFactory::ToLength(isolate);
1425 last_index = a->CallStub(tolength_callable, context, last_index);
1426
1427 Node* const new_last_index =
1428 AdvanceStringIndex(a, string, last_index, is_unicode);
1429
1430 if (is_fastpath) {
1431 FastStoreLastIndex(a, context, regexp, new_last_index);
1432 } else {
1433 SlowStoreLastIndex(a, context, regexp, new_last_index);
1434 }
1435
1436 a->Goto(&loop);
1437 }
1438 }
1439
1440 a->Bind(&out);
1441 {
1442 // Wrap the match in a JSArray.
1443
1444 Node* const result = array.ToJSArray(context);
1445 a->Return(result);
1446 }
1447 }
1448 }
1449
1450 } // namespace
1451
1052 // ES#sec-regexp.prototype-@@match 1452 // ES#sec-regexp.prototype-@@match
1053 // RegExp.prototype [ @@match ] ( string ) 1453 // RegExp.prototype [ @@match ] ( string )
1054 BUILTIN(RegExpPrototypeMatch) { 1454 void Builtins::Generate_RegExpPrototypeMatch(CodeAssemblerState* state) {
1055 HandleScope scope(isolate); 1455 CodeStubAssembler a(state);
1056 CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.@@match"); 1456
1057 1457 Node* const maybe_receiver = a.Parameter(0);
1058 Handle<Object> string_obj = args.atOrUndefined(isolate, 1); 1458 Node* const maybe_string = a.Parameter(1);
1059 1459 Node* const context = a.Parameter(4);
1060 Handle<String> string; 1460
1061 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string, 1461 // Ensure {maybe_receiver} is a JSReceiver.
1062 Object::ToString(isolate, string_obj)); 1462 Node* const map = ThrowIfNotJSReceiver(
1063 1463 &a, a.isolate(), context, maybe_receiver,
1064 Handle<Object> global_obj; 1464 MessageTemplate::kIncompatibleMethodReceiver, "RegExp.prototype.@@match");
1065 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1465 Node* const receiver = maybe_receiver;
1066 isolate, global_obj, 1466
1067 JSReceiver::GetProperty(recv, isolate->factory()->global_string())); 1467 // Convert {maybe_string} to a String.
1068 const bool global = global_obj->BooleanValue(); 1468 Node* const string = a.ToString(context, maybe_string);
1069 1469
1070 if (!global) { 1470 CLabel fast_path(&a), slow_path(&a);
1071 RETURN_RESULT_OR_FAILURE( 1471 BranchIfFastPath(&a, context, map, &fast_path, &slow_path);
1072 isolate, 1472
1073 RegExpUtils::RegExpExec(isolate, recv, string, 1473 a.Bind(&fast_path);
1074 isolate->factory()->undefined_value())); 1474 Generate_RegExpPrototypeMatchBody(&a, receiver, string, context, true);
1075 } 1475
1076 1476 a.Bind(&slow_path);
1077 Handle<Object> unicode_obj; 1477 Generate_RegExpPrototypeMatchBody(&a, receiver, string, context, false);
1078 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1079 isolate, unicode_obj,
1080 JSReceiver::GetProperty(recv, isolate->factory()->unicode_string()));
1081 const bool unicode = unicode_obj->BooleanValue();
1082
1083 RETURN_FAILURE_ON_EXCEPTION(isolate,
1084 RegExpUtils::SetLastIndex(isolate, recv, 0));
1085
1086 static const int kInitialArraySize = 8;
1087 Handle<FixedArray> elems =
1088 isolate->factory()->NewFixedArrayWithHoles(kInitialArraySize);
1089
1090 int n = 0;
1091 for (;; n++) {
1092 Handle<Object> result;
1093 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1094 isolate, result,
1095 RegExpUtils::RegExpExec(isolate, recv, string,
1096 isolate->factory()->undefined_value()));
1097
1098 if (result->IsNull(isolate)) {
1099 if (n == 0) return isolate->heap()->null_value();
1100 break;
1101 }
1102
1103 Handle<Object> match_obj;
1104 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, match_obj,
1105 Object::GetElement(isolate, result, 0));
1106
1107 Handle<String> match;
1108 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, match,
1109 Object::ToString(isolate, match_obj));
1110
1111 elems = FixedArray::SetAndGrow(elems, n, match);
1112
1113 if (match->length() == 0) {
1114 RETURN_FAILURE_ON_EXCEPTION(isolate, RegExpUtils::SetAdvancedStringIndex(
1115 isolate, recv, string, unicode));
1116 }
1117 }
1118
1119 elems->Shrink(n);
1120 return *isolate->factory()->NewJSArrayWithElements(elems);
1121 } 1478 }
1122 1479
1123 namespace { 1480 namespace {
1124 1481
1125 void Generate_RegExpPrototypeSearchBody(CodeStubAssembler* a, 1482 void Generate_RegExpPrototypeSearchBody(CodeStubAssembler* a,
1126 Node* const receiver, 1483 Node* const receiver,
1127 Node* const string, Node* const context, 1484 Node* const string, Node* const context,
1128 bool is_fastpath) { 1485 bool is_fastpath) {
1129 Isolate* const isolate = a->isolate(); 1486 Isolate* const isolate = a->isolate();
1130 1487
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1169 1526
1170 // Return -1 if no match was found. 1527 // Return -1 if no match was found.
1171 { 1528 {
1172 CLabel next(a); 1529 CLabel next(a);
1173 a->GotoUnless(a->WordEqual(match_indices, a->NullConstant()), &next); 1530 a->GotoUnless(a->WordEqual(match_indices, a->NullConstant()), &next);
1174 a->Return(a->SmiConstant(-1)); 1531 a->Return(a->SmiConstant(-1));
1175 a->Bind(&next); 1532 a->Bind(&next);
1176 } 1533 }
1177 1534
1178 // Return the index of the match. 1535 // Return the index of the match.
1179 { 1536 if (is_fastpath) {
1537 Node* const index = a->LoadObjectField(
1538 match_indices, JSRegExpResult::kIndexOffset, MachineType::AnyTagged());
1539 a->Return(index);
1540 } else {
1541 DCHECK(!is_fastpath);
1542
1180 CLabel fast_result(a), slow_result(a, CLabel::kDeferred); 1543 CLabel fast_result(a), slow_result(a, CLabel::kDeferred);
1181 1544 BranchIfFastRegExpResult(a, context, a->LoadMap(match_indices),
1182 Node* const native_context = a->LoadNativeContext(context); 1545 &fast_result, &slow_result);
1183 Node* const initial_regexp_result_map =
1184 a->LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX);
1185 Node* const match_indices_map = a->LoadMap(match_indices);
1186
1187 a->Branch(a->WordEqual(match_indices_map, initial_regexp_result_map),
1188 &fast_result, &slow_result);
1189 1546
1190 a->Bind(&fast_result); 1547 a->Bind(&fast_result);
1191 { 1548 {
1192 Node* const index = 1549 Node* const index =
1193 a->LoadObjectField(match_indices, JSRegExpResult::kIndexOffset, 1550 a->LoadObjectField(match_indices, JSRegExpResult::kIndexOffset,
1194 MachineType::AnyTagged()); 1551 MachineType::AnyTagged());
1195 a->Return(index); 1552 a->Return(index);
1196 } 1553 }
1197 1554
1198 a->Bind(&slow_result); 1555 a->Bind(&slow_result);
(...skipping 841 matching lines...) Expand 10 before | Expand all | Expand 10 after
2040 a.Bind(&if_matched); 2397 a.Bind(&if_matched);
2041 { 2398 {
2042 Node* result = ConstructNewResultFromMatchInfo(isolate, &a, context, 2399 Node* result = ConstructNewResultFromMatchInfo(isolate, &a, context,
2043 match_indices, string); 2400 match_indices, string);
2044 a.Return(result); 2401 a.Return(result);
2045 } 2402 }
2046 } 2403 }
2047 2404
2048 } // namespace internal 2405 } // namespace internal
2049 } // namespace v8 2406 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698