Chromium Code Reviews| 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 |