Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 219 | 219 |
| 220 void StoreLastIndex(CodeStubAssembler* a, Node* context, Node* regexp, | 220 void StoreLastIndex(CodeStubAssembler* a, Node* context, Node* regexp, |
| 221 Node* value, bool is_fastpath) { | 221 Node* value, bool is_fastpath) { |
| 222 if (is_fastpath) { | 222 if (is_fastpath) { |
| 223 FastStoreLastIndex(a, regexp, value); | 223 FastStoreLastIndex(a, regexp, value); |
| 224 } else { | 224 } else { |
| 225 SlowStoreLastIndex(a, context, regexp, value); | 225 SlowStoreLastIndex(a, context, regexp, value); |
| 226 } | 226 } |
| 227 } | 227 } |
| 228 | 228 |
| 229 Node* LoadMatchInfoField(CodeStubAssembler* a, Node* const match_info, | |
|
Igor Sheludko
2016/11/30 23:17:22
I think you should add CSA::LoadFieldArrayElement(
jgruber
2016/12/01 09:48:27
Will do this in a follow-up CL since it also affec
| |
| 230 const int index) { | |
| 231 const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; | |
| 232 Node* const result = | |
| 233 a->LoadFixedArrayElement(match_info, a->IntPtrConstant(index), 0, mode); | |
| 234 return result; | |
| 235 } | |
| 236 | |
| 229 Node* ConstructNewResultFromMatchInfo(Isolate* isolate, CodeStubAssembler* a, | 237 Node* ConstructNewResultFromMatchInfo(Isolate* isolate, CodeStubAssembler* a, |
| 230 Node* context, Node* match_info, | 238 Node* context, Node* match_info, |
| 231 Node* string) { | 239 Node* string) { |
| 232 CLabel out(a); | 240 CLabel out(a); |
| 233 | 241 |
| 234 ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; | 242 ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; |
| 235 Node* const num_indices = a->SmiUntag(a->LoadFixedArrayElement( | 243 Node* const num_indices = a->SmiUntag(a->LoadFixedArrayElement( |
|
Igor Sheludko
2016/11/30 23:17:22
LoadMatchInfoField (or new LoadFixedArrayElement)
jgruber
2016/12/01 09:48:27
Done.
| |
| 236 match_info, a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, | 244 match_info, a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, |
| 237 mode)); | 245 mode)); |
| 238 Node* const num_results = a->SmiTag(a->WordShr(num_indices, 1)); | 246 Node* const num_results = a->SmiTag(a->WordShr(num_indices, 1)); |
| 239 Node* const start = a->LoadFixedArrayElement( | 247 Node* const start = a->LoadFixedArrayElement( |
| 240 match_info, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), 0, | 248 match_info, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), 0, |
| 241 mode); | 249 mode); |
| 242 Node* const end = a->LoadFixedArrayElement( | 250 Node* const end = a->LoadFixedArrayElement( |
| 243 match_info, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, | 251 match_info, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, |
| 244 mode); | 252 mode); |
| 245 | 253 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 | 411 |
| 404 StoreLastIndex(a, context, regexp, smi_zero, is_fastpath); | 412 StoreLastIndex(a, context, regexp, smi_zero, is_fastpath); |
| 405 a->Goto(if_didnotmatch); | 413 a->Goto(if_didnotmatch); |
| 406 } | 414 } |
| 407 | 415 |
| 408 a->Bind(&successful_match); | 416 a->Bind(&successful_match); |
| 409 { | 417 { |
| 410 a->GotoUnless(should_update_last_index, &out); | 418 a->GotoUnless(should_update_last_index, &out); |
| 411 | 419 |
| 412 // Update the new last index from {match_indices}. | 420 // Update the new last index from {match_indices}. |
| 413 Node* const new_lastindex = a->LoadFixedArrayElement( | 421 Node* const new_lastindex = a->LoadFixedArrayElement( |
|
Igor Sheludko
2016/11/30 23:17:22
Same here.
jgruber
2016/12/01 09:48:27
Done and at all other places as well.
| |
| 414 match_indices, | 422 match_indices, |
| 415 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1)); | 423 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1)); |
| 416 | 424 |
| 417 StoreLastIndex(a, context, regexp, new_lastindex, is_fastpath); | 425 StoreLastIndex(a, context, regexp, new_lastindex, is_fastpath); |
| 418 a->Goto(&out); | 426 a->Goto(&out); |
| 419 } | 427 } |
| 420 | 428 |
| 421 a->Bind(&out); | 429 a->Bind(&out); |
| 422 return var_result.value(); | 430 return var_result.value(); |
| 423 } | 431 } |
| (...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1123 void Builtins::Generate_RegExpPrototypeTest(CodeAssemblerState* state) { | 1131 void Builtins::Generate_RegExpPrototypeTest(CodeAssemblerState* state) { |
| 1124 CodeStubAssembler a(state); | 1132 CodeStubAssembler a(state); |
| 1125 | 1133 |
| 1126 Isolate* const isolate = a.isolate(); | 1134 Isolate* const isolate = a.isolate(); |
| 1127 | 1135 |
| 1128 Node* const maybe_receiver = a.Parameter(0); | 1136 Node* const maybe_receiver = a.Parameter(0); |
| 1129 Node* const maybe_string = a.Parameter(1); | 1137 Node* const maybe_string = a.Parameter(1); |
| 1130 Node* const context = a.Parameter(4); | 1138 Node* const context = a.Parameter(4); |
| 1131 | 1139 |
| 1132 // Ensure {maybe_receiver} is a JSReceiver. | 1140 // Ensure {maybe_receiver} is a JSReceiver. |
| 1133 ThrowIfNotJSReceiver(&a, isolate, context, maybe_receiver, | 1141 Node* const map = ThrowIfNotJSReceiver( |
| 1134 MessageTemplate::kIncompatibleMethodReceiver, | 1142 &a, isolate, context, maybe_receiver, |
| 1135 "RegExp.prototype.test"); | 1143 MessageTemplate::kIncompatibleMethodReceiver, "RegExp.prototype.test"); |
| 1136 Node* const receiver = maybe_receiver; | 1144 Node* const receiver = maybe_receiver; |
| 1137 | 1145 |
| 1138 // Convert {maybe_string} to a String. | 1146 // Convert {maybe_string} to a String. |
| 1139 Node* const string = a.ToString(context, maybe_string); | 1147 Node* const string = a.ToString(context, maybe_string); |
| 1140 | 1148 |
| 1141 // Call exec. | 1149 CLabel fast_path(&a), slow_path(&a); |
| 1142 Node* const match_indices = RegExpExec(&a, context, receiver, string); | 1150 BranchIfFastPath(&a, context, map, &fast_path, &slow_path); |
| 1143 | 1151 |
| 1144 // Return true iff exec matched successfully. | 1152 a.Bind(&fast_path); |
| 1145 Node* const result = a.Select(a.WordEqual(match_indices, a.NullConstant()), | 1153 { |
| 1146 a.FalseConstant(), a.TrueConstant()); | 1154 CLabel if_didnotmatch(&a); |
| 1147 a.Return(result); | 1155 Generate_RegExpPrototypeExecBodyWithoutResult(&a, context, receiver, string, |
| 1156 &if_didnotmatch, true); | |
| 1157 a.Return(a.TrueConstant()); | |
| 1158 | |
| 1159 a.Bind(&if_didnotmatch); | |
| 1160 a.Return(a.FalseConstant()); | |
| 1161 } | |
| 1162 | |
| 1163 a.Bind(&slow_path); | |
| 1164 { | |
| 1165 // Call exec. | |
| 1166 Node* const match_indices = RegExpExec(&a, context, receiver, string); | |
| 1167 | |
| 1168 // Return true iff exec matched successfully. | |
| 1169 Node* const result = a.Select(a.WordEqual(match_indices, a.NullConstant()), | |
| 1170 a.FalseConstant(), a.TrueConstant()); | |
| 1171 a.Return(result); | |
| 1172 } | |
| 1148 } | 1173 } |
| 1149 | 1174 |
| 1150 namespace { | 1175 namespace { |
| 1151 | 1176 |
| 1152 Node* AdvanceStringIndex(CodeStubAssembler* a, Node* const string, | 1177 Node* AdvanceStringIndex(CodeStubAssembler* a, Node* const string, |
| 1153 Node* const index, Node* const is_unicode) { | 1178 Node* const index, Node* const is_unicode) { |
| 1154 CVariable var_result(a, MachineRepresentation::kTagged); | 1179 CVariable var_result(a, MachineRepresentation::kTagged); |
| 1155 | 1180 |
| 1156 // Default to last_index + 1. | 1181 // Default to last_index + 1. |
| 1157 Node* const index_plus_one = a->SmiAdd(index, a->SmiConstant(1)); | 1182 Node* const index_plus_one = a->SmiAdd(index, a->SmiConstant(1)); |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1353 // Loop preparations. Within the loop, collect results from RegExpExec | 1378 // Loop preparations. Within the loop, collect results from RegExpExec |
| 1354 // and store match strings in the array. | 1379 // and store match strings in the array. |
| 1355 | 1380 |
| 1356 CVariable* vars[] = {array.var_array(), array.var_length(), | 1381 CVariable* vars[] = {array.var_array(), array.var_length(), |
| 1357 array.var_capacity()}; | 1382 array.var_capacity()}; |
| 1358 CLabel loop(a, 3, vars), out(a); | 1383 CLabel loop(a, 3, vars), out(a); |
| 1359 a->Goto(&loop); | 1384 a->Goto(&loop); |
| 1360 | 1385 |
| 1361 a->Bind(&loop); | 1386 a->Bind(&loop); |
| 1362 { | 1387 { |
| 1363 Node* const result = is_fastpath ? Generate_RegExpPrototypeExecBody( | 1388 CVariable var_match(a, MachineRepresentation::kTagged); |
| 1364 a, context, regexp, string, true) | |
| 1365 : RegExpExec(a, context, regexp, string); | |
| 1366 | 1389 |
| 1367 CLabel if_didmatch(a), if_didnotmatch(a); | 1390 CLabel if_didmatch(a), if_didnotmatch(a); |
| 1368 a->Branch(a->WordEqual(result, null), &if_didnotmatch, &if_didmatch); | 1391 if (is_fastpath) { |
| 1392 // On the fast path, grab the matching string from the raw match index | |
| 1393 // array. | |
| 1394 Node* const match_indices = | |
| 1395 Generate_RegExpPrototypeExecBodyWithoutResult( | |
| 1396 a, context, regexp, string, &if_didnotmatch, true); | |
| 1369 | 1397 |
| 1370 a->Bind(&if_didnotmatch); | 1398 Node* const match_from = LoadMatchInfoField( |
| 1371 { | 1399 a, match_indices, RegExpMatchInfo::kFirstCaptureIndex); |
| 1372 // Return null if there were no matches, otherwise just exit the loop. | 1400 Node* const match_to = LoadMatchInfoField( |
| 1373 a->GotoUnless(a->IntPtrEqual(array.length(), int_zero), &out); | 1401 a, match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1); |
| 1374 a->Return(null); | |
| 1375 } | |
| 1376 | 1402 |
| 1377 a->Bind(&if_didmatch); | 1403 Node* match = a->SubString(context, string, match_from, match_to); |
| 1378 { | 1404 var_match.Bind(match); |
| 1379 Node* match = nullptr; | |
| 1380 if (is_fastpath) { | |
| 1381 // TODO(jgruber): We could optimize further here and in other | |
| 1382 // methods (e.g. @@search) by bypassing RegExp result construction. | |
| 1383 Node* const result_fixed_array = a->LoadElements(result); | |
| 1384 const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; | |
| 1385 match = | |
| 1386 a->LoadFixedArrayElement(result_fixed_array, int_zero, 0, mode); | |
| 1387 | 1405 |
| 1388 // The match is guaranteed to be a string on the fast path. | 1406 a->Goto(&if_didmatch); |
| 1389 CSA_ASSERT(a, a->IsStringInstanceType(a->LoadInstanceType(match))); | 1407 } else { |
| 1390 } else { | 1408 DCHECK(!is_fastpath); |
| 1391 DCHECK(!is_fastpath); | 1409 Node* const result = RegExpExec(a, context, regexp, string); |
| 1392 | 1410 |
| 1393 CVariable var_match(a, MachineRepresentation::kTagged); | 1411 CLabel load_match(a); |
| 1394 CLabel fast_result(a), slow_result(a), match_loaded(a); | 1412 a->Branch(a->WordEqual(result, null), &if_didnotmatch, &load_match); |
| 1413 | |
| 1414 a->Bind(&load_match); | |
| 1415 { | |
| 1416 CLabel fast_result(a), slow_result(a); | |
| 1395 BranchIfFastRegExpResult(a, context, a->LoadMap(result), &fast_result, | 1417 BranchIfFastRegExpResult(a, context, a->LoadMap(result), &fast_result, |
| 1396 &slow_result); | 1418 &slow_result); |
| 1397 | 1419 |
| 1398 a->Bind(&fast_result); | 1420 a->Bind(&fast_result); |
| 1399 { | 1421 { |
| 1400 // TODO(jgruber): We could optimize further here and in other | |
| 1401 // methods (e.g. @@search) by bypassing RegExp result construction. | |
| 1402 Node* const result_fixed_array = a->LoadElements(result); | 1422 Node* const result_fixed_array = a->LoadElements(result); |
| 1403 const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; | 1423 const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; |
| 1404 Node* const match = | 1424 Node* const match = |
| 1405 a->LoadFixedArrayElement(result_fixed_array, int_zero, 0, mode); | 1425 a->LoadFixedArrayElement(result_fixed_array, int_zero, 0, mode); |
| 1406 | 1426 |
| 1407 // The match is guaranteed to be a string on the fast path. | 1427 // The match is guaranteed to be a string on the fast path. |
| 1408 CSA_ASSERT(a, a->IsStringInstanceType(a->LoadInstanceType(match))); | 1428 CSA_ASSERT(a, a->IsStringInstanceType(a->LoadInstanceType(match))); |
| 1409 | 1429 |
| 1410 var_match.Bind(match); | 1430 var_match.Bind(match); |
| 1411 a->Goto(&match_loaded); | 1431 a->Goto(&if_didmatch); |
| 1412 } | 1432 } |
| 1413 | 1433 |
| 1414 a->Bind(&slow_result); | 1434 a->Bind(&slow_result); |
| 1415 { | 1435 { |
| 1416 // TODO(ishell): Use GetElement stub once it's available. | 1436 // TODO(ishell): Use GetElement stub once it's available. |
| 1417 Node* const name = smi_zero; | 1437 Node* const name = smi_zero; |
| 1418 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | 1438 Callable getproperty_callable = CodeFactory::GetProperty(isolate); |
| 1419 Node* const match = | 1439 Node* const match = |
| 1420 a->CallStub(getproperty_callable, context, result, name); | 1440 a->CallStub(getproperty_callable, context, result, name); |
| 1421 | 1441 |
| 1422 var_match.Bind(match); | 1442 var_match.Bind(a->ToString(context, match)); |
| 1423 a->Goto(&match_loaded); | 1443 a->Goto(&if_didmatch); |
| 1424 } | 1444 } |
| 1445 } | |
| 1446 } | |
| 1425 | 1447 |
| 1426 a->Bind(&match_loaded); | 1448 a->Bind(&if_didnotmatch); |
| 1427 match = a->ToString(context, var_match.value()); | 1449 { |
| 1428 } | 1450 // Return null if there were no matches, otherwise just exit the loop. |
| 1429 DCHECK(match != nullptr); | 1451 a->GotoUnless(a->IntPtrEqual(array.length(), int_zero), &out); |
| 1452 a->Return(null); | |
| 1453 } | |
| 1454 | |
| 1455 a->Bind(&if_didmatch); | |
| 1456 { | |
| 1457 Node* match = var_match.value(); | |
| 1430 | 1458 |
| 1431 // Store the match, growing the fixed array if needed. | 1459 // Store the match, growing the fixed array if needed. |
| 1432 | 1460 |
| 1433 array.Push(match); | 1461 array.Push(match); |
| 1434 | 1462 |
| 1435 // Advance last index if the match is the empty string. | 1463 // Advance last index if the match is the empty string. |
| 1436 | 1464 |
| 1437 Node* const match_length = a->LoadStringLength(match); | 1465 Node* const match_length = a->LoadStringLength(match); |
| 1438 a->GotoUnless(a->SmiEqual(match_length, smi_zero), &loop); | 1466 a->GotoUnless(a->SmiEqual(match_length, smi_zero), &loop); |
| 1439 | 1467 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1486 | 1514 |
| 1487 a.Bind(&fast_path); | 1515 a.Bind(&fast_path); |
| 1488 Generate_RegExpPrototypeMatchBody(&a, receiver, string, context, true); | 1516 Generate_RegExpPrototypeMatchBody(&a, receiver, string, context, true); |
| 1489 | 1517 |
| 1490 a.Bind(&slow_path); | 1518 a.Bind(&slow_path); |
| 1491 Generate_RegExpPrototypeMatchBody(&a, receiver, string, context, false); | 1519 Generate_RegExpPrototypeMatchBody(&a, receiver, string, context, false); |
| 1492 } | 1520 } |
| 1493 | 1521 |
| 1494 namespace { | 1522 namespace { |
| 1495 | 1523 |
| 1496 void Generate_RegExpPrototypeSearchBody(CodeStubAssembler* a, | 1524 void Generate_RegExpPrototypeSearchBodyFast(CodeStubAssembler* a, |
|
Igor Sheludko
2016/11/30 23:17:22
I think you can drop Generate_ prefixes from helpe
jgruber
2016/12/01 09:48:27
Done.
| |
| 1497 Node* const receiver, | 1525 Node* const receiver, |
| 1498 Node* const string, Node* const context, | 1526 Node* const string, |
| 1499 bool is_fastpath) { | 1527 Node* const context) { |
| 1528 // Grab the initial value of last index. | |
| 1529 Node* const previous_last_index = FastLoadLastIndex(a, receiver); | |
| 1530 | |
| 1531 // Ensure last index is 0. | |
| 1532 FastStoreLastIndex(a, receiver, a->SmiConstant(Smi::kZero)); | |
| 1533 | |
| 1534 // Call exec. | |
| 1535 CLabel if_didnotmatch(a); | |
| 1536 Node* const match_indices = Generate_RegExpPrototypeExecBodyWithoutResult( | |
| 1537 a, context, receiver, string, &if_didnotmatch, true); | |
| 1538 | |
| 1539 // Successful match. | |
| 1540 { | |
| 1541 // Reset last index. | |
| 1542 FastStoreLastIndex(a, receiver, previous_last_index); | |
| 1543 | |
| 1544 // Return the index of the match. | |
| 1545 Node* const index = LoadMatchInfoField(a, match_indices, | |
| 1546 RegExpMatchInfo::kFirstCaptureIndex); | |
| 1547 a->Return(index); | |
| 1548 } | |
| 1549 | |
| 1550 a->Bind(&if_didnotmatch); | |
| 1551 { | |
| 1552 // Reset last index and return -1. | |
| 1553 FastStoreLastIndex(a, receiver, previous_last_index); | |
| 1554 a->Return(a->SmiConstant(-1)); | |
| 1555 } | |
| 1556 } | |
| 1557 | |
| 1558 void Generate_RegExpPrototypeSearchBodySlow(CodeStubAssembler* a, | |
| 1559 Node* const receiver, | |
| 1560 Node* const string, | |
| 1561 Node* const context) { | |
| 1500 Isolate* const isolate = a->isolate(); | 1562 Isolate* const isolate = a->isolate(); |
| 1501 | 1563 |
| 1502 Node* const smi_zero = a->SmiConstant(Smi::kZero); | 1564 Node* const smi_zero = a->SmiConstant(Smi::kZero); |
| 1503 | 1565 |
| 1504 // Grab the initial value of last index. | 1566 // Grab the initial value of last index. |
| 1505 Node* const previous_last_index = | 1567 Node* const previous_last_index = SlowLoadLastIndex(a, context, receiver); |
| 1506 LoadLastIndex(a, context, receiver, is_fastpath); | |
| 1507 | 1568 |
| 1508 // Ensure last index is 0. | 1569 // Ensure last index is 0. |
| 1509 if (is_fastpath) { | 1570 { |
| 1510 FastStoreLastIndex(a, receiver, smi_zero); | |
| 1511 } else { | |
| 1512 CLabel next(a); | 1571 CLabel next(a); |
| 1513 a->GotoIf(a->SameValue(previous_last_index, smi_zero, context), &next); | 1572 a->GotoIf(a->SameValue(previous_last_index, smi_zero, context), &next); |
| 1514 | 1573 |
| 1515 SlowStoreLastIndex(a, context, receiver, smi_zero); | 1574 SlowStoreLastIndex(a, context, receiver, smi_zero); |
| 1516 a->Goto(&next); | 1575 a->Goto(&next); |
| 1517 a->Bind(&next); | 1576 a->Bind(&next); |
| 1518 } | 1577 } |
| 1519 | 1578 |
| 1520 // Call exec. | 1579 // Call exec. |
| 1521 Node* const match_indices = | 1580 Node* const exec_result = RegExpExec(a, context, receiver, string); |
| 1522 is_fastpath | |
| 1523 ? Generate_RegExpPrototypeExecBody(a, context, receiver, string, true) | |
| 1524 : RegExpExec(a, context, receiver, string); | |
| 1525 | 1581 |
| 1526 // Reset last index if necessary. | 1582 // Reset last index if necessary. |
| 1527 if (is_fastpath) { | 1583 { |
| 1528 FastStoreLastIndex(a, receiver, previous_last_index); | |
| 1529 } else { | |
| 1530 CLabel next(a); | 1584 CLabel next(a); |
| 1531 Node* const current_last_index = SlowLoadLastIndex(a, context, receiver); | 1585 Node* const current_last_index = SlowLoadLastIndex(a, context, receiver); |
| 1532 | 1586 |
| 1533 a->GotoIf(a->SameValue(current_last_index, previous_last_index, context), | 1587 a->GotoIf(a->SameValue(current_last_index, previous_last_index, context), |
| 1534 &next); | 1588 &next); |
| 1535 | 1589 |
| 1536 SlowStoreLastIndex(a, context, receiver, previous_last_index); | 1590 SlowStoreLastIndex(a, context, receiver, previous_last_index); |
| 1537 a->Goto(&next); | 1591 a->Goto(&next); |
| 1592 | |
| 1538 a->Bind(&next); | 1593 a->Bind(&next); |
| 1539 } | 1594 } |
| 1540 | 1595 |
| 1541 // Return -1 if no match was found. | 1596 // Return -1 if no match was found. |
| 1542 { | 1597 { |
| 1543 CLabel next(a); | 1598 CLabel next(a); |
| 1544 a->GotoUnless(a->WordEqual(match_indices, a->NullConstant()), &next); | 1599 a->GotoUnless(a->WordEqual(exec_result, a->NullConstant()), &next); |
| 1545 a->Return(a->SmiConstant(-1)); | 1600 a->Return(a->SmiConstant(-1)); |
| 1546 a->Bind(&next); | 1601 a->Bind(&next); |
| 1547 } | 1602 } |
| 1548 | 1603 |
| 1549 // Return the index of the match. | 1604 // Return the index of the match. |
| 1550 if (is_fastpath) { | 1605 { |
| 1551 Node* const index = a->LoadObjectField( | |
| 1552 match_indices, JSRegExpResult::kIndexOffset, MachineType::AnyTagged()); | |
| 1553 a->Return(index); | |
| 1554 } else { | |
| 1555 DCHECK(!is_fastpath); | |
| 1556 | |
| 1557 CLabel fast_result(a), slow_result(a, CLabel::kDeferred); | 1606 CLabel fast_result(a), slow_result(a, CLabel::kDeferred); |
| 1558 BranchIfFastRegExpResult(a, context, a->LoadMap(match_indices), | 1607 BranchIfFastRegExpResult(a, context, a->LoadMap(exec_result), &fast_result, |
| 1559 &fast_result, &slow_result); | 1608 &slow_result); |
| 1560 | 1609 |
| 1561 a->Bind(&fast_result); | 1610 a->Bind(&fast_result); |
| 1562 { | 1611 { |
| 1563 Node* const index = | 1612 Node* const index = a->LoadObjectField( |
| 1564 a->LoadObjectField(match_indices, JSRegExpResult::kIndexOffset, | 1613 exec_result, JSRegExpResult::kIndexOffset, MachineType::AnyTagged()); |
|
Igor Sheludko
2016/11/30 23:17:22
AnyTagged() is default, you can drop it for readab
jgruber
2016/12/01 09:48:27
Done.
| |
| 1565 MachineType::AnyTagged()); | |
| 1566 a->Return(index); | 1614 a->Return(index); |
| 1567 } | 1615 } |
| 1568 | 1616 |
| 1569 a->Bind(&slow_result); | 1617 a->Bind(&slow_result); |
| 1570 { | 1618 { |
| 1571 Node* const name = a->HeapConstant(isolate->factory()->index_string()); | 1619 Node* const name = a->HeapConstant(isolate->factory()->index_string()); |
| 1572 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate()); | 1620 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate()); |
| 1573 Node* const index = | 1621 Node* const index = |
| 1574 a->CallStub(getproperty_callable, context, match_indices, name); | 1622 a->CallStub(getproperty_callable, context, exec_result, name); |
| 1575 a->Return(index); | 1623 a->Return(index); |
| 1576 } | 1624 } |
| 1577 } | 1625 } |
| 1578 } | 1626 } |
| 1579 | 1627 |
| 1580 } // namespace | 1628 } // namespace |
| 1581 | 1629 |
| 1582 // ES#sec-regexp.prototype-@@search | 1630 // ES#sec-regexp.prototype-@@search |
| 1583 // RegExp.prototype [ @@search ] ( string ) | 1631 // RegExp.prototype [ @@search ] ( string ) |
| 1584 void Builtins::Generate_RegExpPrototypeSearch(CodeAssemblerState* state) { | 1632 void Builtins::Generate_RegExpPrototypeSearch(CodeAssemblerState* state) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1597 "RegExp.prototype.@@search"); | 1645 "RegExp.prototype.@@search"); |
| 1598 Node* const receiver = maybe_receiver; | 1646 Node* const receiver = maybe_receiver; |
| 1599 | 1647 |
| 1600 // Convert {maybe_string} to a String. | 1648 // Convert {maybe_string} to a String. |
| 1601 Node* const string = a.ToString(context, maybe_string); | 1649 Node* const string = a.ToString(context, maybe_string); |
| 1602 | 1650 |
| 1603 CLabel fast_path(&a), slow_path(&a); | 1651 CLabel fast_path(&a), slow_path(&a); |
| 1604 BranchIfFastPath(&a, context, map, &fast_path, &slow_path); | 1652 BranchIfFastPath(&a, context, map, &fast_path, &slow_path); |
| 1605 | 1653 |
| 1606 a.Bind(&fast_path); | 1654 a.Bind(&fast_path); |
| 1607 Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, true); | 1655 Generate_RegExpPrototypeSearchBodyFast(&a, receiver, string, context); |
| 1608 | 1656 |
| 1609 a.Bind(&slow_path); | 1657 a.Bind(&slow_path); |
| 1610 Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, false); | 1658 Generate_RegExpPrototypeSearchBodySlow(&a, receiver, string, context); |
| 1611 } | 1659 } |
| 1612 | 1660 |
| 1613 namespace { | 1661 namespace { |
| 1614 | 1662 |
| 1615 // Generates the fast path for @@split. {regexp} is an unmodified JSRegExp, | 1663 // Generates the fast path for @@split. {regexp} is an unmodified JSRegExp, |
| 1616 // {string} is a String, and {limit} is a Smi. | 1664 // {string} is a String, and {limit} is a Smi. |
| 1617 void Generate_RegExpPrototypeSplitBody(CodeStubAssembler* a, Node* const regexp, | 1665 void Generate_RegExpPrototypeSplitBody(CodeStubAssembler* a, Node* const regexp, |
| 1618 Node* const string, Node* const limit, | 1666 Node* const string, Node* const limit, |
| 1619 Node* const context) { | 1667 Node* const context) { |
| 1620 Isolate* isolate = a->isolate(); | 1668 Isolate* isolate = a->isolate(); |
| (...skipping 761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2382 a.Bind(&if_matched); | 2430 a.Bind(&if_matched); |
| 2383 { | 2431 { |
| 2384 Node* result = ConstructNewResultFromMatchInfo(isolate, &a, context, | 2432 Node* result = ConstructNewResultFromMatchInfo(isolate, &a, context, |
| 2385 match_indices, string); | 2433 match_indices, string); |
| 2386 a.Return(result); | 2434 a.Return(result); |
| 2387 } | 2435 } |
| 2388 } | 2436 } |
| 2389 | 2437 |
| 2390 } // namespace internal | 2438 } // namespace internal |
| 2391 } // namespace v8 | 2439 } // namespace v8 |
| OLD | NEW |