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

Side by Side Diff: runtime/vm/flow_graph_builder.cc

Issue 71703002: Introduce a nesting stack to the flow graph builder. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_builder.h" 5 #include "vm/flow_graph_builder.h"
6 6
7 #include "lib/invocation_mirror.h" 7 #include "lib/invocation_mirror.h"
8 #include "vm/ast_printer.h" 8 #include "vm/ast_printer.h"
9 #include "vm/bit_vector.h" 9 #include "vm/bit_vector.h"
10 #include "vm/class_finalizer.h" 10 #include "vm/class_finalizer.h"
(...skipping 24 matching lines...) Expand all
35 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree."); 35 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree.");
36 DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables."); 36 DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables.");
37 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph."); 37 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph.");
38 DEFINE_FLAG(bool, print_flow_graph_optimized, false, 38 DEFINE_FLAG(bool, print_flow_graph_optimized, false,
39 "Print the IR flow graph when optimizing."); 39 "Print the IR flow graph when optimizing.");
40 DEFINE_FLAG(bool, trace_type_check_elimination, false, 40 DEFINE_FLAG(bool, trace_type_check_elimination, false,
41 "Trace type check elimination at compile time."); 41 "Trace type check elimination at compile time.");
42 DECLARE_FLAG(bool, enable_type_checks); 42 DECLARE_FLAG(bool, enable_type_checks);
43 43
44 44
45 JoinEntryInstr* NestedStatement::BreakTargetFor(SourceLabel* label) {
46 if (label != label_) return NULL;
47 if (break_target_ == NULL) {
48 break_target_ =
49 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
50 }
51 return break_target_;
52 }
53
54
55 JoinEntryInstr* NestedStatement::ContinueTargetFor(SourceLabel* label) {
56 return NULL;
57 }
58
59
60 // A nested statement that can be the target of a continue as well as a
61 // break.
62 class NestedLoop : public NestedStatement {
63 public:
64 NestedLoop(FlowGraphBuilder* owner, SourceLabel* label)
65 : NestedStatement(owner, label), continue_target_(NULL) { }
66
67 JoinEntryInstr* continue_target() const { return continue_target_; }
68
69 virtual JoinEntryInstr* ContinueTargetFor(SourceLabel* label);
70
71 private:
72 JoinEntryInstr* continue_target_;
73 };
74
75
76 JoinEntryInstr* NestedLoop::ContinueTargetFor(SourceLabel* label) {
77 if (label != this->label()) return NULL;
78 if (continue_target_ == NULL) {
79 continue_target_ =
80 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
81 }
82 return continue_target_;
83 }
84
85
86 // A nested switch which can be the target of a break if labeled, and whose
87 // cases can be the targets of continues.
88 class NestedSwitch : public NestedStatement {
89 public:
90 NestedSwitch(FlowGraphBuilder* owner, SwitchNode* node);
91
92 virtual JoinEntryInstr* ContinueTargetFor(SourceLabel* label);
93
94 private:
95 GrowableArray<SourceLabel*> case_labels_;
96 GrowableArray<JoinEntryInstr*> case_targets_;
97 };
98
99
100 NestedSwitch::NestedSwitch(FlowGraphBuilder* owner, SwitchNode* node)
101 : NestedStatement(owner, node->label()),
102 case_labels_(node->body()->length()),
103 case_targets_(node->body()->length()) {
104 SequenceNode* body = node->body();
105 for (intptr_t i = 0; i < body->length(); ++i) {
106 CaseNode* case_node = body->NodeAt(i)->AsCaseNode();
107 if (case_node != NULL) {
108 case_labels_.Add(case_node->label());
109 case_targets_.Add(NULL);
110 }
111 }
112 }
113
114
115 JoinEntryInstr* NestedSwitch::ContinueTargetFor(SourceLabel* label) {
116 // Allocate a join for a case clause that matches the label. This block
117 // is not necessarily targeted by a continue, but we always use a join in
118 // the graph anyway.
119 for (intptr_t i = 0; i < case_labels_.length(); ++i) {
120 if (label != case_labels_[i]) continue;
121 if (case_targets_[i] == NULL) {
122 case_targets_[i] =
123 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
124 }
125 return case_targets_[i];
126 }
127 return NULL;
128 }
129
130
45 FlowGraphBuilder::FlowGraphBuilder(ParsedFunction* parsed_function, 131 FlowGraphBuilder::FlowGraphBuilder(ParsedFunction* parsed_function,
46 const Array& ic_data_array, 132 const Array& ic_data_array,
47 InlineExitCollector* exit_collector, 133 InlineExitCollector* exit_collector,
48 intptr_t osr_id) 134 intptr_t osr_id)
49 : parsed_function_(parsed_function), 135 : parsed_function_(parsed_function),
50 ic_data_array_(ic_data_array), 136 ic_data_array_(ic_data_array),
51 num_copied_params_(parsed_function->num_copied_params()), 137 num_copied_params_(parsed_function->num_copied_params()),
52 // All parameters are copied if any parameter is. 138 // All parameters are copied if any parameter is.
53 num_non_copied_params_((num_copied_params_ == 0) 139 num_non_copied_params_((num_copied_params_ == 0)
54 ? parsed_function->function().num_fixed_parameters() 140 ? parsed_function->function().num_fixed_parameters()
55 : 0), 141 : 0),
56 num_stack_locals_(parsed_function->num_stack_locals()), 142 num_stack_locals_(parsed_function->num_stack_locals()),
57 exit_collector_(exit_collector), 143 exit_collector_(exit_collector),
58 guarded_fields_(new ZoneGrowableArray<const Field*>()), 144 guarded_fields_(new ZoneGrowableArray<const Field*>()),
59 last_used_block_id_(0), // 0 is used for the graph entry. 145 last_used_block_id_(0), // 0 is used for the graph entry.
60 context_level_(0), 146 context_level_(0),
61 try_index_(CatchClauseNode::kInvalidTryIndex), 147 try_index_(CatchClauseNode::kInvalidTryIndex),
62 catch_try_index_(CatchClauseNode::kInvalidTryIndex), 148 catch_try_index_(CatchClauseNode::kInvalidTryIndex),
63 loop_depth_(0), 149 loop_depth_(0),
64 graph_entry_(NULL), 150 graph_entry_(NULL),
65 temp_count_(0), 151 temp_count_(0),
66 args_pushed_(0), 152 args_pushed_(0),
153 nesting_stack_(NULL),
67 osr_id_(osr_id) { } 154 osr_id_(osr_id) { }
68 155
69 156
70 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) { 157 void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) {
71 graph_entry_->AddCatchEntry(entry); 158 graph_entry_->AddCatchEntry(entry);
72 } 159 }
73 160
74 161
75 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) { 162 void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) {
76 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1); 163 ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1);
(...skipping 1483 matching lines...) Expand 10 before | Expand all | Expand 10 after
1560 1647
1561 node->true_branch()->Visit(&for_true); 1648 node->true_branch()->Visit(&for_true);
1562 // The for_false graph fragment will be empty (default graph fragment) if 1649 // The for_false graph fragment will be empty (default graph fragment) if
1563 // we do not call Visit. 1650 // we do not call Visit.
1564 if (node->false_branch() != NULL) node->false_branch()->Visit(&for_false); 1651 if (node->false_branch() != NULL) node->false_branch()->Visit(&for_false);
1565 Join(for_test, for_true, for_false); 1652 Join(for_test, for_true, for_false);
1566 } 1653 }
1567 1654
1568 1655
1569 void EffectGraphVisitor::VisitSwitchNode(SwitchNode* node) { 1656 void EffectGraphVisitor::VisitSwitchNode(SwitchNode* node) {
1657 NestedSwitch nested_switch(owner(), node);
1570 EffectGraphVisitor switch_body(owner()); 1658 EffectGraphVisitor switch_body(owner());
1571 node->body()->Visit(&switch_body); 1659 node->body()->Visit(&switch_body);
1572 Append(switch_body); 1660 Append(switch_body);
1573 if ((node->label() != NULL) && (node->label()->join_for_break() != NULL)) { 1661 if (nested_switch.break_target() != NULL) {
1574 if (is_open()) Goto(node->label()->join_for_break()); 1662 if (is_open()) Goto(nested_switch.break_target());
1575 exit_ = node->label()->join_for_break(); 1663 exit_ = nested_switch.break_target();
1576 } 1664 }
1577 // No continue label allowed.
1578 ASSERT((node->label() == NULL) ||
1579 (node->label()->join_for_continue() == NULL));
1580 } 1665 }
1581 1666
1582 1667
1583 // A case node contains zero or more case expressions, can contain default 1668 // A case node contains zero or more case expressions, can contain default
1584 // and a case statement body. 1669 // and a case statement body.
1585 // Compose fragment as follows: 1670 // Compose fragment as follows:
1586 // - if no case expressions, must have default: 1671 // - if no case expressions, must have default:
1587 // a) target 1672 // a) target
1588 // b) [ case-statements ] 1673 // b) [ case-statements ]
1589 // 1674 //
1590 // - if has 1 or more case statements 1675 // - if has 1 or more case statements
1591 // a) target-0 1676 // a) target-0
1592 // b) [ case-expression-0 ] -> (true-target-0, target-1) 1677 // b) [ case-expression-0 ] -> (true-target-0, target-1)
1593 // c) target-1 1678 // c) target-1
1594 // d) [ case-expression-1 ] -> (true-target-1, exit-target) 1679 // d) [ case-expression-1 ] -> (true-target-1, exit-target)
1595 // e) true-target-0 -> case-statements-join 1680 // e) true-target-0 -> case-statements-join
1596 // f) true-target-1 -> case-statements-join 1681 // f) true-target-1 -> case-statements-join
1597 // g) case-statements-join 1682 // g) case-statements-join
1598 // h) [ case-statements ] -> exit-join 1683 // h) [ case-statements ] -> exit-join
1599 // i) exit-target -> exit-join 1684 // i) exit-target -> exit-join
1600 // j) exit-join 1685 // j) exit-join
1601 // 1686 //
1602 // Note: The specification of switch/case is under discussion and may change 1687 // Note: The specification of switch/case is under discussion and may change
1603 // drastically. 1688 // drastically.
1604 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) { 1689 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) {
1605 const intptr_t len = node->case_expressions()->length(); 1690 const intptr_t len = node->case_expressions()->length();
1606 // Create case statements instructions. 1691 // Create case statements instructions.
1607 EffectGraphVisitor for_case_statements(owner()); 1692 EffectGraphVisitor for_case_statements(owner());
1608 // Compute start of statements fragment. 1693 // Compute the start of the statements fragment.
1609 JoinEntryInstr* statement_start = NULL; 1694 JoinEntryInstr* statement_start = NULL;
1610 if ((node->label() != NULL) && node->label()->is_continue_target()) { 1695 if (node->label() == NULL) {
1611 // Since a labeled jump continue statement occur in a different case node,
1612 // allocate JoinNode here and use it as statement start.
1613 statement_start = node->label()->join_for_continue();
1614 if (statement_start == NULL) {
1615 statement_start = new JoinEntryInstr(owner()->AllocateBlockId(),
1616 owner()->try_index());
1617 node->label()->set_join_for_continue(statement_start);
1618 }
1619 } else {
1620 statement_start = new JoinEntryInstr(owner()->AllocateBlockId(), 1696 statement_start = new JoinEntryInstr(owner()->AllocateBlockId(),
1621 owner()->try_index()); 1697 owner()->try_index());
1698 } else {
1699 // The case nodes are nested inside a SequenceNode that is the body of a
1700 // SwitchNode. The SwitchNode on the nesting stack contains the
1701 // continue labels for all the case clauses.
1702 statement_start =
1703 owner()->nesting_stack()->outer()->ContinueTargetFor(node->label());
1622 } 1704 }
1705 ASSERT(statement_start != NULL);
1623 node->statements()->Visit(&for_case_statements); 1706 node->statements()->Visit(&for_case_statements);
1624 Instruction* statement_exit = 1707 Instruction* statement_exit =
1625 AppendFragment(statement_start, for_case_statements); 1708 AppendFragment(statement_start, for_case_statements);
1626 if (is_open() && (len == 0)) { 1709 if (is_open() && (len == 0)) {
1627 ASSERT(node->contains_default()); 1710 ASSERT(node->contains_default());
1628 // Default only case node. 1711 // Default only case node.
1629 Goto(statement_start); 1712 Goto(statement_start);
1630 exit_ = statement_exit; 1713 exit_ = statement_exit;
1631 return; 1714 return;
1632 } 1715 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1688 // body: <Sequence> } 1771 // body: <Sequence> }
1689 // The fragment is composed as follows: 1772 // The fragment is composed as follows:
1690 // a) loop-join 1773 // a) loop-join
1691 // b) [ test ] -> (body-entry-target, loop-exit-target) 1774 // b) [ test ] -> (body-entry-target, loop-exit-target)
1692 // c) body-entry-target 1775 // c) body-entry-target
1693 // d) [ body ] -> (continue-join) 1776 // d) [ body ] -> (continue-join)
1694 // e) continue-join -> (loop-join) 1777 // e) continue-join -> (loop-join)
1695 // f) loop-exit-target 1778 // f) loop-exit-target
1696 // g) break-join (optional) 1779 // g) break-join (optional)
1697 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { 1780 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) {
1781 NestedLoop nested_loop(owner(), node->label());
1698 owner()->IncrementLoopDepth(); 1782 owner()->IncrementLoopDepth();
1783
1699 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); 1784 TestGraphVisitor for_test(owner(), node->condition()->token_pos());
1700 node->condition()->Visit(&for_test); 1785 node->condition()->Visit(&for_test);
1701 ASSERT(!for_test.is_empty()); // Language spec. 1786 ASSERT(!for_test.is_empty()); // Language spec.
1702 1787
1703 EffectGraphVisitor for_body(owner()); 1788 EffectGraphVisitor for_body(owner());
1704 node->body()->Visit(&for_body); 1789 node->body()->Visit(&for_body);
1705 1790
1706 // Labels are set after body traversal. 1791 // Labels are set after body traversal.
1707 SourceLabel* lbl = node->label(); 1792 JoinEntryInstr* join = nested_loop.continue_target();
1708 ASSERT(lbl != NULL);
1709 JoinEntryInstr* join = lbl->join_for_continue();
1710 if (join != NULL) { 1793 if (join != NULL) {
1711 if (for_body.is_open()) for_body.Goto(join); 1794 if (for_body.is_open()) for_body.Goto(join);
1712 for_body.exit_ = join; 1795 for_body.exit_ = join;
1713 } 1796 }
1714 TieLoop(node->token_pos(), for_test, for_body); 1797 TieLoop(node->token_pos(), for_test, for_body);
1715 join = lbl->join_for_break(); 1798 join = nested_loop.break_target();
1716 if (join != NULL) { 1799 if (join != NULL) {
1717 Goto(join); 1800 Goto(join);
1718 exit_ = join; 1801 exit_ = join;
1719 } 1802 }
1720 owner()->DecrementLoopDepth(); 1803 owner()->DecrementLoopDepth();
1721 } 1804 }
1722 1805
1723 1806
1724 // The fragment is composed as follows: 1807 // The fragment is composed as follows:
1725 // a) body-entry-join 1808 // a) body-entry-join
1726 // b) [ body ] 1809 // b) [ body ]
1727 // c) test-entry (continue-join or body-exit-target) 1810 // c) test-entry (continue-join or body-exit-target)
1728 // d) [ test-entry ] -> (back-target, loop-exit-target) 1811 // d) [ test-entry ] -> (back-target, loop-exit-target)
1729 // e) back-target -> (body-entry-join) 1812 // e) back-target -> (body-entry-join)
1730 // f) loop-exit-target 1813 // f) loop-exit-target
1731 // g) break-join 1814 // g) break-join
1732 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { 1815 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) {
1816 NestedLoop nested_loop(owner(), node->label());
1733 owner()->IncrementLoopDepth(); 1817 owner()->IncrementLoopDepth();
1734 // Traverse body first in order to generate continue and break labels. 1818
1819 // Traverse the body first in order to generate continue and break labels.
1735 EffectGraphVisitor for_body(owner()); 1820 EffectGraphVisitor for_body(owner());
1736 node->body()->Visit(&for_body); 1821 node->body()->Visit(&for_body);
1737 1822
1738 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); 1823 TestGraphVisitor for_test(owner(), node->condition()->token_pos());
1739 node->condition()->Visit(&for_test); 1824 node->condition()->Visit(&for_test);
1740 ASSERT(is_open()); 1825 ASSERT(is_open());
1741 1826
1742 // Tie do-while loop (test is after the body). 1827 // Tie do-while loop (test is after the body).
1743 JoinEntryInstr* body_entry_join = 1828 JoinEntryInstr* body_entry_join =
1744 new JoinEntryInstr(owner()->AllocateBlockId(), 1829 new JoinEntryInstr(owner()->AllocateBlockId(),
1745 owner()->try_index()); 1830 owner()->try_index());
1746 Goto(body_entry_join); 1831 Goto(body_entry_join);
1747 Instruction* body_exit = AppendFragment(body_entry_join, for_body); 1832 Instruction* body_exit = AppendFragment(body_entry_join, for_body);
1748 1833
1749 JoinEntryInstr* join = node->label()->join_for_continue(); 1834 JoinEntryInstr* join = nested_loop.continue_target();
1750 if ((body_exit != NULL) || (join != NULL)) { 1835 if ((body_exit != NULL) || (join != NULL)) {
1751 if (join == NULL) { 1836 if (join == NULL) {
1752 join = new JoinEntryInstr(owner()->AllocateBlockId(), 1837 join = new JoinEntryInstr(owner()->AllocateBlockId(),
1753 owner()->try_index()); 1838 owner()->try_index());
1754 } 1839 }
1755 CheckStackOverflowInstr* check = 1840 CheckStackOverflowInstr* check =
1756 new CheckStackOverflowInstr(node->token_pos(), owner()->loop_depth()); 1841 new CheckStackOverflowInstr(node->token_pos(), owner()->loop_depth());
1757 join->LinkTo(check); 1842 join->LinkTo(check);
1758 check->LinkTo(for_test.entry()); 1843 check->LinkTo(for_test.entry());
1759 if (body_exit != NULL) { 1844 if (body_exit != NULL) {
1760 body_exit->Goto(join); 1845 body_exit->Goto(join);
1761 } 1846 }
1762 } 1847 }
1763 1848
1764 for_test.IfTrueGoto(body_entry_join); 1849 for_test.IfTrueGoto(body_entry_join);
1765 join = node->label()->join_for_break(); 1850 join = nested_loop.break_target();
1766 if (join == NULL) { 1851 if (join == NULL) {
1767 exit_ = for_test.CreateFalseSuccessor(); 1852 exit_ = for_test.CreateFalseSuccessor();
1768 } else { 1853 } else {
1769 for_test.IfFalseGoto(join); 1854 for_test.IfFalseGoto(join);
1770 exit_ = join; 1855 exit_ = join;
1771 } 1856 }
1772 owner()->DecrementLoopDepth(); 1857 owner()->DecrementLoopDepth();
1773 } 1858 }
1774 1859
1775 1860
1776 // A ForNode can contain break and continue jumps. 'break' joins to 1861 // A ForNode can contain break and continue jumps. 'break' joins to
1777 // ForNode exit, 'continue' joins at increment entry. The fragment is composed 1862 // ForNode exit, 'continue' joins at increment entry. The fragment is composed
1778 // as follows: 1863 // as follows:
1779 // a) [ initializer ] 1864 // a) [ initializer ]
1780 // b) loop-join 1865 // b) loop-join
1781 // c) [ test ] -> (body-entry-target, loop-exit-target) 1866 // c) [ test ] -> (body-entry-target, loop-exit-target)
1782 // d) body-entry-target 1867 // d) body-entry-target
1783 // e) [ body ] 1868 // e) [ body ]
1784 // f) continue-join (optional) 1869 // f) continue-join (optional)
1785 // g) [ increment ] -> (loop-join) 1870 // g) [ increment ] -> (loop-join)
1786 // h) loop-exit-target 1871 // h) loop-exit-target
1787 // i) break-join 1872 // i) break-join
1788 void EffectGraphVisitor::VisitForNode(ForNode* node) { 1873 void EffectGraphVisitor::VisitForNode(ForNode* node) {
1789 EffectGraphVisitor for_initializer(owner()); 1874 EffectGraphVisitor for_initializer(owner());
1790 node->initializer()->Visit(&for_initializer); 1875 node->initializer()->Visit(&for_initializer);
1791 Append(for_initializer); 1876 Append(for_initializer);
1792 ASSERT(is_open()); 1877 ASSERT(is_open());
1793 1878
1879 NestedLoop nested_loop(owner(), node->label());
1794 owner()->IncrementLoopDepth(); 1880 owner()->IncrementLoopDepth();
1795 // Compose body to set any jump labels. 1881 // Compose body to set any jump labels.
1796 EffectGraphVisitor for_body(owner()); 1882 EffectGraphVisitor for_body(owner());
1797 node->body()->Visit(&for_body); 1883 node->body()->Visit(&for_body);
1798 1884
1799 EffectGraphVisitor for_increment(owner()); 1885 EffectGraphVisitor for_increment(owner());
1800 node->increment()->Visit(&for_increment); 1886 node->increment()->Visit(&for_increment);
1801 1887
1802 // Join the loop body and increment and then tie the loop. 1888 // Join the loop body and increment and then tie the loop.
1803 JoinEntryInstr* continue_join = node->label()->join_for_continue(); 1889 JoinEntryInstr* continue_join = nested_loop.continue_target();
1804 if ((continue_join != NULL) || for_body.is_open()) { 1890 if ((continue_join != NULL) || for_body.is_open()) {
1805 JoinEntryInstr* loop_entry = 1891 JoinEntryInstr* loop_entry =
1806 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); 1892 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index());
1807 if (continue_join != NULL) { 1893 if (continue_join != NULL) {
1808 if (for_body.is_open()) for_body.Goto(continue_join); 1894 if (for_body.is_open()) for_body.Goto(continue_join);
1809 Instruction* current = AppendFragment(continue_join, for_increment); 1895 Instruction* current = AppendFragment(continue_join, for_increment);
1810 current->Goto(loop_entry); 1896 current->Goto(loop_entry);
1811 } else { 1897 } else {
1812 for_body.Append(for_increment); 1898 for_body.Append(for_increment);
1813 for_body.Goto(loop_entry); 1899 for_body.Goto(loop_entry);
1814 } 1900 }
1815 Goto(loop_entry); 1901 Goto(loop_entry);
1816 exit_ = loop_entry; 1902 exit_ = loop_entry;
1817 AddInstruction( 1903 AddInstruction(
1818 new CheckStackOverflowInstr(node->token_pos(), owner()->loop_depth())); 1904 new CheckStackOverflowInstr(node->token_pos(), owner()->loop_depth()));
1819 } 1905 }
1820 1906
1821 if (node->condition() == NULL) { 1907 if (node->condition() == NULL) {
1822 // Endless loop, no test. 1908 // Endless loop, no test.
1823 Append(for_body); 1909 Append(for_body);
1824 exit_ = node->label()->join_for_break(); // May be NULL. 1910 exit_ = nested_loop.break_target(); // May be NULL.
1825 } else { 1911 } else {
1826 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); 1912 TestGraphVisitor for_test(owner(), node->condition()->token_pos());
1827 node->condition()->Visit(&for_test); 1913 node->condition()->Visit(&for_test);
1828 Append(for_test); 1914 Append(for_test);
1829 1915
1830 BlockEntryInstr* body_entry = for_test.CreateTrueSuccessor(); 1916 BlockEntryInstr* body_entry = for_test.CreateTrueSuccessor();
1831 AppendFragment(body_entry, for_body); 1917 AppendFragment(body_entry, for_body);
1832 1918
1833 if (node->label()->join_for_break() == NULL) { 1919 if (nested_loop.break_target() == NULL) {
1834 exit_ = for_test.CreateFalseSuccessor(); 1920 exit_ = for_test.CreateFalseSuccessor();
1835 } else { 1921 } else {
1836 for_test.IfFalseGoto(node->label()->join_for_break()); 1922 for_test.IfFalseGoto(nested_loop.break_target());
1837 exit_ = node->label()->join_for_break(); 1923 exit_ = nested_loop.break_target();
1838 } 1924 }
1839 } 1925 }
1840 owner()->DecrementLoopDepth(); 1926 owner()->DecrementLoopDepth();
1841 } 1927 }
1842 1928
1843 1929
1844 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { 1930 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) {
1845 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { 1931 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) {
1846 EffectGraphVisitor for_effect(owner()); 1932 EffectGraphVisitor for_effect(owner());
1847 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); 1933 node->InlinedFinallyNodeAt(i)->Visit(&for_effect);
(...skipping 23 matching lines...) Expand all
1871 } 1957 }
1872 } 1958 }
1873 ASSERT(target_context_level >= 0); 1959 ASSERT(target_context_level >= 0);
1874 intptr_t current_context_level = owner()->context_level(); 1960 intptr_t current_context_level = owner()->context_level();
1875 ASSERT(current_context_level >= target_context_level); 1961 ASSERT(current_context_level >= target_context_level);
1876 while (current_context_level-- > target_context_level) { 1962 while (current_context_level-- > target_context_level) {
1877 UnchainContext(); 1963 UnchainContext();
1878 } 1964 }
1879 1965
1880 JoinEntryInstr* jump_target = NULL; 1966 JoinEntryInstr* jump_target = NULL;
1881 if (node->kind() == Token::kBREAK) { 1967 if (node->kind() == Token::kBREAK) {
Florian Schneider 2013/11/13 17:42:58 For less duplicated code maybe move this condition
Kevin Millikin (Google) 2013/11/13 17:47:22 That sounds good to me. I'll do it.
1882 if (node->label()->join_for_break() == NULL) { 1968 NestedStatement* current = owner()->nesting_stack();
1883 node->label()->set_join_for_break( 1969 while (current != NULL) {
1884 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index())); 1970 jump_target = current->BreakTargetFor(node->label());
1971 if (jump_target != NULL) break;
1972 current = current->outer();
1885 } 1973 }
1886 jump_target = node->label()->join_for_break();
1887 } else { 1974 } else {
1888 if (node->label()->join_for_continue() == NULL) { 1975 NestedStatement* current = owner()->nesting_stack();
1889 node->label()->set_join_for_continue( 1976 while (current != NULL) {
1890 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index())); 1977 jump_target = current->ContinueTargetFor(node->label());
1978 if (jump_target != NULL) break;
1979 current = current->outer();
1891 } 1980 }
1892 jump_target = node->label()->join_for_continue();
1893 } 1981 }
1982 ASSERT(jump_target != NULL);
1894 Goto(jump_target); 1983 Goto(jump_target);
1895 } 1984 }
1896 1985
1897 1986
1898 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { 1987 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) {
1899 UNREACHABLE(); 1988 UNREACHABLE();
1900 } 1989 }
1901 1990
1902 1991
1903 intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const { 1992 intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const {
(...skipping 1475 matching lines...) Expand 10 before | Expand all | Expand 10 after
3379 3468
3380 3469
3381 // <Statement> ::= Sequence { scope: LocalScope 3470 // <Statement> ::= Sequence { scope: LocalScope
3382 // nodes: <Statement>* 3471 // nodes: <Statement>*
3383 // label: SourceLabel } 3472 // label: SourceLabel }
3384 void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) { 3473 void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
3385 LocalScope* scope = node->scope(); 3474 LocalScope* scope = node->scope();
3386 const intptr_t num_context_variables = 3475 const intptr_t num_context_variables =
3387 (scope != NULL) ? scope->num_context_variables() : 0; 3476 (scope != NULL) ? scope->num_context_variables() : 0;
3388 int previous_context_level = owner()->context_level(); 3477 int previous_context_level = owner()->context_level();
3478 // The outermost function sequence cannot contain a label.
3479 ASSERT((node->label() == NULL) ||
3480 (node != owner()->parsed_function()->node_sequence()));
3481 NestedStatement nested_block(owner(), node->label());
3482
3389 if (num_context_variables > 0) { 3483 if (num_context_variables > 0) {
3390 // The loop local scope declares variables that are captured. 3484 // The loop local scope declares variables that are captured.
3391 // Allocate and chain a new context. 3485 // Allocate and chain a new context.
3392 // Allocate context computation (uses current CTX) 3486 // Allocate context computation (uses current CTX)
3393 Value* allocated_context = 3487 Value* allocated_context =
3394 Bind(new AllocateContextInstr(node->token_pos(), 3488 Bind(new AllocateContextInstr(node->token_pos(),
3395 num_context_variables)); 3489 num_context_variables));
3396 { LocalVariable* tmp_var = EnterTempLocalScope(allocated_context); 3490 { LocalVariable* tmp_var = EnterTempLocalScope(allocated_context);
3397 // If this node_sequence is the body of the function being compiled, and 3491 // If this node_sequence is the body of the function being compiled, and
3398 // if this function allocates context variables, but none of its enclosing 3492 // if this function allocates context variables, but none of its enclosing
3399 // functions do, the context on entry is not linked as parent of the 3493 // functions do, the context on entry is not linked as parent of the
3400 // allocated context but saved on entry and restored on exit as to prevent 3494 // allocated context but saved on entry and restored on exit as to prevent
3401 // memory leaks. 3495 // memory leaks.
3402 // In this case, the parser pre-allocates a variable to save the context. 3496 // In this case, the parser pre-allocates a variable to save the context.
3403 if (MustSaveRestoreContext(node)) { 3497 if (MustSaveRestoreContext(node)) {
3404 BuildSaveContext( 3498 BuildSaveContext(
3405 *owner()->parsed_function()->saved_entry_context_var()); 3499 *owner()->parsed_function()->saved_entry_context_var());
3406 Value* null_context = Bind(new ConstantInstr(Object::ZoneHandle())); 3500 Value* null_context = Bind(new ConstantInstr(Object::ZoneHandle()));
3407 AddInstruction(new StoreContextInstr(null_context)); 3501 AddInstruction(new StoreContextInstr(null_context));
3408 } 3502 }
3409 Value* current_context = Bind(new CurrentContextInstr()); 3503 Value* current_context = Bind(new CurrentContextInstr());
3410 Value* tmp_val = Bind(new LoadLocalInstr(*tmp_var)); 3504 Value* tmp_val = Bind(new LoadLocalInstr(*tmp_var));
3411 Do(new StoreVMFieldInstr(tmp_val, 3505 Do(new StoreVMFieldInstr(tmp_val,
3412 Context::parent_offset(), 3506 Context::parent_offset(),
3413 current_context, 3507 current_context,
3414 Type::ZoneHandle())); 3508 Type::ZoneHandle()));
3415 AddInstruction( 3509 AddInstruction(
3416 new StoreContextInstr(Bind(ExitTempLocalScope(tmp_var)))); 3510 new StoreContextInstr(Bind(ExitTempLocalScope(tmp_var))));
3417 } 3511 }
3512
3418 owner()->set_context_level(scope->context_level()); 3513 owner()->set_context_level(scope->context_level());
3419 3514
3420 // If this node_sequence is the body of the function being compiled, copy 3515 // If this node_sequence is the body of the function being compiled, copy
3421 // the captured parameters from the frame into the context. 3516 // the captured parameters from the frame into the context.
3422 if (node == owner()->parsed_function()->node_sequence()) { 3517 if (node == owner()->parsed_function()->node_sequence()) {
3423 ASSERT(scope->context_level() == 1); 3518 ASSERT(scope->context_level() == 1);
3424 const Function& function = owner()->parsed_function()->function(); 3519 const Function& function = owner()->parsed_function()->function();
3425 const int num_params = function.NumParameters(); 3520 const int num_params = function.NumParameters();
3426 int param_frame_index = (num_params == function.num_fixed_parameters()) ? 3521 int param_frame_index = (num_params == function.num_fixed_parameters()) ?
3427 (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp; 3522 (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
3502 if (is_open()) { 3597 if (is_open()) {
3503 if (MustSaveRestoreContext(node)) { 3598 if (MustSaveRestoreContext(node)) {
3504 ASSERT(num_context_variables > 0); 3599 ASSERT(num_context_variables > 0);
3505 BuildRestoreContext( 3600 BuildRestoreContext(
3506 *owner()->parsed_function()->saved_entry_context_var()); 3601 *owner()->parsed_function()->saved_entry_context_var());
3507 } else if (num_context_variables > 0) { 3602 } else if (num_context_variables > 0) {
3508 UnchainContext(); 3603 UnchainContext();
3509 } 3604 }
3510 } 3605 }
3511 3606
3512 // No continue on sequence allowed.
3513 ASSERT((node->label() == NULL) ||
3514 (node->label()->join_for_continue() == NULL));
3515 // If this node sequence is labeled, a break out of the sequence will have 3607 // If this node sequence is labeled, a break out of the sequence will have
3516 // taken care of unchaining the context. 3608 // taken care of unchaining the context.
3517 if ((node->label() != NULL) && 3609 if (nested_block.break_target() != NULL) {
3518 (node->label()->join_for_break() != NULL)) { 3610 if (is_open()) Goto(nested_block.break_target());
3519 if (is_open()) Goto(node->label()->join_for_break()); 3611 exit_ = nested_block.break_target();
3520 exit_ = node->label()->join_for_break();
3521 } 3612 }
3522 3613
3523 // The outermost function sequence cannot contain a label.
3524 ASSERT((node->label() == NULL) ||
3525 (node != owner()->parsed_function()->node_sequence()));
3526 owner()->set_context_level(previous_context_level); 3614 owner()->set_context_level(previous_context_level);
3527 } 3615 }
3528 3616
3529 3617
3530 void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) { 3618 void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) {
3531 InlineBailout("EffectGraphVisitor::VisitCatchClauseNode (exception)"); 3619 InlineBailout("EffectGraphVisitor::VisitCatchClauseNode (exception)");
3532 // Restores CTX from local variable ':saved_context'. 3620 // Restores CTX from local variable ':saved_context'.
3533 BuildRestoreContext(node->context_var()); 3621 BuildRestoreContext(node->context_var());
3534 3622
3535 EffectGraphVisitor for_catch(owner()); 3623 EffectGraphVisitor for_catch(owner());
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
3886 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 3974 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
3887 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 3975 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
3888 OS::SNPrint(chars, len, kFormat, function_name, reason); 3976 OS::SNPrint(chars, len, kFormat, function_name, reason);
3889 const Error& error = Error::Handle( 3977 const Error& error = Error::Handle(
3890 LanguageError::New(String::Handle(String::New(chars)))); 3978 LanguageError::New(String::Handle(String::New(chars))));
3891 Isolate::Current()->long_jump_base()->Jump(1, error); 3979 Isolate::Current()->long_jump_base()->Jump(1, error);
3892 } 3980 }
3893 3981
3894 3982
3895 } // namespace dart 3983 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698