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/compiler/bytecode-branch-analysis.h" | 7 #include "src/compiler/bytecode-branch-analysis.h" |
8 #include "src/compiler/linkage.h" | 8 #include "src/compiler/linkage.h" |
9 #include "src/compiler/operator-properties.h" | 9 #include "src/compiler/operator-properties.h" |
10 #include "src/interpreter/bytecodes.h" | 10 #include "src/interpreter/bytecodes.h" |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 jsgraph_(jsgraph), | 471 jsgraph_(jsgraph), |
472 bytecode_array_(handle(info()->shared_info()->bytecode_array())), | 472 bytecode_array_(handle(info()->shared_info()->bytecode_array())), |
473 exception_handler_table_( | 473 exception_handler_table_( |
474 handle(HandlerTable::cast(bytecode_array()->handler_table()))), | 474 handle(HandlerTable::cast(bytecode_array()->handler_table()))), |
475 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( | 475 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( |
476 FrameStateType::kInterpretedFunction, | 476 FrameStateType::kInterpretedFunction, |
477 bytecode_array()->parameter_count(), | 477 bytecode_array()->parameter_count(), |
478 bytecode_array()->register_count(), info()->shared_info(), | 478 bytecode_array()->register_count(), info()->shared_info(), |
479 CALL_MAINTAINS_NATIVE_CONTEXT)), | 479 CALL_MAINTAINS_NATIVE_CONTEXT)), |
480 merge_environments_(local_zone), | 480 merge_environments_(local_zone), |
481 loop_header_environments_(local_zone), | |
482 exception_handlers_(local_zone), | 481 exception_handlers_(local_zone), |
483 current_exception_handler_(0), | 482 current_exception_handler_(0), |
484 input_buffer_size_(0), | 483 input_buffer_size_(0), |
485 input_buffer_(nullptr), | 484 input_buffer_(nullptr), |
486 exit_controls_(local_zone) {} | 485 exit_controls_(local_zone) {} |
487 | 486 |
488 Node* BytecodeGraphBuilder::GetNewTarget() { | 487 Node* BytecodeGraphBuilder::GetNewTarget() { |
489 if (!new_target_.is_set()) { | 488 if (!new_target_.is_set()) { |
490 int params = bytecode_array()->parameter_count(); | 489 int params = bytecode_array()->parameter_count(); |
491 int index = Linkage::GetJSCallNewTargetParamIndex(params); | 490 int index = Linkage::GetJSCallNewTargetParamIndex(params); |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 void BytecodeGraphBuilder::VisitBytecodes() { | 610 void BytecodeGraphBuilder::VisitBytecodes() { |
612 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); | 611 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); |
613 analysis.Analyze(); | 612 analysis.Analyze(); |
614 set_branch_analysis(&analysis); | 613 set_branch_analysis(&analysis); |
615 interpreter::BytecodeArrayIterator iterator(bytecode_array()); | 614 interpreter::BytecodeArrayIterator iterator(bytecode_array()); |
616 set_bytecode_iterator(&iterator); | 615 set_bytecode_iterator(&iterator); |
617 while (!iterator.done()) { | 616 while (!iterator.done()) { |
618 int current_offset = iterator.current_offset(); | 617 int current_offset = iterator.current_offset(); |
619 if (analysis.is_reachable(current_offset)) { | 618 if (analysis.is_reachable(current_offset)) { |
620 EnterAndExitExceptionHandlers(current_offset); | 619 EnterAndExitExceptionHandlers(current_offset); |
621 MergeEnvironmentsOfForwardBranches(current_offset); | 620 SwitchToMergeEnvironment(current_offset); |
622 BuildLoopHeaderForBackwardBranches(current_offset); | 621 BuildLoopHeaderEnvironment(current_offset); |
623 | 622 |
624 switch (iterator.current_bytecode()) { | 623 switch (iterator.current_bytecode()) { |
625 #define BYTECODE_CASE(name, ...) \ | 624 #define BYTECODE_CASE(name, ...) \ |
626 case interpreter::Bytecode::k##name: \ | 625 case interpreter::Bytecode::k##name: \ |
627 Visit##name(); \ | 626 Visit##name(); \ |
628 break; | 627 break; |
629 BYTECODE_LIST(BYTECODE_CASE) | 628 BYTECODE_LIST(BYTECODE_CASE) |
630 #undef BYTECODE_CODE | 629 #undef BYTECODE_CODE |
631 } | 630 } |
632 } | 631 } |
(...skipping 962 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1595 void BytecodeGraphBuilder::VisitForInNextWide() { BuildForInNext(); } | 1594 void BytecodeGraphBuilder::VisitForInNextWide() { BuildForInNext(); } |
1596 | 1595 |
1597 void BytecodeGraphBuilder::VisitForInStep() { | 1596 void BytecodeGraphBuilder::VisitForInStep() { |
1598 FrameStateBeforeAndAfter states(this); | 1597 FrameStateBeforeAndAfter states(this); |
1599 Node* index = | 1598 Node* index = |
1600 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); | 1599 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); |
1601 index = NewNode(javascript()->ForInStep(), index); | 1600 index = NewNode(javascript()->ForInStep(), index); |
1602 environment()->BindAccumulator(index, &states); | 1601 environment()->BindAccumulator(index, &states); |
1603 } | 1602 } |
1604 | 1603 |
1605 | 1604 void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) { |
1606 void BytecodeGraphBuilder::MergeEnvironmentsOfBackwardBranches( | 1605 if (merge_environments_[current_offset] != nullptr) { |
1607 int source_offset, int target_offset) { | 1606 if (environment() != nullptr) { |
1608 DCHECK_GE(source_offset, target_offset); | 1607 merge_environments_[current_offset]->Merge(environment()); |
1609 const ZoneVector<int>* branch_sites = | |
1610 branch_analysis()->BackwardBranchesTargetting(target_offset); | |
1611 if (branch_sites->back() == source_offset) { | |
1612 // The set of back branches is complete, merge them. | |
1613 DCHECK_GE(branch_sites->at(0), target_offset); | |
1614 Environment* merged = merge_environments_[branch_sites->at(0)]; | |
1615 for (size_t i = 1; i < branch_sites->size(); i++) { | |
1616 DCHECK_GE(branch_sites->at(i), target_offset); | |
1617 merged->Merge(merge_environments_[branch_sites->at(i)]); | |
1618 } | 1608 } |
1619 // And now merge with loop header environment created when loop | 1609 set_environment(merge_environments_[current_offset]); |
1620 // header was visited. | |
1621 loop_header_environments_[target_offset]->Merge(merged); | |
1622 } | 1610 } |
1623 } | 1611 } |
1624 | 1612 |
1625 | 1613 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { |
1626 void BytecodeGraphBuilder::MergeEnvironmentsOfForwardBranches( | 1614 if (branch_analysis()->backward_branches_target(current_offset)) { |
1627 int source_offset) { | 1615 // Add loop header and store a copy so we can connect merged back |
1628 if (branch_analysis()->forward_branches_target(source_offset)) { | 1616 // edge inputs to the loop header. |
1629 // Merge environments of branches that reach this bytecode. | 1617 merge_environments_[current_offset] = environment()->CopyForLoop(); |
1630 auto branch_sites = | |
1631 branch_analysis()->ForwardBranchesTargetting(source_offset); | |
1632 DCHECK_LT(branch_sites->at(0), source_offset); | |
1633 Environment* merged = merge_environments_[branch_sites->at(0)]; | |
1634 for (size_t i = 1; i < branch_sites->size(); i++) { | |
1635 DCHECK_LT(branch_sites->at(i), source_offset); | |
1636 merged->Merge(merge_environments_[branch_sites->at(i)]); | |
1637 } | |
1638 if (environment()) { | |
1639 merged->Merge(environment()); | |
1640 } | |
1641 set_environment(merged); | |
1642 } | 1618 } |
1643 } | 1619 } |
1644 | 1620 |
1645 | 1621 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { |
1646 void BytecodeGraphBuilder::BuildLoopHeaderForBackwardBranches( | 1622 if (merge_environments_[target_offset] == nullptr) { |
1647 int source_offset) { | 1623 // Append merge nodes to the environment. We may merge here with another |
1648 if (branch_analysis()->backward_branches_target(source_offset)) { | 1624 // environment. So add a place holder for merge nodes. We may add redundant |
1649 // Add loop header and store a copy so we can connect merged back | 1625 // but will be eliminated in a later pass. |
1650 // edge inputs to the loop header. | 1626 // TODO(mstarzinger): Be smarter about this! |
1651 loop_header_environments_[source_offset] = environment()->CopyForLoop(); | 1627 NewMerge(); |
1652 } | 1628 merge_environments_[target_offset] = environment(); |
1653 } | 1629 } else { |
1654 | 1630 merge_environments_[target_offset]->Merge(environment()); |
1655 | |
1656 void BytecodeGraphBuilder::BuildJump(int source_offset, int target_offset) { | |
1657 DCHECK_NULL(merge_environments_[source_offset]); | |
1658 // Append merge nodes to the environment. We may merge here with another | |
1659 // environment. So add a place holder for merge nodes. We may add redundant | |
1660 // but will be eliminated in a later pass. | |
1661 // TODO(mstarzinger): This can be simplified by propagating environment | |
1662 // forward along the direction of the dataflow. | |
1663 NewMerge(); | |
1664 merge_environments_[source_offset] = environment(); | |
1665 if (source_offset >= target_offset) { | |
1666 MergeEnvironmentsOfBackwardBranches(source_offset, target_offset); | |
1667 } | 1631 } |
1668 set_environment(nullptr); | 1632 set_environment(nullptr); |
1669 } | 1633 } |
1670 | 1634 |
1671 | 1635 |
1672 void BytecodeGraphBuilder::BuildJump() { | 1636 void BytecodeGraphBuilder::BuildJump() { |
1673 int source_offset = bytecode_iterator().current_offset(); | 1637 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); |
1674 int target_offset = bytecode_iterator().GetJumpTargetOffset(); | |
1675 BuildJump(source_offset, target_offset); | |
1676 } | 1638 } |
1677 | 1639 |
1678 | 1640 |
1679 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { | 1641 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { |
1680 int source_offset = bytecode_iterator().current_offset(); | |
1681 NewBranch(condition); | 1642 NewBranch(condition); |
1682 Environment* if_false_environment = environment()->CopyForConditional(); | 1643 Environment* if_false_environment = environment()->CopyForConditional(); |
1683 NewIfTrue(); | 1644 NewIfTrue(); |
1684 BuildJump(source_offset, bytecode_iterator().GetJumpTargetOffset()); | 1645 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); |
1685 set_environment(if_false_environment); | 1646 set_environment(if_false_environment); |
1686 NewIfFalse(); | 1647 NewIfFalse(); |
1687 } | 1648 } |
1688 | 1649 |
1689 | 1650 |
1690 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) { | 1651 void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) { |
1691 Node* accumulator = environment()->LookupAccumulator(); | 1652 Node* accumulator = environment()->LookupAccumulator(); |
1692 Node* condition = | 1653 Node* condition = |
1693 NewNode(javascript()->StrictEqual(), accumulator, comperand); | 1654 NewNode(javascript()->StrictEqual(), accumulator, comperand); |
1694 BuildConditionalJump(condition); | 1655 BuildConditionalJump(condition); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1790 // Update the current control dependency for control-producing nodes. | 1751 // Update the current control dependency for control-producing nodes. |
1791 if (NodeProperties::IsControl(result)) { | 1752 if (NodeProperties::IsControl(result)) { |
1792 environment()->UpdateControlDependency(result); | 1753 environment()->UpdateControlDependency(result); |
1793 } | 1754 } |
1794 // Update the current effect dependency for effect-producing nodes. | 1755 // Update the current effect dependency for effect-producing nodes. |
1795 if (result->op()->EffectOutputCount() > 0) { | 1756 if (result->op()->EffectOutputCount() > 0) { |
1796 environment()->UpdateEffectDependency(result); | 1757 environment()->UpdateEffectDependency(result); |
1797 } | 1758 } |
1798 // Add implicit exception continuation for throwing nodes. | 1759 // Add implicit exception continuation for throwing nodes. |
1799 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { | 1760 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { |
1800 int throw_offset = bytecode_iterator().current_offset(); | |
1801 int handler_offset = exception_handlers_.top().handler_offset_; | 1761 int handler_offset = exception_handlers_.top().handler_offset_; |
1802 // TODO(mstarzinger): Thread through correct prediction! | 1762 // TODO(mstarzinger): Thread through correct prediction! |
1803 IfExceptionHint hint = IfExceptionHint::kLocallyCaught; | 1763 IfExceptionHint hint = IfExceptionHint::kLocallyCaught; |
1804 // TODO(mstarzinger): For now we mutate the branch analysis result and | |
1805 // add the artificial control flow from throw-site to handler-entry. | |
1806 // This can be simplified by pushing environment forward along the | |
1807 // direction of the data-flow. | |
1808 branch_analysis_->AddExceptionalBranch(throw_offset, handler_offset); | |
1809 Environment* success_env = environment()->CopyForConditional(); | 1764 Environment* success_env = environment()->CopyForConditional(); |
1810 const Operator* op = common()->IfException(hint); | 1765 const Operator* op = common()->IfException(hint); |
1811 Node* effect = environment()->GetEffectDependency(); | 1766 Node* effect = environment()->GetEffectDependency(); |
1812 Node* on_exception = graph()->NewNode(op, effect, result); | 1767 Node* on_exception = graph()->NewNode(op, effect, result); |
1813 environment()->UpdateControlDependency(on_exception); | 1768 environment()->UpdateControlDependency(on_exception); |
1814 environment()->UpdateEffectDependency(on_exception); | 1769 environment()->UpdateEffectDependency(on_exception); |
1815 environment()->BindAccumulator(on_exception); | 1770 environment()->BindAccumulator(on_exception); |
1816 BuildJump(throw_offset, handler_offset); | 1771 MergeIntoSuccessorEnvironment(handler_offset); |
1817 set_environment(success_env); | 1772 set_environment(success_env); |
1818 } | 1773 } |
1819 // Add implicit success continuation for throwing nodes. | 1774 // Add implicit success continuation for throwing nodes. |
1820 if (!result->op()->HasProperty(Operator::kNoThrow)) { | 1775 if (!result->op()->HasProperty(Operator::kNoThrow)) { |
1821 const Operator* if_success = common()->IfSuccess(); | 1776 const Operator* if_success = common()->IfSuccess(); |
1822 Node* on_success = graph()->NewNode(if_success, result); | 1777 Node* on_success = graph()->NewNode(if_success, result); |
1823 environment()->UpdateControlDependency(on_success); | 1778 environment()->UpdateControlDependency(on_success); |
1824 } | 1779 } |
1825 } | 1780 } |
1826 } | 1781 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1907 | 1862 |
1908 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { | 1863 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { |
1909 if (environment()->IsMarkedAsUnreachable()) return; | 1864 if (environment()->IsMarkedAsUnreachable()) return; |
1910 environment()->MarkAsUnreachable(); | 1865 environment()->MarkAsUnreachable(); |
1911 exit_controls_.push_back(exit); | 1866 exit_controls_.push_back(exit); |
1912 } | 1867 } |
1913 | 1868 |
1914 } // namespace compiler | 1869 } // namespace compiler |
1915 } // namespace internal | 1870 } // namespace internal |
1916 } // namespace v8 | 1871 } // namespace v8 |
OLD | NEW |