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

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

Issue 2543483003: [regexp] Skip result construction in test, @@match, @@search (Closed)
Patch Set: 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
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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | test/js-perf-test/RegExp/base_ctor.js » ('j') | test/js-perf-test/RegExp/base_ctor.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698