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-regexp.h" | 5 #include "src/builtins/builtins-regexp.h" |
6 | 6 |
7 #include "src/builtins/builtins-constructor.h" | 7 #include "src/builtins/builtins-constructor.h" |
8 #include "src/builtins/builtins-utils.h" | 8 #include "src/builtins/builtins-utils.h" |
9 #include "src/builtins/builtins.h" | 9 #include "src/builtins/builtins.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
448 Node* const pending_exception = | 448 Node* const pending_exception = |
449 Load(MachineType::AnyTagged(), pending_exception_address); | 449 Load(MachineType::AnyTagged(), pending_exception_address); |
450 | 450 |
451 // If there is no pending exception, a | 451 // If there is no pending exception, a |
452 // stack overflow (on the backtrack stack) was detected in RegExp code. | 452 // stack overflow (on the backtrack stack) was detected in RegExp code. |
453 | 453 |
454 Label stack_overflow(this), rethrow(this); | 454 Label stack_overflow(this), rethrow(this); |
455 Branch(IsTheHole(pending_exception), &stack_overflow, &rethrow); | 455 Branch(IsTheHole(pending_exception), &stack_overflow, &rethrow); |
456 | 456 |
457 Bind(&stack_overflow); | 457 Bind(&stack_overflow); |
458 TailCallRuntime(Runtime::kThrowStackOverflow, context); | 458 CallRuntime(Runtime::kThrowStackOverflow, context); |
459 Unreachable(); | |
459 | 460 |
460 Bind(&rethrow); | 461 Bind(&rethrow); |
461 TailCallRuntime(Runtime::kRegExpExecReThrow, context); | 462 CallRuntime(Runtime::kRegExpExecReThrow, context); |
463 Unreachable(); | |
462 } | 464 } |
463 | 465 |
464 Bind(&runtime); | 466 Bind(&runtime); |
465 { | 467 { |
466 Node* const result = CallRuntime(Runtime::kRegExpExec, context, regexp, | 468 Node* const result = CallRuntime(Runtime::kRegExpExec, context, regexp, |
467 string, last_index, match_info); | 469 string, last_index, match_info); |
468 var_result.Bind(result); | 470 var_result.Bind(result); |
469 Goto(&out); | 471 Goto(&out); |
470 } | 472 } |
471 | 473 |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
729 Label* if_isunmodified, | 731 Label* if_isunmodified, |
730 Label* if_ismodified) { | 732 Label* if_ismodified) { |
731 Node* const native_context = LoadNativeContext(context); | 733 Node* const native_context = LoadNativeContext(context); |
732 Node* const initial_regexp_result_map = | 734 Node* const initial_regexp_result_map = |
733 LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX); | 735 LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX); |
734 | 736 |
735 Branch(WordEqual(map, initial_regexp_result_map), if_isunmodified, | 737 Branch(WordEqual(map, initial_regexp_result_map), if_isunmodified, |
736 if_ismodified); | 738 if_ismodified); |
737 } | 739 } |
738 | 740 |
741 // Slow path stub for RegExpPrototypeExec to decrease code size. | |
742 TF_BUILTIN(RegExpPrototypeExecSlow, RegExpBuiltinsAssembler) { | |
743 typedef GenericTagged2Descriptor Descriptor; | |
744 | |
745 Node* const regexp = Parameter(Descriptor::kFirst); | |
746 Node* const string = Parameter(Descriptor::kSecond); | |
747 Node* const context = Parameter(Descriptor::kContext); | |
748 | |
749 Return(RegExpPrototypeExecBody(context, regexp, string, false)); | |
750 } | |
751 | |
739 // ES#sec-regexp.prototype.exec | 752 // ES#sec-regexp.prototype.exec |
740 // RegExp.prototype.exec ( string ) | 753 // RegExp.prototype.exec ( string ) |
741 TF_BUILTIN(RegExpPrototypeExec, RegExpBuiltinsAssembler) { | 754 TF_BUILTIN(RegExpPrototypeExec, RegExpBuiltinsAssembler) { |
742 Node* const maybe_receiver = Parameter(0); | 755 Node* const maybe_receiver = Parameter(0); |
743 Node* const maybe_string = Parameter(1); | 756 Node* const maybe_string = Parameter(1); |
744 Node* const context = Parameter(4); | 757 Node* const context = Parameter(4); |
745 | 758 |
746 // Ensure {maybe_receiver} is a JSRegExp. | 759 // Ensure {maybe_receiver} is a JSRegExp. |
747 Node* const regexp_map = ThrowIfNotInstanceType( | 760 Node* const regexp_map = ThrowIfNotInstanceType( |
748 context, maybe_receiver, JS_REGEXP_TYPE, "RegExp.prototype.exec"); | 761 context, maybe_receiver, JS_REGEXP_TYPE, "RegExp.prototype.exec"); |
749 Node* const receiver = maybe_receiver; | 762 Node* const receiver = maybe_receiver; |
750 | 763 |
751 // Convert {maybe_string} to a String. | 764 // Convert {maybe_string} to a String. |
752 Node* const string = ToString(context, maybe_string); | 765 Node* const string = ToString(context, maybe_string); |
753 | 766 |
754 Label if_isfastpath(this), if_isslowpath(this); | 767 Label if_isfastpath(this), if_isslowpath(this); |
755 Branch(IsInitialRegExpMap(context, regexp_map), &if_isfastpath, | 768 Branch(IsInitialRegExpMap(context, regexp_map), &if_isfastpath, |
756 &if_isslowpath); | 769 &if_isslowpath); |
757 | 770 |
758 Bind(&if_isfastpath); | 771 Bind(&if_isfastpath); |
759 { | 772 { |
760 Node* const result = | 773 Node* const result = |
761 RegExpPrototypeExecBody(context, receiver, string, true); | 774 RegExpPrototypeExecBody(context, receiver, string, true); |
762 Return(result); | 775 Return(result); |
763 } | 776 } |
764 | 777 |
765 Bind(&if_isslowpath); | 778 Bind(&if_isslowpath); |
766 { | 779 { |
767 Node* const result = | 780 Handle<Code> code = isolate()->builtins()->RegExpPrototypeExecSlow(); |
768 RegExpPrototypeExecBody(context, receiver, string, false); | 781 const auto desc = GenericTagged2Descriptor(isolate()); |
782 Callable callable(code, desc); | |
783 | |
784 Node* const result = CallStub(callable, context, receiver, string); | |
769 Return(result); | 785 Return(result); |
770 } | 786 } |
771 } | 787 } |
772 | 788 |
773 Node* RegExpBuiltinsAssembler::FlagsGetter(Node* const context, | 789 Node* RegExpBuiltinsAssembler::FlagsGetter(Node* const context, |
774 Node* const regexp, | 790 Node* const regexp, |
775 bool is_fastpath) { | 791 bool is_fastpath) { |
776 Isolate* isolate = this->isolate(); | 792 Isolate* isolate = this->isolate(); |
777 | 793 |
778 Node* const int_zero = IntPtrConstant(0); | 794 Node* const int_zero = IntPtrConstant(0); |
(...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1472 Node* RegExpBuiltinsAssembler::RegExpExec(Node* context, Node* regexp, | 1488 Node* RegExpBuiltinsAssembler::RegExpExec(Node* context, Node* regexp, |
1473 Node* string) { | 1489 Node* string) { |
1474 Isolate* isolate = this->isolate(); | 1490 Isolate* isolate = this->isolate(); |
1475 | 1491 |
1476 Node* const null = NullConstant(); | 1492 Node* const null = NullConstant(); |
1477 | 1493 |
1478 Variable var_result(this, MachineRepresentation::kTagged); | 1494 Variable var_result(this, MachineRepresentation::kTagged); |
1479 Label out(this), if_isfastpath(this), if_isslowpath(this); | 1495 Label out(this), if_isfastpath(this), if_isslowpath(this); |
1480 | 1496 |
1481 Node* const map = LoadMap(regexp); | 1497 Node* const map = LoadMap(regexp); |
1482 BranchIfFastRegExp(context, map, &if_isfastpath, &if_isslowpath); | 1498 BranchIfFastRegExp(context, map, &if_isfastpath, &if_isslowpath); |
Igor Sheludko
2017/03/13 16:30:32
I guess it's better to skip this check and jump di
jgruber
2017/03/17 09:51:22
Done.
| |
1483 | 1499 |
1484 Bind(&if_isfastpath); | 1500 Bind(&if_isfastpath); |
1485 { | 1501 Unreachable(); |
1486 Node* const result = RegExpPrototypeExecBody(context, regexp, string, true); | |
1487 var_result.Bind(result); | |
1488 Goto(&out); | |
1489 } | |
1490 | 1502 |
1491 Bind(&if_isslowpath); | 1503 Bind(&if_isslowpath); |
1492 { | 1504 { |
1493 // Take the slow path of fetching the exec property, calling it, and | 1505 // Take the slow path of fetching the exec property, calling it, and |
1494 // verifying its return value. | 1506 // verifying its return value. |
1495 | 1507 |
1496 // Get the exec property. | 1508 // Get the exec property. |
1497 Node* const name = HeapConstant(isolate->factory()->exec_string()); | 1509 Node* const name = HeapConstant(isolate->factory()->exec_string()); |
1498 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | 1510 Callable getproperty_callable = CodeFactory::GetProperty(isolate); |
1499 Node* const exec = CallStub(getproperty_callable, context, regexp, name); | 1511 Node* const exec = CallStub(getproperty_callable, context, regexp, name); |
(...skipping 18 matching lines...) Expand all Loading... | |
1518 MessageTemplate::kInvalidRegExpExecResult, "unused"); | 1530 MessageTemplate::kInvalidRegExpExecResult, "unused"); |
1519 | 1531 |
1520 Goto(&out); | 1532 Goto(&out); |
1521 } | 1533 } |
1522 | 1534 |
1523 Bind(&if_isnotcallable); | 1535 Bind(&if_isnotcallable); |
1524 { | 1536 { |
1525 ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE, | 1537 ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE, |
1526 "RegExp.prototype.exec"); | 1538 "RegExp.prototype.exec"); |
1527 | 1539 |
1528 Node* const result = | 1540 Handle<Code> code = isolate->builtins()->RegExpPrototypeExecSlow(); |
1529 RegExpPrototypeExecBody(context, regexp, string, false); | 1541 const auto desc = GenericTagged2Descriptor(isolate); |
1542 Callable callable(code, desc); | |
1543 | |
1544 Node* const result = CallStub(callable, context, regexp, string); | |
1530 var_result.Bind(result); | 1545 var_result.Bind(result); |
1531 Goto(&out); | 1546 Goto(&out); |
1532 } | 1547 } |
1533 } | 1548 } |
1534 | 1549 |
1535 Bind(&out); | 1550 Bind(&out); |
1536 return var_result.value(); | 1551 return var_result.value(); |
1537 } | 1552 } |
1538 | 1553 |
1539 // ES#sec-regexp.prototype.test | 1554 // ES#sec-regexp.prototype.test |
(...skipping 1281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2821 Bind(&if_matched); | 2836 Bind(&if_matched); |
2822 { | 2837 { |
2823 Node* result = | 2838 Node* result = |
2824 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); | 2839 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); |
2825 Return(result); | 2840 Return(result); |
2826 } | 2841 } |
2827 } | 2842 } |
2828 | 2843 |
2829 } // namespace internal | 2844 } // namespace internal |
2830 } // namespace v8 | 2845 } // namespace v8 |
OLD | NEW |