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

Side by Side Diff: vm/flow_graph_builder.cc

Issue 10700034: Add a goto instruction to the IL use it to terminate basic blocks. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 5 months 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
« no previous file with comments | « vm/flow_graph_builder.h ('k') | vm/flow_graph_compiler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "vm/ast_printer.h" 7 #include "vm/ast_printer.h"
8 #include "vm/bit_vector.h" 8 #include "vm/bit_vector.h"
9 #include "vm/code_descriptors.h" 9 #include "vm/code_descriptors.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 } 44 }
45 45
46 46
47 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) { 47 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) {
48 ASSERT(is_open()); 48 ASSERT(is_open());
49 if (other_fragment.is_empty()) return; 49 if (other_fragment.is_empty()) return;
50 if (is_empty()) { 50 if (is_empty()) {
51 entry_ = other_fragment.entry(); 51 entry_ = other_fragment.entry();
52 exit_ = other_fragment.exit(); 52 exit_ = other_fragment.exit();
53 } else { 53 } else {
54 exit()->SetSuccessor(other_fragment.entry()); 54 Instruction* successor = other_fragment.entry();
55 exit()->SetSuccessor(successor->IsBlockEntry()
56 ? new GotoInstr(successor->AsBlockEntry())
57 : successor);
55 exit_ = other_fragment.exit(); 58 exit_ = other_fragment.exit();
56 } 59 }
57 temp_index_ = other_fragment.temp_index(); 60 temp_index_ = other_fragment.temp_index();
58 } 61 }
59 62
60 63
61 void EffectGraphVisitor::AddInstruction(Instruction* instruction) { 64 void EffectGraphVisitor::AddInstruction(Instruction* instruction) {
62 ASSERT(is_open()); 65 ASSERT(is_open());
66 ASSERT(!instruction->IsBlockEntry());
63 DeallocateTempIndex(instruction->InputCount()); 67 DeallocateTempIndex(instruction->InputCount());
64 if (instruction->IsDefinition()) { 68 if (instruction->IsDefinition()) {
65 instruction->AsDefinition()->set_temp_index(AllocateTempIndex()); 69 instruction->AsDefinition()->set_temp_index(AllocateTempIndex());
66 } 70 }
67 if (is_empty()) { 71 if (is_empty()) {
68 entry_ = exit_ = instruction; 72 entry_ = exit_ = instruction;
69 } else { 73 } else {
70 exit()->SetSuccessor(instruction); 74 exit()->SetSuccessor(instruction);
71 exit_ = instruction; 75 exit_ = instruction;
72 } 76 }
73 } 77 }
74 78
75 79
80 void EffectGraphVisitor::AddBlockEntry(BlockEntryInstr* instruction) {
81 ASSERT(is_open());
82 if (is_empty()) {
83 entry_ = exit_ = instruction;
84 } else {
85 ASSERT(exit()->IsGraphEntry() ||
86 exit()->IsGoto());
87 exit()->SetSuccessor(instruction);
88 exit_ = instruction;
89 }
90 }
91
92
76 void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment, 93 void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment,
77 const EffectGraphVisitor& true_fragment, 94 const EffectGraphVisitor& true_fragment,
78 const EffectGraphVisitor& false_fragment) { 95 const EffectGraphVisitor& false_fragment) {
79 // We have: a test graph fragment with zero, one, or two available exits; 96 // We have: a test graph fragment with zero, one, or two available exits;
80 // and a pair of effect graph fragments with zero or one available exits. 97 // and a pair of effect graph fragments with zero or one available exits.
81 // We want to append the branch and (if necessary) a join node to this 98 // We want to append the branch and (if necessary) a join node to this
82 // graph fragment. 99 // graph fragment.
83 ASSERT(is_open()); 100 ASSERT(is_open());
84 101
85 // 1. Connect the test to this graph. 102 // 1. Connect the test to this graph.
(...skipping 15 matching lines...) Expand all
101 118
102 // 3. Add a join or select one (or neither) of the arms as exit. 119 // 3. Add a join or select one (or neither) of the arms as exit.
103 if (true_exit == NULL) { 120 if (true_exit == NULL) {
104 exit_ = false_exit; // May be NULL. 121 exit_ = false_exit; // May be NULL.
105 if (false_exit != NULL) temp_index_ = false_fragment.temp_index(); 122 if (false_exit != NULL) temp_index_ = false_fragment.temp_index();
106 } else if (false_exit == NULL) { 123 } else if (false_exit == NULL) {
107 exit_ = true_exit; 124 exit_ = true_exit;
108 temp_index_ = true_fragment.temp_index(); 125 temp_index_ = true_fragment.temp_index();
109 } else { 126 } else {
110 exit_ = new JoinEntryInstr(); 127 exit_ = new JoinEntryInstr();
111 true_exit->SetSuccessor(exit_); 128 true_exit->SetSuccessor(new GotoInstr(exit_->AsBlockEntry()));
112 false_exit->SetSuccessor(exit_); 129 false_exit->SetSuccessor(new GotoInstr(exit_->AsBlockEntry()));
113 ASSERT(true_fragment.temp_index() == false_fragment.temp_index()); 130 ASSERT(true_fragment.temp_index() == false_fragment.temp_index());
114 temp_index_ = true_fragment.temp_index(); 131 temp_index_ = true_fragment.temp_index();
115 } 132 }
116 } 133 }
117 134
118 135
119 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, 136 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment,
120 const EffectGraphVisitor& body_fragment) { 137 const EffectGraphVisitor& body_fragment) {
121 // We have: a test graph fragment with zero, one, or two available exits; 138 // We have: a test graph fragment with zero, one, or two available exits;
122 // and an effect graph fragment with zero or one available exits. We want 139 // and an effect graph fragment with zero or one available exits. We want
123 // to append the 'while loop' consisting of the test graph fragment as 140 // to append the 'while loop' consisting of the test graph fragment as
124 // condition and the effect graph fragment as body. 141 // condition and the effect graph fragment as body.
125 ASSERT(is_open()); 142 ASSERT(is_open());
126 143
127 // 1. Connect the body to the test if it is reachable, and if so record 144 // 1. Connect the body to the test if it is reachable, and if so record
128 // its exit (if any). 145 // its exit (if any).
129 Instruction* body_exit = NULL; 146 Instruction* body_exit = NULL;
130 TargetEntryInstr* body_entry = new TargetEntryInstr(); 147 TargetEntryInstr* body_entry = new TargetEntryInstr();
131 *test_fragment.true_successor_address() = body_entry; 148 *test_fragment.true_successor_address() = body_entry;
132 body_entry->SetSuccessor(body_fragment.entry()); 149 body_entry->SetSuccessor(body_fragment.entry());
133 body_exit = body_fragment.is_empty() ? body_entry : body_fragment.exit(); 150 body_exit = body_fragment.is_empty() ? body_entry : body_fragment.exit();
134 151
135 // 2. Connect the test to this graph, including the body if reachable and 152 // 2. Connect the test to this graph, including the body if reachable and
136 // using a fresh join node if the body is reachable and has an open exit. 153 // using a fresh join node if the body is reachable and has an open exit.
137 if (body_exit == NULL) { 154 if (body_exit == NULL) {
138 Append(test_fragment); 155 Append(test_fragment);
139 } else { 156 } else {
140 JoinEntryInstr* join = new JoinEntryInstr(); 157 JoinEntryInstr* join = new JoinEntryInstr();
141 AddInstruction(join); 158 AddInstruction(new GotoInstr(join));
159 AddBlockEntry(join);
142 join->SetSuccessor(test_fragment.entry()); 160 join->SetSuccessor(test_fragment.entry());
143 body_exit->SetSuccessor(join); 161 body_exit->SetSuccessor(new GotoInstr(join));
144 } 162 }
145 163
146 // 3. Set the exit to the graph to be the false successor of the test, a 164 // 3. Set the exit to the graph to be the false successor of the test, a
147 // fresh target node 165 // fresh target node
148 exit_ = *test_fragment.false_successor_address() = new TargetEntryInstr(); 166 exit_ = *test_fragment.false_successor_address() = new TargetEntryInstr();
149 } 167 }
150 168
151 169
152 Computation* EffectGraphVisitor::BuildStoreLocal( 170 Computation* EffectGraphVisitor::BuildStoreLocal(
153 const LocalVariable& local, Value* value) { 171 const LocalVariable& local, Value* value) {
(...skipping 802 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 Join(for_test, for_true, for_false); 974 Join(for_test, for_true, for_false);
957 } 975 }
958 976
959 977
960 void EffectGraphVisitor::VisitSwitchNode(SwitchNode* node) { 978 void EffectGraphVisitor::VisitSwitchNode(SwitchNode* node) {
961 EffectGraphVisitor switch_body(owner(), temp_index()); 979 EffectGraphVisitor switch_body(owner(), temp_index());
962 node->body()->Visit(&switch_body); 980 node->body()->Visit(&switch_body);
963 Append(switch_body); 981 Append(switch_body);
964 if ((node->label() != NULL) && (node->label()->join_for_break() != NULL)) { 982 if ((node->label() != NULL) && (node->label()->join_for_break() != NULL)) {
965 if (is_open()) { 983 if (is_open()) {
966 AddInstruction(node->label()->join_for_break()); 984 AddInstruction(new GotoInstr(node->label()->join_for_break()));
985 AddBlockEntry(node->label()->join_for_break());
967 } else { 986 } else {
968 exit_ = node->label()->join_for_break(); 987 exit_ = node->label()->join_for_break();
969 } 988 }
970 } 989 }
971 // No continue label allowed. 990 // No continue label allowed.
972 ASSERT((node->label() == NULL) || 991 ASSERT((node->label() == NULL) ||
973 (node->label()->join_for_continue() == NULL)); 992 (node->label()->join_for_continue() == NULL));
974 } 993 }
975 994
976 995
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1008 // allocate JoinNode here and use it as statement start. 1027 // allocate JoinNode here and use it as statement start.
1009 if (node->label()->join_for_continue() == NULL) { 1028 if (node->label()->join_for_continue() == NULL) {
1010 node->label()->set_join_for_continue(new JoinEntryInstr()); 1029 node->label()->set_join_for_continue(new JoinEntryInstr());
1011 } 1030 }
1012 statement_start = node->label()->join_for_continue(); 1031 statement_start = node->label()->join_for_continue();
1013 } else if (needs_join_at_statement_entry) { 1032 } else if (needs_join_at_statement_entry) {
1014 statement_start = new JoinEntryInstr(); 1033 statement_start = new JoinEntryInstr();
1015 } else { 1034 } else {
1016 statement_start = new TargetEntryInstr(); 1035 statement_start = new TargetEntryInstr();
1017 } 1036 }
1018 for_case_statements.AddInstruction(statement_start); 1037 for_case_statements.AddBlockEntry(statement_start);
1019 node->statements()->Visit(&for_case_statements); 1038 node->statements()->Visit(&for_case_statements);
1020 if (is_open() && (len == 0)) { 1039 if (is_open() && (len == 0)) {
1021 ASSERT(node->contains_default()); 1040 ASSERT(node->contains_default());
1022 // Default only case node. 1041 // Default only case node.
1023 Append(for_case_statements); 1042 Append(for_case_statements);
1024 return; 1043 return;
1025 } 1044 }
1026 1045
1027 // Generate instructions for all case expressions and collect data to 1046 // Generate instructions for all case expressions and collect data to
1028 // connect them. 1047 // connect them.
1029 GrowableArray<TargetEntryInstr**> case_true_addresses; 1048 GrowableArray<TargetEntryInstr**> case_true_addresses;
1030 GrowableArray<TargetEntryInstr**> case_false_addresses; 1049 GrowableArray<TargetEntryInstr**> case_false_addresses;
1031 GrowableArray<TargetEntryInstr*> case_entries; 1050 GrowableArray<TargetEntryInstr*> case_entries;
1032 for (intptr_t i = 0; i < len; i++) { 1051 for (intptr_t i = 0; i < len; i++) {
1033 AstNode* case_expr = node->case_expressions()->NodeAt(i); 1052 AstNode* case_expr = node->case_expressions()->NodeAt(i);
1034 TestGraphVisitor for_case_expression(owner(), 1053 TestGraphVisitor for_case_expression(owner(),
1035 temp_index(), 1054 temp_index(),
1036 case_expr->token_pos()); 1055 case_expr->token_pos());
1037 if (i == 0) { 1056 if (i == 0) {
1038 case_entries.Add(NULL); // Not to be used 1057 case_entries.Add(NULL); // Not to be used
1039 case_expr->Visit(&for_case_expression); 1058 case_expr->Visit(&for_case_expression);
1040 // Append only the first one, everything else is connected from it. 1059 // Append only the first one, everything else is connected from it.
1041 Append(for_case_expression); 1060 Append(for_case_expression);
1042 } else { 1061 } else {
1043 TargetEntryInstr* case_entry_target = new TargetEntryInstr(); 1062 TargetEntryInstr* case_entry_target = new TargetEntryInstr();
1044 case_entries.Add(case_entry_target); 1063 case_entries.Add(case_entry_target);
1045 for_case_expression.AddInstruction(case_entry_target); 1064 for_case_expression.AddBlockEntry(case_entry_target);
1046 case_expr->Visit(&for_case_expression); 1065 case_expr->Visit(&for_case_expression);
1047 } 1066 }
1048 case_true_addresses.Add(for_case_expression.true_successor_address()); 1067 case_true_addresses.Add(for_case_expression.true_successor_address());
1049 case_false_addresses.Add(for_case_expression.false_successor_address()); 1068 case_false_addresses.Add(for_case_expression.false_successor_address());
1050 } 1069 }
1051 1070
1052 // Once a test fragment has been added, this fragment is closed. 1071 // Once a test fragment has been added, this fragment is closed.
1053 ASSERT(!is_open()); 1072 ASSERT(!is_open());
1054 1073
1055 // Connect all test cases except the last one. 1074 // Connect all test cases except the last one.
1056 for (intptr_t i = 0; i < (len - 1); i++) { 1075 for (intptr_t i = 0; i < (len - 1); i++) {
1057 ASSERT(needs_join_at_statement_entry); 1076 ASSERT(needs_join_at_statement_entry);
1058 *case_false_addresses[i] = case_entries[i + 1]; 1077 *case_false_addresses[i] = case_entries[i + 1];
1059 TargetEntryInstr* true_target = new TargetEntryInstr(); 1078 TargetEntryInstr* true_target = new TargetEntryInstr();
1060 *case_true_addresses[i] = true_target; 1079 *case_true_addresses[i] = true_target;
1061 true_target->SetSuccessor(statement_start); 1080 true_target->SetSuccessor(new GotoInstr(statement_start));
1062 } 1081 }
1063 1082
1064 BlockEntryInstr* exit_instruction = NULL; 1083 BlockEntryInstr* exit_instruction = NULL;
1065 // Handle last (or only) case: false goes to exit or to statement if this 1084 // Handle last (or only) case: false goes to exit or to statement if this
1066 // node contains default. 1085 // node contains default.
1067 if (len > 0) { 1086 if (len > 0) {
1068 if (statement_start->IsTargetEntry()) { 1087 if (statement_start->IsTargetEntry()) {
1069 *case_true_addresses[len - 1] = statement_start->AsTargetEntry(); 1088 *case_true_addresses[len - 1] = statement_start->AsTargetEntry();
1070 } else { 1089 } else {
1071 TargetEntryInstr* true_target = new TargetEntryInstr(); 1090 TargetEntryInstr* true_target = new TargetEntryInstr();
1072 *case_true_addresses[len - 1] = true_target; 1091 *case_true_addresses[len - 1] = true_target;
1073 true_target->SetSuccessor(statement_start); 1092 true_target->SetSuccessor(new GotoInstr(statement_start));
1074 } 1093 }
1075 TargetEntryInstr* false_target = new TargetEntryInstr(); 1094 TargetEntryInstr* false_target = new TargetEntryInstr();
1076 *case_false_addresses[len - 1] = false_target; 1095 *case_false_addresses[len - 1] = false_target;
1077 if (node->contains_default()) { 1096 if (node->contains_default()) {
1078 // True and false go to statement start. 1097 // True and false go to statement start.
1079 false_target->SetSuccessor(statement_start); 1098 false_target->SetSuccessor(new GotoInstr(statement_start));
1080 if (for_case_statements.is_open()) { 1099 if (for_case_statements.is_open()) {
1081 exit_instruction = new TargetEntryInstr(); 1100 exit_instruction = new TargetEntryInstr();
1082 for_case_statements.exit()->SetSuccessor(exit_instruction); 1101 for_case_statements.exit()->SetSuccessor(
1102 new GotoInstr(exit_instruction));
1083 } 1103 }
1084 } else { 1104 } else {
1085 if (for_case_statements.is_open()) { 1105 if (for_case_statements.is_open()) {
1086 exit_instruction = new JoinEntryInstr(); 1106 exit_instruction = new JoinEntryInstr();
1087 for_case_statements.exit()->SetSuccessor(exit_instruction); 1107 for_case_statements.exit()->SetSuccessor(
1108 new GotoInstr(exit_instruction));
1088 } else { 1109 } else {
1089 exit_instruction = new TargetEntryInstr(); 1110 exit_instruction = new TargetEntryInstr();
1090 } 1111 }
1091 false_target->SetSuccessor(exit_instruction); 1112 false_target->SetSuccessor(new GotoInstr(exit_instruction));
1092 } 1113 }
1093 } else { 1114 } else {
1094 // A CaseNode without case expressions must contain default. 1115 // A CaseNode without case expressions must contain default.
1095 ASSERT(node->contains_default()); 1116 ASSERT(node->contains_default());
1096 AddInstruction(statement_start); 1117 AddInstruction(new GotoInstr(statement_start));
1118 AddBlockEntry(statement_start);
1097 } 1119 }
1098 1120
1099 ASSERT(!is_open()); 1121 ASSERT(!is_open());
1100 exit_ = exit_instruction; 1122 exit_ = exit_instruction;
1101 } 1123 }
1102 1124
1103 1125
1104 // <Statement> ::= While { label: SourceLabel 1126 // <Statement> ::= While { label: SourceLabel
1105 // condition: <Expression> 1127 // condition: <Expression>
1106 // body: <Sequence> } 1128 // body: <Sequence> }
(...skipping 15 matching lines...) Expand all
1122 EffectGraphVisitor for_body(owner(), temp_index()); 1144 EffectGraphVisitor for_body(owner(), temp_index());
1123 CheckStackOverflowComp* comp = 1145 CheckStackOverflowComp* comp =
1124 new CheckStackOverflowComp(node->token_pos(), owner()->try_index()); 1146 new CheckStackOverflowComp(node->token_pos(), owner()->try_index());
1125 for_body.AddInstruction(new DoInstr(comp)); 1147 for_body.AddInstruction(new DoInstr(comp));
1126 node->body()->Visit(&for_body); 1148 node->body()->Visit(&for_body);
1127 1149
1128 // Labels are set after body traversal. 1150 // Labels are set after body traversal.
1129 SourceLabel* lbl = node->label(); 1151 SourceLabel* lbl = node->label();
1130 ASSERT(lbl != NULL); 1152 ASSERT(lbl != NULL);
1131 if (lbl->join_for_continue() != NULL) { 1153 if (lbl->join_for_continue() != NULL) {
1132 AddInstruction(lbl->join_for_continue()); 1154 AddInstruction(new GotoInstr(lbl->join_for_continue()));
1155 AddBlockEntry(lbl->join_for_continue());
1133 } 1156 }
1134 TieLoop(for_test, for_body); 1157 TieLoop(for_test, for_body);
1135 if (lbl->join_for_break() != NULL) { 1158 if (lbl->join_for_break() != NULL) {
1136 AddInstruction(lbl->join_for_break()); 1159 AddInstruction(new GotoInstr(lbl->join_for_break()));
1160 AddBlockEntry(lbl->join_for_break());
1137 } 1161 }
1138 } 1162 }
1139 1163
1140 1164
1141 // The fragment is composed as follows: 1165 // The fragment is composed as follows:
1142 // a) body-entry-join 1166 // a) body-entry-join
1143 // b) [ body ] 1167 // b) [ body ]
1144 // c) test-entry (continue-join or body-exit-target) 1168 // c) test-entry (continue-join or body-exit-target)
1145 // d) [ test-entry ] -> (back-target, loop-exit-target) 1169 // d) [ test-entry ] -> (back-target, loop-exit-target)
1146 // e) back-target -> (body-entry-join) 1170 // e) back-target -> (body-entry-join)
1147 // f) loop-exit-target 1171 // f) loop-exit-target
1148 // g) break-join 1172 // g) break-join
1149 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { 1173 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) {
1150 // Traverse body first in order to generate continue and break labels. 1174 // Traverse body first in order to generate continue and break labels.
1151 EffectGraphVisitor for_body(owner(), temp_index()); 1175 EffectGraphVisitor for_body(owner(), temp_index());
1152 CheckStackOverflowComp* comp = 1176 CheckStackOverflowComp* comp =
1153 new CheckStackOverflowComp(node->token_pos(), owner()->try_index()); 1177 new CheckStackOverflowComp(node->token_pos(), owner()->try_index());
1154 for_body.AddInstruction(new DoInstr(comp)); 1178 for_body.AddInstruction(new DoInstr(comp));
1155 node->body()->Visit(&for_body); 1179 node->body()->Visit(&for_body);
1156 1180
1157 TestGraphVisitor for_test(owner(), 1181 TestGraphVisitor for_test(owner(),
1158 temp_index(), 1182 temp_index(),
1159 node->condition()->token_pos()); 1183 node->condition()->token_pos());
1160 node->condition()->Visit(&for_test); 1184 node->condition()->Visit(&for_test);
1161 ASSERT(is_open()); 1185 ASSERT(is_open());
1162 1186
1163 // Tie do-while loop (test is after the body). 1187 // Tie do-while loop (test is after the body).
1164 JoinEntryInstr* body_entry_join = new JoinEntryInstr(); 1188 JoinEntryInstr* body_entry_join = new JoinEntryInstr();
1165 AddInstruction(body_entry_join); 1189 AddInstruction(new GotoInstr(body_entry_join));
1190 AddBlockEntry(body_entry_join);
1166 body_entry_join->SetSuccessor(for_body.entry()); 1191 body_entry_join->SetSuccessor(for_body.entry());
1167 Instruction* body_exit = 1192 Instruction* body_exit =
1168 for_body.is_empty() ? body_entry_join : for_body.exit(); 1193 for_body.is_empty() ? body_entry_join : for_body.exit();
1169 1194
1170 if (for_body.is_open() || (node->label()->join_for_continue() != NULL)) { 1195 if (for_body.is_open() || (node->label()->join_for_continue() != NULL)) {
1171 BlockEntryInstr* test_entry = NULL; 1196 BlockEntryInstr* test_entry = NULL;
1172 if (node->label()->join_for_continue() == NULL) { 1197 if (node->label()->join_for_continue() == NULL) {
1173 test_entry = new TargetEntryInstr(); 1198 test_entry = new TargetEntryInstr();
1174 } else { 1199 } else {
1175 test_entry = node->label()->join_for_continue(); 1200 test_entry = node->label()->join_for_continue();
1176 } 1201 }
1177 test_entry->SetSuccessor(for_test.entry()); 1202 test_entry->SetSuccessor(for_test.entry());
1178 if (body_exit != NULL) { 1203 if (body_exit != NULL) {
1179 body_exit->SetSuccessor(test_entry); 1204 body_exit->SetSuccessor(new GotoInstr(test_entry));
1180 } 1205 }
1181 } 1206 }
1182 1207
1183 TargetEntryInstr* back_target_entry = new TargetEntryInstr(); 1208 TargetEntryInstr* back_target_entry = new TargetEntryInstr();
1184 *for_test.true_successor_address() = back_target_entry; 1209 *for_test.true_successor_address() = back_target_entry;
1185 back_target_entry->SetSuccessor(body_entry_join); 1210 back_target_entry->SetSuccessor(new GotoInstr(body_entry_join));
1186 TargetEntryInstr* loop_exit_target = new TargetEntryInstr(); 1211 TargetEntryInstr* loop_exit_target = new TargetEntryInstr();
1187 *for_test.false_successor_address() = loop_exit_target; 1212 *for_test.false_successor_address() = loop_exit_target;
1188 if (node->label()->join_for_break() == NULL) { 1213 if (node->label()->join_for_break() == NULL) {
1189 exit_ = loop_exit_target; 1214 exit_ = loop_exit_target;
1190 } else { 1215 } else {
1191 loop_exit_target->SetSuccessor(node->label()->join_for_break()); 1216 loop_exit_target->SetSuccessor(
1217 new GotoInstr(node->label()->join_for_break()));
1192 exit_ = node->label()->join_for_break(); 1218 exit_ = node->label()->join_for_break();
1193 } 1219 }
1194 } 1220 }
1195 1221
1196 1222
1197 // A ForNode can contain break and continue jumps. 'break' joins to 1223 // A ForNode can contain break and continue jumps. 'break' joins to
1198 // ForNode exit, 'continue' joins at increment entry. The fragment is composed 1224 // ForNode exit, 'continue' joins at increment entry. The fragment is composed
1199 // as follows: 1225 // as follows:
1200 // a) [ initializer ] 1226 // a) [ initializer ]
1201 // b) loop-join 1227 // b) loop-join
1202 // c) [ test ] -> (body-entry-target, loop-exit-target) 1228 // c) [ test ] -> (body-entry-target, loop-exit-target)
1203 // d) body-entry-target 1229 // d) body-entry-target
1204 // e) [ body ] 1230 // e) [ body ]
1205 // f) continue-join (optional) 1231 // f) continue-join (optional)
1206 // g) [ increment ] -> (loop-join) 1232 // g) [ increment ] -> (loop-join)
1207 // h) loop-exit-target 1233 // h) loop-exit-target
1208 // i) break-join 1234 // i) break-join
1209 void EffectGraphVisitor::VisitForNode(ForNode* node) { 1235 void EffectGraphVisitor::VisitForNode(ForNode* node) {
1210 EffectGraphVisitor for_initializer(owner(), temp_index()); 1236 EffectGraphVisitor for_initializer(owner(), temp_index());
1211 node->initializer()->Visit(&for_initializer); 1237 node->initializer()->Visit(&for_initializer);
1212 Append(for_initializer); 1238 Append(for_initializer);
1213 ASSERT(is_open()); 1239 ASSERT(is_open());
1214 1240
1215 // Compose body to set any jump labels. 1241 // Compose body to set any jump labels.
1216 EffectGraphVisitor for_body(owner(), temp_index()); 1242 EffectGraphVisitor for_body(owner(), temp_index());
1217 TargetEntryInstr* body_entry = new TargetEntryInstr(); 1243 TargetEntryInstr* body_entry = new TargetEntryInstr();
1218 for_body.AddInstruction(body_entry); 1244 for_body.AddBlockEntry(body_entry);
1219 CheckStackOverflowComp* comp = 1245 CheckStackOverflowComp* comp =
1220 new CheckStackOverflowComp(node->token_pos(), owner()->try_index()); 1246 new CheckStackOverflowComp(node->token_pos(), owner()->try_index());
1221 for_body.AddInstruction(new DoInstr(comp)); 1247 for_body.AddInstruction(new DoInstr(comp));
1222 node->body()->Visit(&for_body); 1248 node->body()->Visit(&for_body);
1223 1249
1224 // Join loop body, increment and compute their end instruction. 1250 // Join loop body, increment and compute their end instruction.
1225 ASSERT(!for_body.is_empty()); 1251 ASSERT(!for_body.is_empty());
1226 Instruction* loop_increment_end = NULL; 1252 Instruction* loop_increment_end = NULL;
1227 EffectGraphVisitor for_increment(owner(), temp_index()); 1253 EffectGraphVisitor for_increment(owner(), temp_index());
1228 if ((node->label()->join_for_continue() == NULL) && for_body.is_open()) { 1254 if ((node->label()->join_for_continue() == NULL) && for_body.is_open()) {
1229 // Do not insert an extra basic block. 1255 // Do not insert an extra basic block.
1230 node->increment()->Visit(&for_increment); 1256 node->increment()->Visit(&for_increment);
1231 for_body.Append(for_increment); 1257 for_body.Append(for_increment);
1232 loop_increment_end = for_body.exit(); 1258 loop_increment_end = for_body.exit();
1233 // 'for_body' contains at least the TargetInstruction 'body_entry'. 1259 // 'for_body' contains at least the TargetInstruction 'body_entry'.
1234 ASSERT(loop_increment_end != NULL); 1260 ASSERT(loop_increment_end != NULL);
1235 } else if (node->label()->join_for_continue() != NULL) { 1261 } else if (node->label()->join_for_continue() != NULL) {
1236 // Insert join between body and increment. 1262 // Insert join between body and increment.
1237 if (for_body.is_open()) { 1263 if (for_body.is_open()) {
1238 for_body.exit()->SetSuccessor(node->label()->join_for_continue()); 1264 for_body.exit()->SetSuccessor(
1265 new GotoInstr(node->label()->join_for_continue()));
1239 } 1266 }
1240 for_increment.AddInstruction(node->label()->join_for_continue()); 1267 for_increment.AddBlockEntry(node->label()->join_for_continue());
1241 node->increment()->Visit(&for_increment); 1268 node->increment()->Visit(&for_increment);
1242 loop_increment_end = for_increment.exit(); 1269 loop_increment_end = for_increment.exit();
1243 ASSERT(loop_increment_end != NULL); 1270 ASSERT(loop_increment_end != NULL);
1244 } else { 1271 } else {
1245 loop_increment_end = NULL; 1272 loop_increment_end = NULL;
1246 ASSERT(!for_body.is_open() && node->label()->join_for_continue() == NULL); 1273 ASSERT(!for_body.is_open() && node->label()->join_for_continue() == NULL);
1247 } 1274 }
1248 1275
1249 // 'loop_increment_end' is NULL only if there is no join for continue and the 1276 // 'loop_increment_end' is NULL only if there is no join for continue and the
1250 // body is not open, i.e., no backward branch exists. 1277 // body is not open, i.e., no backward branch exists.
1251 if (loop_increment_end != NULL) { 1278 if (loop_increment_end != NULL) {
1252 JoinEntryInstr* loop_start = new JoinEntryInstr(); 1279 JoinEntryInstr* loop_start = new JoinEntryInstr();
1253 AddInstruction(loop_start); 1280 AddInstruction(new GotoInstr(loop_start));
1254 loop_increment_end->SetSuccessor(loop_start); 1281 AddBlockEntry(loop_start);
1282 loop_increment_end->SetSuccessor(new GotoInstr(loop_start));
1255 } 1283 }
1256 1284
1257 if (node->condition() == NULL) { 1285 if (node->condition() == NULL) {
1258 // Endless loop, no test. 1286 // Endless loop, no test.
1259 Append(for_body); 1287 Append(for_body);
1260 if (node->label()->join_for_break() == NULL) { 1288 if (node->label()->join_for_break() == NULL) {
1261 CloseFragment(); 1289 CloseFragment();
1262 } else { 1290 } else {
1263 // Control flow of ForLoop continues into join_for_break. 1291 // Control flow of ForLoop continues into join_for_break.
1264 exit_ = node->label()->join_for_break(); 1292 exit_ = node->label()->join_for_break();
1265 } 1293 }
1266 } else { 1294 } else {
1267 TargetEntryInstr* loop_exit = new TargetEntryInstr(); 1295 TargetEntryInstr* loop_exit = new TargetEntryInstr();
1268 TestGraphVisitor for_test(owner(), 1296 TestGraphVisitor for_test(owner(),
1269 temp_index(), 1297 temp_index(),
1270 node->condition()->token_pos()); 1298 node->condition()->token_pos());
1271 node->condition()->Visit(&for_test); 1299 node->condition()->Visit(&for_test);
1272 Append(for_test); 1300 Append(for_test);
1273 *for_test.true_successor_address() = body_entry; 1301 *for_test.true_successor_address() = body_entry;
1274 *for_test.false_successor_address() = loop_exit; 1302 *for_test.false_successor_address() = loop_exit;
1275 if (node->label()->join_for_break() == NULL) { 1303 if (node->label()->join_for_break() == NULL) {
1276 exit_ = loop_exit; 1304 exit_ = loop_exit;
1277 } else { 1305 } else {
1278 loop_exit->SetSuccessor(node->label()->join_for_break()); 1306 loop_exit->SetSuccessor(new GotoInstr(node->label()->join_for_break()));
1279 exit_ = node->label()->join_for_break(); 1307 exit_ = node->label()->join_for_break();
1280 } 1308 }
1281 } 1309 }
1282 } 1310 }
1283 1311
1284 1312
1285 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { 1313 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) {
1286 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { 1314 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) {
1287 EffectGraphVisitor for_effect(owner(), temp_index()); 1315 EffectGraphVisitor for_effect(owner(), temp_index());
1288 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); 1316 node->InlinedFinallyNodeAt(i)->Visit(&for_effect);
(...skipping 22 matching lines...) Expand all
1311 target_context_level = target_scope->context_level(); 1339 target_context_level = target_scope->context_level();
1312 } 1340 }
1313 } 1341 }
1314 ASSERT(target_context_level >= 0); 1342 ASSERT(target_context_level >= 0);
1315 intptr_t current_context_level = owner()->context_level(); 1343 intptr_t current_context_level = owner()->context_level();
1316 ASSERT(current_context_level >= target_context_level); 1344 ASSERT(current_context_level >= target_context_level);
1317 while (current_context_level-- > target_context_level) { 1345 while (current_context_level-- > target_context_level) {
1318 UnchainContext(); 1346 UnchainContext();
1319 } 1347 }
1320 1348
1321 Instruction* jump_target = NULL; 1349 BlockEntryInstr* jump_target = NULL;
1322 if (node->kind() == Token::kBREAK) { 1350 if (node->kind() == Token::kBREAK) {
1323 if (node->label()->join_for_break() == NULL) { 1351 if (node->label()->join_for_break() == NULL) {
1324 node->label()->set_join_for_break(new JoinEntryInstr()); 1352 node->label()->set_join_for_break(new JoinEntryInstr());
1325 } 1353 }
1326 jump_target = node->label()->join_for_break(); 1354 jump_target = node->label()->join_for_break();
1327 } else { 1355 } else {
1328 if (node->label()->join_for_continue() == NULL) { 1356 if (node->label()->join_for_continue() == NULL) {
1329 node->label()->set_join_for_continue(new JoinEntryInstr()); 1357 node->label()->set_join_for_continue(new JoinEntryInstr());
1330 } 1358 }
1331 jump_target = node->label()->join_for_continue(); 1359 jump_target = node->label()->join_for_continue();
1332 } 1360 }
1333 AddInstruction(jump_target); 1361 AddInstruction(new GotoInstr(jump_target));
1362 AddBlockEntry(jump_target);
1334 CloseFragment(); 1363 CloseFragment();
1335 } 1364 }
1336 1365
1337 1366
1338 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) { 1367 void EffectGraphVisitor::VisitArgumentListNode(ArgumentListNode* node) {
1339 UNREACHABLE(); 1368 UNREACHABLE();
1340 } 1369 }
1341 1370
1342 1371
1343 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) { 1372 void EffectGraphVisitor::VisitArrayNode(ArrayNode* node) {
(...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after
2219 } 2248 }
2220 2249
2221 // No continue on sequence allowed. 2250 // No continue on sequence allowed.
2222 ASSERT((node->label() == NULL) || 2251 ASSERT((node->label() == NULL) ||
2223 (node->label()->join_for_continue() == NULL)); 2252 (node->label()->join_for_continue() == NULL));
2224 // If this node sequence is labeled, a break out of the sequence will have 2253 // If this node sequence is labeled, a break out of the sequence will have
2225 // taken care of unchaining the context. 2254 // taken care of unchaining the context.
2226 if ((node->label() != NULL) && 2255 if ((node->label() != NULL) &&
2227 (node->label()->join_for_break() != NULL)) { 2256 (node->label()->join_for_break() != NULL)) {
2228 if (is_open()) { 2257 if (is_open()) {
2229 AddInstruction(node->label()->join_for_break()); 2258 AddInstruction(new GotoInstr(node->label()->join_for_break()));
2259 AddBlockEntry(node->label()->join_for_break());
2230 } else { 2260 } else {
2231 exit_ = node->label()->join_for_break(); 2261 exit_ = node->label()->join_for_break();
2232 } 2262 }
2233 } 2263 }
2234 2264
2235 // The outermost function sequence cannot contain a label. 2265 // The outermost function sequence cannot contain a label.
2236 ASSERT((node->label() == NULL) || 2266 ASSERT((node->label() == NULL) ||
2237 (node != owner()->parsed_function().node_sequence())); 2267 (node != owner()->parsed_function().node_sequence()));
2238 owner()->set_context_level(previous_context_level); 2268 owner()->set_context_level(previous_context_level);
2239 } 2269 }
(...skipping 30 matching lines...) Expand all
2270 owner()->set_try_index(old_try_index); 2300 owner()->set_try_index(old_try_index);
2271 2301
2272 CatchClauseNode* catch_block = node->catch_block(); 2302 CatchClauseNode* catch_block = node->catch_block();
2273 if (catch_block != NULL) { 2303 if (catch_block != NULL) {
2274 // Set the corresponding try index for this catch block so 2304 // Set the corresponding try index for this catch block so
2275 // that we can set the appropriate handler pc when we generate 2305 // that we can set the appropriate handler pc when we generate
2276 // code for this catch block. 2306 // code for this catch block.
2277 catch_block->set_try_index(try_index); 2307 catch_block->set_try_index(try_index);
2278 EffectGraphVisitor for_catch_block(owner(), temp_index()); 2308 EffectGraphVisitor for_catch_block(owner(), temp_index());
2279 TargetEntryInstr* catch_entry = new TargetEntryInstr(try_index); 2309 TargetEntryInstr* catch_entry = new TargetEntryInstr(try_index);
2280 for_catch_block.AddInstruction(catch_entry); 2310 for_catch_block.AddBlockEntry(catch_entry);
2281 catch_block->Visit(&for_catch_block); 2311 catch_block->Visit(&for_catch_block);
2282 owner()->AddCatchEntry(catch_entry); 2312 owner()->AddCatchEntry(catch_entry);
2283 ASSERT(!for_catch_block.is_open()); 2313 ASSERT(!for_catch_block.is_open());
2284 if ((node->end_catch_label() != NULL) && 2314 if ((node->end_catch_label() != NULL) &&
2285 (node->end_catch_label()->join_for_continue() != NULL)) { 2315 (node->end_catch_label()->join_for_continue() != NULL)) {
2286 if (is_open()) { 2316 if (is_open()) {
2287 AddInstruction(node->end_catch_label()->join_for_continue()); 2317 AddInstruction(
2318 new GotoInstr(node->end_catch_label()->join_for_continue()));
2319 AddBlockEntry(node->end_catch_label()->join_for_continue());
2288 } else { 2320 } else {
2289 exit_ = node->end_catch_label()->join_for_continue(); 2321 exit_ = node->end_catch_label()->join_for_continue();
2290 } 2322 }
2291 } 2323 }
2292 } 2324 }
2293 2325
2294 // Generate code for the finally block if one exists. 2326 // Generate code for the finally block if one exists.
2295 if ((node->finally_block() != NULL) && is_open()) { 2327 if ((node->finally_block() != NULL) && is_open()) {
2296 EffectGraphVisitor for_finally_block(owner(), temp_index()); 2328 EffectGraphVisitor for_finally_block(owner(), temp_index());
2297 node->finally_block()->Visit(&for_finally_block); 2329 node->finally_block()->Visit(&for_finally_block);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2358 void FlowGraphBuilder::BuildGraph(bool for_optimized, bool use_ssa) { 2390 void FlowGraphBuilder::BuildGraph(bool for_optimized, bool use_ssa) {
2359 if (FLAG_print_ast) { 2391 if (FLAG_print_ast) {
2360 // Print the function ast before IL generation. 2392 // Print the function ast before IL generation.
2361 AstPrinter::PrintFunctionNodes(parsed_function()); 2393 AstPrinter::PrintFunctionNodes(parsed_function());
2362 } 2394 }
2363 // Compilation can be nested, preserve the computation-id. 2395 // Compilation can be nested, preserve the computation-id.
2364 const Function& function = parsed_function().function(); 2396 const Function& function = parsed_function().function();
2365 TargetEntryInstr* normal_entry = new TargetEntryInstr(); 2397 TargetEntryInstr* normal_entry = new TargetEntryInstr();
2366 graph_entry_ = new GraphEntryInstr(normal_entry); 2398 graph_entry_ = new GraphEntryInstr(normal_entry);
2367 EffectGraphVisitor for_effect(this, 0); 2399 EffectGraphVisitor for_effect(this, 0);
2368 for_effect.AddInstruction(normal_entry); 2400 for_effect.AddBlockEntry(normal_entry);
2369 parsed_function().node_sequence()->Visit(&for_effect); 2401 parsed_function().node_sequence()->Visit(&for_effect);
2370 // Check that the graph is properly terminated. 2402 // Check that the graph is properly terminated.
2371 ASSERT(!for_effect.is_open()); 2403 ASSERT(!for_effect.is_open());
2372 GrowableArray<intptr_t> parent; 2404 GrowableArray<intptr_t> parent;
2373 GrowableArray<BitVector*> assigned_vars; 2405 GrowableArray<BitVector*> assigned_vars;
2374 intptr_t variable_count = parsed_function_.function().num_fixed_parameters() + 2406 intptr_t variable_count = parsed_function_.function().num_fixed_parameters() +
2375 parsed_function_.copied_parameter_count() + 2407 parsed_function_.copied_parameter_count() +
2376 parsed_function_.stack_local_count(); 2408 parsed_function_.stack_local_count();
2377 // Perform a depth-first traversal of the graph to build preorder and 2409 // Perform a depth-first traversal of the graph to build preorder and
2378 // postorder block orders. 2410 // postorder block orders.
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after
2767 char* chars = reinterpret_cast<char*>( 2799 char* chars = reinterpret_cast<char*>(
2768 Isolate::Current()->current_zone()->Allocate(len)); 2800 Isolate::Current()->current_zone()->Allocate(len));
2769 OS::SNPrint(chars, len, kFormat, function_name, reason); 2801 OS::SNPrint(chars, len, kFormat, function_name, reason);
2770 const Error& error = Error::Handle( 2802 const Error& error = Error::Handle(
2771 LanguageError::New(String::Handle(String::New(chars)))); 2803 LanguageError::New(String::Handle(String::New(chars))));
2772 Isolate::Current()->long_jump_base()->Jump(1, error); 2804 Isolate::Current()->long_jump_base()->Jump(1, error);
2773 } 2805 }
2774 2806
2775 2807
2776 } // namespace dart 2808 } // namespace dart
OLDNEW
« no previous file with comments | « vm/flow_graph_builder.h ('k') | vm/flow_graph_compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698