OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/compiler/bytecode-graph-builder.h" | 5 #include "src/compiler/bytecode-graph-builder.h" |
6 | 6 |
7 #include "src/ast/ast.h" | 7 #include "src/ast/ast.h" |
8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
9 #include "src/compilation-info.h" | 9 #include "src/compilation-info.h" |
10 #include "src/compiler/bytecode-branch-analysis.h" | 10 #include "src/compiler/bytecode-branch-analysis.h" |
(...skipping 630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 | 641 |
642 VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) { | 642 VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) { |
643 FeedbackVectorSlot slot; | 643 FeedbackVectorSlot slot; |
644 if (slot_id >= TypeFeedbackVector::kReservedIndexCount) { | 644 if (slot_id >= TypeFeedbackVector::kReservedIndexCount) { |
645 slot = feedback_vector()->ToSlot(slot_id); | 645 slot = feedback_vector()->ToSlot(slot_id); |
646 } | 646 } |
647 return VectorSlotPair(feedback_vector(), slot); | 647 return VectorSlotPair(feedback_vector(), slot); |
648 } | 648 } |
649 | 649 |
650 bool BytecodeGraphBuilder::CreateGraph() { | 650 bool BytecodeGraphBuilder::CreateGraph() { |
651 // Set up the basic structure of the graph. Outputs for {Start} are | |
652 // the formal parameters (including the receiver) plus context and | |
653 // closure. | |
654 | |
655 // Set up the basic structure of the graph. Outputs for {Start} are the formal | 651 // Set up the basic structure of the graph. Outputs for {Start} are the formal |
656 // parameters (including the receiver) plus new target, number of arguments, | 652 // parameters (including the receiver) plus new target, number of arguments, |
657 // context and closure. | 653 // context and closure. |
658 int actual_parameter_count = bytecode_array()->parameter_count() + 4; | 654 int actual_parameter_count = bytecode_array()->parameter_count() + 4; |
659 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count))); | 655 graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count))); |
660 | 656 |
661 Environment env(this, bytecode_array()->register_count(), | 657 Environment env(this, bytecode_array()->register_count(), |
662 bytecode_array()->parameter_count(), graph()->start(), | 658 bytecode_array()->parameter_count(), graph()->start(), |
663 GetFunctionContext()); | 659 GetFunctionContext()); |
664 set_environment(&env); | 660 set_environment(&env); |
665 | 661 |
666 // For OSR add an {OsrNormalEntry} as the start of the top-level environment. | |
667 // It will be replaced with {Dead} after typing and optimizations. | |
668 if (!osr_ast_id_.IsNone()) NewNode(common()->OsrNormalEntry()); | |
669 | |
670 VisitBytecodes(); | 662 VisitBytecodes(); |
671 | 663 |
672 // Finish the basic structure of the graph. | 664 // Finish the basic structure of the graph. |
673 DCHECK_NE(0u, exit_controls_.size()); | 665 DCHECK_NE(0u, exit_controls_.size()); |
674 int const input_count = static_cast<int>(exit_controls_.size()); | 666 int const input_count = static_cast<int>(exit_controls_.size()); |
675 Node** const inputs = &exit_controls_.front(); | 667 Node** const inputs = &exit_controls_.front(); |
676 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); | 668 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); |
677 graph()->SetEnd(end); | 669 graph()->SetEnd(end); |
678 | 670 |
679 ClearNonLiveSlotsInFrameStates(); | 671 ClearNonLiveSlotsInFrameStates(); |
(...skipping 17 matching lines...) Expand all Loading... |
697 | 689 |
698 void BytecodeGraphBuilder::VisitBytecodes() { | 690 void BytecodeGraphBuilder::VisitBytecodes() { |
699 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); | 691 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); |
700 BytecodeLoopAnalysis loop_analysis(bytecode_array(), &analysis, local_zone()); | 692 BytecodeLoopAnalysis loop_analysis(bytecode_array(), &analysis, local_zone()); |
701 analysis.Analyze(); | 693 analysis.Analyze(); |
702 loop_analysis.Analyze(); | 694 loop_analysis.Analyze(); |
703 set_branch_analysis(&analysis); | 695 set_branch_analysis(&analysis); |
704 set_loop_analysis(&loop_analysis); | 696 set_loop_analysis(&loop_analysis); |
705 interpreter::BytecodeArrayIterator iterator(bytecode_array()); | 697 interpreter::BytecodeArrayIterator iterator(bytecode_array()); |
706 set_bytecode_iterator(&iterator); | 698 set_bytecode_iterator(&iterator); |
| 699 BuildOSRNormalEntryPoint(); |
707 while (!iterator.done()) { | 700 while (!iterator.done()) { |
708 int current_offset = iterator.current_offset(); | 701 int current_offset = iterator.current_offset(); |
709 EnterAndExitExceptionHandlers(current_offset); | 702 EnterAndExitExceptionHandlers(current_offset); |
710 SwitchToMergeEnvironment(current_offset); | 703 SwitchToMergeEnvironment(current_offset); |
711 if (environment() != nullptr) { | 704 if (environment() != nullptr) { |
712 BuildLoopHeaderEnvironment(current_offset); | 705 BuildLoopHeaderEnvironment(current_offset); |
| 706 BuildOSRLoopEntryPoint(current_offset); |
713 | 707 |
714 switch (iterator.current_bytecode()) { | 708 switch (iterator.current_bytecode()) { |
715 #define BYTECODE_CASE(name, ...) \ | 709 #define BYTECODE_CASE(name, ...) \ |
716 case interpreter::Bytecode::k##name: \ | 710 case interpreter::Bytecode::k##name: \ |
717 Visit##name(); \ | 711 Visit##name(); \ |
718 break; | 712 break; |
719 BYTECODE_LIST(BYTECODE_CASE) | 713 BYTECODE_LIST(BYTECODE_CASE) |
720 #undef BYTECODE_CODE | 714 #undef BYTECODE_CODE |
721 } | 715 } |
722 } | 716 } |
(...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1625 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() { | 1619 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() { |
1626 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); | 1620 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); |
1627 } | 1621 } |
1628 | 1622 |
1629 void BytecodeGraphBuilder::VisitStackCheck() { | 1623 void BytecodeGraphBuilder::VisitStackCheck() { |
1630 FrameStateBeforeAndAfter states(this); | 1624 FrameStateBeforeAndAfter states(this); |
1631 Node* node = NewNode(javascript()->StackCheck()); | 1625 Node* node = NewNode(javascript()->StackCheck()); |
1632 environment()->RecordAfterState(node, &states); | 1626 environment()->RecordAfterState(node, &states); |
1633 } | 1627 } |
1634 | 1628 |
1635 void BytecodeGraphBuilder::VisitOsrPoll() { | 1629 void BytecodeGraphBuilder::VisitOsrPoll() {} |
1636 // TODO(4764): This should be moved into the {VisitBytecodes} once we merge | |
1637 // the polling with existing bytecode. This will also guarantee that we are | |
1638 // not missing the OSR entry point, which we wouldn't catch right now. | |
1639 if (osr_ast_id_.ToInt() == bytecode_iterator().current_offset()) { | |
1640 environment()->PrepareForOsr(); | |
1641 } | |
1642 } | |
1643 | 1630 |
1644 void BytecodeGraphBuilder::VisitReturn() { | 1631 void BytecodeGraphBuilder::VisitReturn() { |
1645 BuildLoopExitsForFunctionExit(); | 1632 BuildLoopExitsForFunctionExit(); |
1646 Node* control = | 1633 Node* control = |
1647 NewNode(common()->Return(), environment()->LookupAccumulator()); | 1634 NewNode(common()->Return(), environment()->LookupAccumulator()); |
1648 MergeControlToLeaveFunction(control); | 1635 MergeControlToLeaveFunction(control); |
1649 } | 1636 } |
1650 | 1637 |
1651 void BytecodeGraphBuilder::VisitDebugger() { | 1638 void BytecodeGraphBuilder::VisitDebugger() { |
1652 FrameStateBeforeAndAfter states(this); | 1639 FrameStateBeforeAndAfter states(this); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1805 merge_environments_[target_offset]->Merge(environment()); | 1792 merge_environments_[target_offset]->Merge(environment()); |
1806 } | 1793 } |
1807 set_environment(nullptr); | 1794 set_environment(nullptr); |
1808 } | 1795 } |
1809 | 1796 |
1810 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { | 1797 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { |
1811 exit_controls_.push_back(exit); | 1798 exit_controls_.push_back(exit); |
1812 set_environment(nullptr); | 1799 set_environment(nullptr); |
1813 } | 1800 } |
1814 | 1801 |
| 1802 void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) { |
| 1803 if (!osr_ast_id_.IsNone() && osr_ast_id_.ToInt() == current_offset) { |
| 1804 // For OSR add a special {OsrLoopEntry} node into the current loop header. |
| 1805 // It will be turned into a usable entry by the OSR deconstruction. |
| 1806 environment()->PrepareForOsr(); |
| 1807 } |
| 1808 } |
| 1809 |
| 1810 void BytecodeGraphBuilder::BuildOSRNormalEntryPoint() { |
| 1811 if (!osr_ast_id_.IsNone()) { |
| 1812 // For OSR add an {OsrNormalEntry} as the the top-level environment start. |
| 1813 // It will be replaced with {Dead} by the OSR deconstruction. |
| 1814 NewNode(common()->OsrNormalEntry()); |
| 1815 // Note that the requested OSR entry point must be the target of a backward |
| 1816 // branch, otherwise there will not be a proper loop header available. |
| 1817 DCHECK(branch_analysis()->backward_branches_target(osr_ast_id_.ToInt())); |
| 1818 } |
| 1819 } |
| 1820 |
1815 void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) { | 1821 void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) { |
1816 int origin_offset = bytecode_iterator().current_offset(); | 1822 int origin_offset = bytecode_iterator().current_offset(); |
1817 // Only build loop exits for forward edges. | 1823 // Only build loop exits for forward edges. |
1818 if (target_offset > origin_offset) { | 1824 if (target_offset > origin_offset) { |
1819 BuildLoopExitsUntilLoop(loop_analysis()->GetLoopOffsetFor(target_offset)); | 1825 BuildLoopExitsUntilLoop(loop_analysis()->GetLoopOffsetFor(target_offset)); |
1820 } | 1826 } |
1821 } | 1827 } |
1822 | 1828 |
1823 void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) { | 1829 void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) { |
1824 int origin_offset = bytecode_iterator().current_offset(); | 1830 int origin_offset = bytecode_iterator().current_offset(); |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2076 // Phi does not exist yet, introduce one. | 2082 // Phi does not exist yet, introduce one. |
2077 value = NewPhi(inputs, value, control); | 2083 value = NewPhi(inputs, value, control); |
2078 value->ReplaceInput(inputs - 1, other); | 2084 value->ReplaceInput(inputs - 1, other); |
2079 } | 2085 } |
2080 return value; | 2086 return value; |
2081 } | 2087 } |
2082 | 2088 |
2083 } // namespace compiler | 2089 } // namespace compiler |
2084 } // namespace internal | 2090 } // namespace internal |
2085 } // namespace v8 | 2091 } // namespace v8 |
OLD | NEW |