OLD | NEW |
---|---|
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 Loading... | |
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 // Base class for a stack of enclosing statements of interest (e.g., | |
46 // blocks (breakable) and loops (continuable)). | |
47 class NestedStatement : public ValueObject { | |
48 public: | |
49 NestedStatement(FlowGraphBuilder* owner, const SourceLabel* label) | |
Florian Schneider
2013/11/19 10:37:05
Since only subclasses of NestedStatement exist (Ne
Kevin Millikin (Google)
2013/11/19 11:36:54
OK.
| |
50 : owner_(owner), | |
51 label_(label), | |
52 outer_(owner->nesting_stack_), | |
53 break_target_(NULL) { | |
54 // Push on the owner's nesting stack. | |
55 owner->nesting_stack_ = this; | |
56 } | |
57 | |
58 virtual ~NestedStatement() { | |
59 // Pop from the owner's nesting stack. | |
60 ASSERT(owner_->nesting_stack_ == this); | |
61 owner_->nesting_stack_ = outer_; | |
62 } | |
63 | |
64 FlowGraphBuilder* owner() const { return owner_; } | |
65 const SourceLabel* label() const { return label_; } | |
66 NestedStatement* outer() const { return outer_; } | |
67 JoinEntryInstr* break_target() const { return break_target_; } | |
68 | |
69 virtual intptr_t ContextLevel() const; | |
70 | |
71 virtual JoinEntryInstr* BreakTargetFor(SourceLabel* label); | |
72 virtual JoinEntryInstr* ContinueTargetFor(SourceLabel* label); | |
73 | |
74 private: | |
75 FlowGraphBuilder* owner_; | |
76 const SourceLabel* label_; | |
77 NestedStatement* outer_; | |
78 | |
79 JoinEntryInstr* break_target_; | |
80 }; | |
81 | |
82 | |
83 intptr_t NestedStatement::ContextLevel() const { | |
84 // Context level is determined by the innermost nested statement having one. | |
85 return (outer() == NULL) ? 0 : outer()->ContextLevel(); | |
86 } | |
87 | |
88 | |
89 intptr_t FlowGraphBuilder::context_level() const { | |
90 return (nesting_stack() == NULL) ? 0 : nesting_stack()->ContextLevel(); | |
91 } | |
92 | |
93 | |
45 JoinEntryInstr* NestedStatement::BreakTargetFor(SourceLabel* label) { | 94 JoinEntryInstr* NestedStatement::BreakTargetFor(SourceLabel* label) { |
46 if (label != label_) return NULL; | 95 if (label != label_) return NULL; |
47 if (break_target_ == NULL) { | 96 if (break_target_ == NULL) { |
48 break_target_ = | 97 break_target_ = |
49 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); | 98 new JoinEntryInstr(owner()->AllocateBlockId(), owner()->try_index()); |
50 } | 99 } |
51 return break_target_; | 100 return break_target_; |
52 } | 101 } |
53 | 102 |
54 | 103 |
55 JoinEntryInstr* NestedStatement::ContinueTargetFor(SourceLabel* label) { | 104 JoinEntryInstr* NestedStatement::ContinueTargetFor(SourceLabel* label) { |
56 return NULL; | 105 return NULL; |
57 } | 106 } |
58 | 107 |
59 | 108 |
109 // A nested statement that has its own context level. | |
110 class NestedBlock : public NestedStatement { | |
111 public: | |
112 NestedBlock(FlowGraphBuilder* owner, SequenceNode* node) | |
113 : NestedStatement(owner, node->label()), scope_(node->scope()) {} | |
114 | |
115 virtual intptr_t ContextLevel() const; | |
116 | |
117 private: | |
118 LocalScope* scope_; | |
119 }; | |
120 | |
121 | |
122 intptr_t NestedBlock::ContextLevel() const { | |
123 return ((scope_ == NULL) || (scope_->num_context_variables() == 0)) | |
124 ? NestedStatement::ContextLevel() | |
125 : scope_->context_level(); | |
126 } | |
127 | |
128 | |
60 // A nested statement that can be the target of a continue as well as a | 129 // A nested statement that can be the target of a continue as well as a |
61 // break. | 130 // break. |
62 class NestedLoop : public NestedStatement { | 131 class NestedLoop : public NestedStatement { |
63 public: | 132 public: |
64 NestedLoop(FlowGraphBuilder* owner, SourceLabel* label) | 133 NestedLoop(FlowGraphBuilder* owner, SourceLabel* label) |
65 : NestedStatement(owner, label), continue_target_(NULL) { } | 134 : NestedStatement(owner, label), continue_target_(NULL) { |
135 owner->IncrementLoopDepth(); | |
136 } | |
137 | |
138 virtual ~NestedLoop() { | |
139 owner()->DecrementLoopDepth(); | |
140 } | |
66 | 141 |
67 JoinEntryInstr* continue_target() const { return continue_target_; } | 142 JoinEntryInstr* continue_target() const { return continue_target_; } |
68 | 143 |
69 virtual JoinEntryInstr* ContinueTargetFor(SourceLabel* label); | 144 virtual JoinEntryInstr* ContinueTargetFor(SourceLabel* label); |
70 | 145 |
71 private: | 146 private: |
72 JoinEntryInstr* continue_target_; | 147 JoinEntryInstr* continue_target_; |
73 }; | 148 }; |
74 | 149 |
75 | 150 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
136 ic_data_array_(ic_data_array), | 211 ic_data_array_(ic_data_array), |
137 num_copied_params_(parsed_function->num_copied_params()), | 212 num_copied_params_(parsed_function->num_copied_params()), |
138 // All parameters are copied if any parameter is. | 213 // All parameters are copied if any parameter is. |
139 num_non_copied_params_((num_copied_params_ == 0) | 214 num_non_copied_params_((num_copied_params_ == 0) |
140 ? parsed_function->function().num_fixed_parameters() | 215 ? parsed_function->function().num_fixed_parameters() |
141 : 0), | 216 : 0), |
142 num_stack_locals_(parsed_function->num_stack_locals()), | 217 num_stack_locals_(parsed_function->num_stack_locals()), |
143 exit_collector_(exit_collector), | 218 exit_collector_(exit_collector), |
144 guarded_fields_(new ZoneGrowableArray<const Field*>()), | 219 guarded_fields_(new ZoneGrowableArray<const Field*>()), |
145 last_used_block_id_(0), // 0 is used for the graph entry. | 220 last_used_block_id_(0), // 0 is used for the graph entry. |
146 context_level_(0), | |
147 try_index_(CatchClauseNode::kInvalidTryIndex), | 221 try_index_(CatchClauseNode::kInvalidTryIndex), |
148 catch_try_index_(CatchClauseNode::kInvalidTryIndex), | 222 catch_try_index_(CatchClauseNode::kInvalidTryIndex), |
149 loop_depth_(0), | 223 loop_depth_(0), |
150 graph_entry_(NULL), | 224 graph_entry_(NULL), |
151 temp_count_(0), | 225 temp_count_(0), |
152 args_pushed_(0), | 226 args_pushed_(0), |
153 nesting_stack_(NULL), | 227 nesting_stack_(NULL), |
154 osr_id_(osr_id) { } | 228 osr_id_(osr_id) { } |
155 | 229 |
156 | 230 |
(...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
909 Symbols::FunctionResult()); | 983 Symbols::FunctionResult()); |
910 } | 984 } |
911 } | 985 } |
912 | 986 |
913 intptr_t current_context_level = owner()->context_level(); | 987 intptr_t current_context_level = owner()->context_level(); |
914 ASSERT(current_context_level >= 0); | 988 ASSERT(current_context_level >= 0); |
915 if (owner()->parsed_function()->saved_entry_context_var() != NULL) { | 989 if (owner()->parsed_function()->saved_entry_context_var() != NULL) { |
916 // CTX on entry was saved, but not linked as context parent. | 990 // CTX on entry was saved, but not linked as context parent. |
917 BuildRestoreContext(*owner()->parsed_function()->saved_entry_context_var()); | 991 BuildRestoreContext(*owner()->parsed_function()->saved_entry_context_var()); |
918 } else { | 992 } else { |
919 while (current_context_level-- > 0) { | 993 UnchainContexts(current_context_level); |
920 UnchainContext(); | |
921 } | |
922 } | 994 } |
923 | 995 |
924 AddReturnExit(node->token_pos(), return_value); | 996 AddReturnExit(node->token_pos(), return_value); |
925 } | 997 } |
926 | 998 |
927 | 999 |
928 // <Expression> ::= Literal { literal: Instance } | 1000 // <Expression> ::= Literal { literal: Instance } |
929 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { | 1001 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { |
930 return; | 1002 return; |
931 } | 1003 } |
(...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1772 // The fragment is composed as follows: | 1844 // The fragment is composed as follows: |
1773 // a) loop-join | 1845 // a) loop-join |
1774 // b) [ test ] -> (body-entry-target, loop-exit-target) | 1846 // b) [ test ] -> (body-entry-target, loop-exit-target) |
1775 // c) body-entry-target | 1847 // c) body-entry-target |
1776 // d) [ body ] -> (continue-join) | 1848 // d) [ body ] -> (continue-join) |
1777 // e) continue-join -> (loop-join) | 1849 // e) continue-join -> (loop-join) |
1778 // f) loop-exit-target | 1850 // f) loop-exit-target |
1779 // g) break-join (optional) | 1851 // g) break-join (optional) |
1780 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { | 1852 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { |
1781 NestedLoop nested_loop(owner(), node->label()); | 1853 NestedLoop nested_loop(owner(), node->label()); |
1782 owner()->IncrementLoopDepth(); | |
1783 | 1854 |
1784 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); | 1855 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); |
1785 node->condition()->Visit(&for_test); | 1856 node->condition()->Visit(&for_test); |
1786 ASSERT(!for_test.is_empty()); // Language spec. | 1857 ASSERT(!for_test.is_empty()); // Language spec. |
1787 | 1858 |
1788 EffectGraphVisitor for_body(owner()); | 1859 EffectGraphVisitor for_body(owner()); |
1789 node->body()->Visit(&for_body); | 1860 node->body()->Visit(&for_body); |
1790 | 1861 |
1791 // Labels are set after body traversal. | 1862 // Labels are set after body traversal. |
1792 JoinEntryInstr* join = nested_loop.continue_target(); | 1863 JoinEntryInstr* join = nested_loop.continue_target(); |
1793 if (join != NULL) { | 1864 if (join != NULL) { |
1794 if (for_body.is_open()) for_body.Goto(join); | 1865 if (for_body.is_open()) for_body.Goto(join); |
1795 for_body.exit_ = join; | 1866 for_body.exit_ = join; |
1796 } | 1867 } |
1797 TieLoop(node->token_pos(), for_test, for_body); | 1868 TieLoop(node->token_pos(), for_test, for_body); |
1798 join = nested_loop.break_target(); | 1869 join = nested_loop.break_target(); |
1799 if (join != NULL) { | 1870 if (join != NULL) { |
1800 Goto(join); | 1871 Goto(join); |
1801 exit_ = join; | 1872 exit_ = join; |
1802 } | 1873 } |
1803 owner()->DecrementLoopDepth(); | |
1804 } | 1874 } |
1805 | 1875 |
1806 | 1876 |
1807 // The fragment is composed as follows: | 1877 // The fragment is composed as follows: |
1808 // a) body-entry-join | 1878 // a) body-entry-join |
1809 // b) [ body ] | 1879 // b) [ body ] |
1810 // c) test-entry (continue-join or body-exit-target) | 1880 // c) test-entry (continue-join or body-exit-target) |
1811 // d) [ test-entry ] -> (back-target, loop-exit-target) | 1881 // d) [ test-entry ] -> (back-target, loop-exit-target) |
1812 // e) back-target -> (body-entry-join) | 1882 // e) back-target -> (body-entry-join) |
1813 // f) loop-exit-target | 1883 // f) loop-exit-target |
1814 // g) break-join | 1884 // g) break-join |
1815 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { | 1885 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { |
1816 NestedLoop nested_loop(owner(), node->label()); | 1886 NestedLoop nested_loop(owner(), node->label()); |
1817 owner()->IncrementLoopDepth(); | |
1818 | 1887 |
1819 // Traverse the body first in order to generate continue and break labels. | 1888 // Traverse the body first in order to generate continue and break labels. |
1820 EffectGraphVisitor for_body(owner()); | 1889 EffectGraphVisitor for_body(owner()); |
1821 node->body()->Visit(&for_body); | 1890 node->body()->Visit(&for_body); |
1822 | 1891 |
1823 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); | 1892 TestGraphVisitor for_test(owner(), node->condition()->token_pos()); |
1824 node->condition()->Visit(&for_test); | 1893 node->condition()->Visit(&for_test); |
1825 ASSERT(is_open()); | 1894 ASSERT(is_open()); |
1826 | 1895 |
1827 // Tie do-while loop (test is after the body). | 1896 // Tie do-while loop (test is after the body). |
(...skipping 19 matching lines...) Expand all Loading... | |
1847 } | 1916 } |
1848 | 1917 |
1849 for_test.IfTrueGoto(body_entry_join); | 1918 for_test.IfTrueGoto(body_entry_join); |
1850 join = nested_loop.break_target(); | 1919 join = nested_loop.break_target(); |
1851 if (join == NULL) { | 1920 if (join == NULL) { |
1852 exit_ = for_test.CreateFalseSuccessor(); | 1921 exit_ = for_test.CreateFalseSuccessor(); |
1853 } else { | 1922 } else { |
1854 for_test.IfFalseGoto(join); | 1923 for_test.IfFalseGoto(join); |
1855 exit_ = join; | 1924 exit_ = join; |
1856 } | 1925 } |
1857 owner()->DecrementLoopDepth(); | |
1858 } | 1926 } |
1859 | 1927 |
1860 | 1928 |
1861 // A ForNode can contain break and continue jumps. 'break' joins to | 1929 // A ForNode can contain break and continue jumps. 'break' joins to |
1862 // ForNode exit, 'continue' joins at increment entry. The fragment is composed | 1930 // ForNode exit, 'continue' joins at increment entry. The fragment is composed |
1863 // as follows: | 1931 // as follows: |
1864 // a) [ initializer ] | 1932 // a) [ initializer ] |
1865 // b) loop-join | 1933 // b) loop-join |
1866 // c) [ test ] -> (body-entry-target, loop-exit-target) | 1934 // c) [ test ] -> (body-entry-target, loop-exit-target) |
1867 // d) body-entry-target | 1935 // d) body-entry-target |
1868 // e) [ body ] | 1936 // e) [ body ] |
1869 // f) continue-join (optional) | 1937 // f) continue-join (optional) |
1870 // g) [ increment ] -> (loop-join) | 1938 // g) [ increment ] -> (loop-join) |
1871 // h) loop-exit-target | 1939 // h) loop-exit-target |
1872 // i) break-join | 1940 // i) break-join |
1873 void EffectGraphVisitor::VisitForNode(ForNode* node) { | 1941 void EffectGraphVisitor::VisitForNode(ForNode* node) { |
1874 EffectGraphVisitor for_initializer(owner()); | 1942 EffectGraphVisitor for_initializer(owner()); |
1875 node->initializer()->Visit(&for_initializer); | 1943 node->initializer()->Visit(&for_initializer); |
1876 Append(for_initializer); | 1944 Append(for_initializer); |
1877 ASSERT(is_open()); | 1945 ASSERT(is_open()); |
1878 | 1946 |
1879 NestedLoop nested_loop(owner(), node->label()); | 1947 NestedLoop nested_loop(owner(), node->label()); |
1880 owner()->IncrementLoopDepth(); | |
1881 // Compose body to set any jump labels. | 1948 // Compose body to set any jump labels. |
1882 EffectGraphVisitor for_body(owner()); | 1949 EffectGraphVisitor for_body(owner()); |
1883 node->body()->Visit(&for_body); | 1950 node->body()->Visit(&for_body); |
1884 | 1951 |
1885 EffectGraphVisitor for_increment(owner()); | 1952 EffectGraphVisitor for_increment(owner()); |
1886 node->increment()->Visit(&for_increment); | 1953 node->increment()->Visit(&for_increment); |
1887 | 1954 |
1888 // Join the loop body and increment and then tie the loop. | 1955 // Join the loop body and increment and then tie the loop. |
1889 JoinEntryInstr* continue_join = nested_loop.continue_target(); | 1956 JoinEntryInstr* continue_join = nested_loop.continue_target(); |
1890 if ((continue_join != NULL) || for_body.is_open()) { | 1957 if ((continue_join != NULL) || for_body.is_open()) { |
(...skipping 25 matching lines...) Expand all Loading... | |
1916 BlockEntryInstr* body_entry = for_test.CreateTrueSuccessor(); | 1983 BlockEntryInstr* body_entry = for_test.CreateTrueSuccessor(); |
1917 AppendFragment(body_entry, for_body); | 1984 AppendFragment(body_entry, for_body); |
1918 | 1985 |
1919 if (nested_loop.break_target() == NULL) { | 1986 if (nested_loop.break_target() == NULL) { |
1920 exit_ = for_test.CreateFalseSuccessor(); | 1987 exit_ = for_test.CreateFalseSuccessor(); |
1921 } else { | 1988 } else { |
1922 for_test.IfFalseGoto(nested_loop.break_target()); | 1989 for_test.IfFalseGoto(nested_loop.break_target()); |
1923 exit_ = nested_loop.break_target(); | 1990 exit_ = nested_loop.break_target(); |
1924 } | 1991 } |
1925 } | 1992 } |
1926 owner()->DecrementLoopDepth(); | |
1927 } | 1993 } |
1928 | 1994 |
1929 | 1995 |
1930 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { | 1996 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { |
1931 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { | 1997 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { |
1932 EffectGraphVisitor for_effect(owner()); | 1998 EffectGraphVisitor for_effect(owner()); |
1933 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); | 1999 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); |
1934 Append(for_effect); | 2000 Append(for_effect); |
1935 if (!is_open()) return; | 2001 if (!is_open()) return; |
1936 } | 2002 } |
(...skipping 15 matching lines...) Expand all Loading... | |
1952 (target_scope->num_context_variables() == 0)) { | 2018 (target_scope->num_context_variables() == 0)) { |
1953 target_scope = target_scope->parent(); | 2019 target_scope = target_scope->parent(); |
1954 } | 2020 } |
1955 if (target_scope != NULL) { | 2021 if (target_scope != NULL) { |
1956 target_context_level = target_scope->context_level(); | 2022 target_context_level = target_scope->context_level(); |
1957 } | 2023 } |
1958 } | 2024 } |
1959 ASSERT(target_context_level >= 0); | 2025 ASSERT(target_context_level >= 0); |
1960 intptr_t current_context_level = owner()->context_level(); | 2026 intptr_t current_context_level = owner()->context_level(); |
1961 ASSERT(current_context_level >= target_context_level); | 2027 ASSERT(current_context_level >= target_context_level); |
1962 while (current_context_level-- > target_context_level) { | 2028 UnchainContexts(current_context_level - target_context_level); |
1963 UnchainContext(); | |
1964 } | |
1965 | 2029 |
1966 JoinEntryInstr* jump_target = NULL; | 2030 JoinEntryInstr* jump_target = NULL; |
1967 if (node->kind() == Token::kBREAK) { | 2031 NestedStatement* current = owner()->nesting_stack(); |
1968 NestedStatement* current = owner()->nesting_stack(); | 2032 while (current != NULL) { |
1969 while (current != NULL) { | 2033 jump_target = (node->kind() == Token::kBREAK) |
1970 jump_target = current->BreakTargetFor(node->label()); | 2034 ? current->BreakTargetFor(node->label()) |
1971 if (jump_target != NULL) break; | 2035 : current->ContinueTargetFor(node->label()); |
1972 current = current->outer(); | 2036 if (jump_target != NULL) break; |
1973 } | 2037 current = current->outer(); |
1974 } else { | |
1975 NestedStatement* current = owner()->nesting_stack(); | |
1976 while (current != NULL) { | |
1977 jump_target = current->ContinueTargetFor(node->label()); | |
1978 if (jump_target != NULL) break; | |
1979 current = current->outer(); | |
1980 } | |
1981 } | 2038 } |
1982 ASSERT(jump_target != NULL); | 2039 ASSERT(jump_target != NULL); |
1983 Goto(jump_target); | 2040 Goto(jump_target); |
1984 } | 2041 } |
1985 | 2042 |
1986 | 2043 |
1987 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { | 2044 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { |
1988 UNREACHABLE(); | 2045 UNREACHABLE(); |
1989 } | 2046 } |
1990 | 2047 |
(...skipping 1459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3450 ReturnDefinition(BuildStoreIndexedValues(node, kResultNeeded)); | 3507 ReturnDefinition(BuildStoreIndexedValues(node, kResultNeeded)); |
3451 } | 3508 } |
3452 | 3509 |
3453 | 3510 |
3454 bool EffectGraphVisitor::MustSaveRestoreContext(SequenceNode* node) const { | 3511 bool EffectGraphVisitor::MustSaveRestoreContext(SequenceNode* node) const { |
3455 return (node == owner()->parsed_function()->node_sequence()) && | 3512 return (node == owner()->parsed_function()->node_sequence()) && |
3456 (owner()->parsed_function()->saved_entry_context_var() != NULL); | 3513 (owner()->parsed_function()->saved_entry_context_var() != NULL); |
3457 } | 3514 } |
3458 | 3515 |
3459 | 3516 |
3460 void EffectGraphVisitor::UnchainContext() { | 3517 void EffectGraphVisitor::UnchainContexts(intptr_t n) { |
3461 Value* context = Bind(new CurrentContextInstr()); | 3518 if (n > 0) { |
3462 Value* parent = Bind( | 3519 Value* context = Bind(new CurrentContextInstr()); |
3463 new LoadFieldInstr(context, | 3520 while (n-- > 0) { |
3464 Context::parent_offset(), | 3521 context = Bind( |
3465 Type::ZoneHandle())); // Not an instance, no type. | 3522 new LoadFieldInstr(context, |
3466 AddInstruction(new StoreContextInstr(parent)); | 3523 Context::parent_offset(), |
3524 Type::ZoneHandle())); // Not an instance, no type. | |
3525 } | |
3526 AddInstruction(new StoreContextInstr(context)); | |
3527 } | |
3467 } | 3528 } |
3468 | 3529 |
3469 | 3530 |
3470 // <Statement> ::= Sequence { scope: LocalScope | 3531 // <Statement> ::= Sequence { scope: LocalScope |
3471 // nodes: <Statement>* | 3532 // nodes: <Statement>* |
3472 // label: SourceLabel } | 3533 // label: SourceLabel } |
3473 void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) { | 3534 void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) { |
3474 LocalScope* scope = node->scope(); | 3535 LocalScope* scope = node->scope(); |
3475 const intptr_t num_context_variables = | 3536 const intptr_t num_context_variables = |
3476 (scope != NULL) ? scope->num_context_variables() : 0; | 3537 (scope != NULL) ? scope->num_context_variables() : 0; |
3477 int previous_context_level = owner()->context_level(); | |
3478 // The outermost function sequence cannot contain a label. | 3538 // The outermost function sequence cannot contain a label. |
3479 ASSERT((node->label() == NULL) || | 3539 ASSERT((node->label() == NULL) || |
3480 (node != owner()->parsed_function()->node_sequence())); | 3540 (node != owner()->parsed_function()->node_sequence())); |
3481 NestedStatement nested_block(owner(), node->label()); | 3541 NestedBlock nested_block(owner(), node); |
3482 | 3542 |
3483 if (num_context_variables > 0) { | 3543 if (num_context_variables > 0) { |
3484 // The loop local scope declares variables that are captured. | 3544 // The loop local scope declares variables that are captured. |
3485 // Allocate and chain a new context. | 3545 // Allocate and chain a new context. |
3486 // Allocate context computation (uses current CTX) | 3546 // Allocate context computation (uses current CTX) |
3487 Value* allocated_context = | 3547 Value* allocated_context = |
3488 Bind(new AllocateContextInstr(node->token_pos(), | 3548 Bind(new AllocateContextInstr(node->token_pos(), |
3489 num_context_variables)); | 3549 num_context_variables)); |
3490 { LocalVariable* tmp_var = EnterTempLocalScope(allocated_context); | 3550 { LocalVariable* tmp_var = EnterTempLocalScope(allocated_context); |
3491 // If this node_sequence is the body of the function being compiled, and | 3551 // If this node_sequence is the body of the function being compiled, and |
(...skipping 11 matching lines...) Expand all Loading... | |
3503 Value* current_context = Bind(new CurrentContextInstr()); | 3563 Value* current_context = Bind(new CurrentContextInstr()); |
3504 Value* tmp_val = Bind(new LoadLocalInstr(*tmp_var)); | 3564 Value* tmp_val = Bind(new LoadLocalInstr(*tmp_var)); |
3505 Do(new StoreVMFieldInstr(tmp_val, | 3565 Do(new StoreVMFieldInstr(tmp_val, |
3506 Context::parent_offset(), | 3566 Context::parent_offset(), |
3507 current_context, | 3567 current_context, |
3508 Type::ZoneHandle())); | 3568 Type::ZoneHandle())); |
3509 AddInstruction( | 3569 AddInstruction( |
3510 new StoreContextInstr(Bind(ExitTempLocalScope(tmp_var)))); | 3570 new StoreContextInstr(Bind(ExitTempLocalScope(tmp_var)))); |
3511 } | 3571 } |
3512 | 3572 |
3513 owner()->set_context_level(scope->context_level()); | |
3514 | |
3515 // If this node_sequence is the body of the function being compiled, copy | 3573 // If this node_sequence is the body of the function being compiled, copy |
3516 // the captured parameters from the frame into the context. | 3574 // the captured parameters from the frame into the context. |
3517 if (node == owner()->parsed_function()->node_sequence()) { | 3575 if (node == owner()->parsed_function()->node_sequence()) { |
3518 ASSERT(scope->context_level() == 1); | 3576 ASSERT(scope->context_level() == 1); |
3519 const Function& function = owner()->parsed_function()->function(); | 3577 const Function& function = owner()->parsed_function()->function(); |
3520 const int num_params = function.NumParameters(); | 3578 const int num_params = function.NumParameters(); |
3521 int param_frame_index = (num_params == function.num_fixed_parameters()) ? | 3579 int param_frame_index = (num_params == function.num_fixed_parameters()) ? |
3522 (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp; | 3580 (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp; |
3523 for (int pos = 0; pos < num_params; param_frame_index--, pos++) { | 3581 for (int pos = 0; pos < num_params; param_frame_index--, pos++) { |
3524 const LocalVariable& parameter = *scope->VariableAt(pos); | 3582 const LocalVariable& parameter = *scope->VariableAt(pos); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3593 break; | 3651 break; |
3594 } | 3652 } |
3595 } | 3653 } |
3596 | 3654 |
3597 if (is_open()) { | 3655 if (is_open()) { |
3598 if (MustSaveRestoreContext(node)) { | 3656 if (MustSaveRestoreContext(node)) { |
3599 ASSERT(num_context_variables > 0); | 3657 ASSERT(num_context_variables > 0); |
3600 BuildRestoreContext( | 3658 BuildRestoreContext( |
3601 *owner()->parsed_function()->saved_entry_context_var()); | 3659 *owner()->parsed_function()->saved_entry_context_var()); |
3602 } else if (num_context_variables > 0) { | 3660 } else if (num_context_variables > 0) { |
3603 UnchainContext(); | 3661 UnchainContexts(1); |
3604 } | 3662 } |
3605 } | 3663 } |
3606 | 3664 |
3607 // If this node sequence is labeled, a break out of the sequence will have | 3665 // If this node sequence is labeled, a break out of the sequence will have |
3608 // taken care of unchaining the context. | 3666 // taken care of unchaining the context. |
3609 if (nested_block.break_target() != NULL) { | 3667 if (nested_block.break_target() != NULL) { |
3610 if (is_open()) Goto(nested_block.break_target()); | 3668 if (is_open()) Goto(nested_block.break_target()); |
3611 exit_ = nested_block.break_target(); | 3669 exit_ = nested_block.break_target(); |
3612 } | 3670 } |
3613 | |
3614 owner()->set_context_level(previous_context_level); | |
3615 } | 3671 } |
3616 | 3672 |
3617 | 3673 |
3618 void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) { | 3674 void EffectGraphVisitor::VisitCatchClauseNode(CatchClauseNode* node) { |
3619 InlineBailout("EffectGraphVisitor::VisitCatchClauseNode (exception)"); | 3675 InlineBailout("EffectGraphVisitor::VisitCatchClauseNode (exception)"); |
3620 // Restores CTX from local variable ':saved_context'. | 3676 // Restores CTX from local variable ':saved_context'. |
3621 BuildRestoreContext(node->context_var()); | 3677 BuildRestoreContext(node->context_var()); |
3622 | 3678 |
3623 EffectGraphVisitor for_catch(owner()); | 3679 EffectGraphVisitor for_catch(owner()); |
3624 node->VisitChildren(&for_catch); | 3680 node->VisitChildren(&for_catch); |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3977 LanguageError::kError, | 4033 LanguageError::kError, |
3978 Heap::kNew, | 4034 Heap::kNew, |
3979 "FlowGraphBuilder Bailout: %s %s", | 4035 "FlowGraphBuilder Bailout: %s %s", |
3980 String::Handle(function.name()).ToCString(), | 4036 String::Handle(function.name()).ToCString(), |
3981 reason)); | 4037 reason)); |
3982 Isolate::Current()->long_jump_base()->Jump(1, error); | 4038 Isolate::Current()->long_jump_base()->Jump(1, error); |
3983 } | 4039 } |
3984 | 4040 |
3985 | 4041 |
3986 } // namespace dart | 4042 } // namespace dart |
OLD | NEW |