| 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 "vm/ast_printer.h" | 7 #include "vm/ast_printer.h" |
| 8 #include "vm/code_descriptors.h" | 8 #include "vm/code_descriptors.h" |
| 9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flags.h" | 10 #include "vm/flags.h" |
| (...skipping 1075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1086 // e) true-target-0 -> case-statements-join | 1086 // e) true-target-0 -> case-statements-join |
| 1087 // f) true-target-1 -> case-statements-join | 1087 // f) true-target-1 -> case-statements-join |
| 1088 // g) case-statements-join | 1088 // g) case-statements-join |
| 1089 // h) [ case-statements ] -> exit-join | 1089 // h) [ case-statements ] -> exit-join |
| 1090 // i) exit-target -> exit-join | 1090 // i) exit-target -> exit-join |
| 1091 // j) exit-join | 1091 // j) exit-join |
| 1092 // | 1092 // |
| 1093 // Note: The specification of switch/case is under discussion and may change | 1093 // Note: The specification of switch/case is under discussion and may change |
| 1094 // drastically. | 1094 // drastically. |
| 1095 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) { | 1095 void EffectGraphVisitor::VisitCaseNode(CaseNode* node) { |
| 1096 InlineBailout("EffectGraphVisitor::VisitCaseNode (control)"); |
| 1096 const intptr_t len = node->case_expressions()->length(); | 1097 const intptr_t len = node->case_expressions()->length(); |
| 1097 // Create case statements instructions. | 1098 // Create case statements instructions. |
| 1098 EffectGraphVisitor for_case_statements(owner(), temp_index()); | 1099 EffectGraphVisitor for_case_statements(owner(), temp_index()); |
| 1099 // Compute start of statements fragment. | 1100 // Compute start of statements fragment. |
| 1100 JoinEntryInstr* statement_start = NULL; | 1101 JoinEntryInstr* statement_start = NULL; |
| 1101 if ((node->label() != NULL) && node->label()->is_continue_target()) { | 1102 if ((node->label() != NULL) && node->label()->is_continue_target()) { |
| 1102 // Since a labeled jump continue statement occur in a different case node, | 1103 // Since a labeled jump continue statement occur in a different case node, |
| 1103 // allocate JoinNode here and use it as statement start. | 1104 // allocate JoinNode here and use it as statement start. |
| 1104 statement_start = node->label()->join_for_continue(); | 1105 statement_start = node->label()->join_for_continue(); |
| 1105 if (statement_start == NULL) { | 1106 if (statement_start == NULL) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1181 // body: <Sequence> } | 1182 // body: <Sequence> } |
| 1182 // The fragment is composed as follows: | 1183 // The fragment is composed as follows: |
| 1183 // a) loop-join | 1184 // a) loop-join |
| 1184 // b) [ test ] -> (body-entry-target, loop-exit-target) | 1185 // b) [ test ] -> (body-entry-target, loop-exit-target) |
| 1185 // c) body-entry-target | 1186 // c) body-entry-target |
| 1186 // d) [ body ] -> (continue-join) | 1187 // d) [ body ] -> (continue-join) |
| 1187 // e) continue-join -> (loop-join) | 1188 // e) continue-join -> (loop-join) |
| 1188 // f) loop-exit-target | 1189 // f) loop-exit-target |
| 1189 // g) break-join (optional) | 1190 // g) break-join (optional) |
| 1190 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { | 1191 void EffectGraphVisitor::VisitWhileNode(WhileNode* node) { |
| 1192 InlineBailout("EffectGraphVisitor::VisitWhileNode (control)"); |
| 1191 TestGraphVisitor for_test(owner(), | 1193 TestGraphVisitor for_test(owner(), |
| 1192 temp_index(), | 1194 temp_index(), |
| 1193 node->condition()->token_pos()); | 1195 node->condition()->token_pos()); |
| 1194 node->condition()->Visit(&for_test); | 1196 node->condition()->Visit(&for_test); |
| 1195 ASSERT(!for_test.is_empty()); // Language spec. | 1197 ASSERT(!for_test.is_empty()); // Language spec. |
| 1196 | 1198 |
| 1197 EffectGraphVisitor for_body(owner(), temp_index()); | 1199 EffectGraphVisitor for_body(owner(), temp_index()); |
| 1198 for_body.AddInstruction( | 1200 for_body.AddInstruction( |
| 1199 new CheckStackOverflowInstr(node->token_pos())); | 1201 new CheckStackOverflowInstr(node->token_pos())); |
| 1200 node->body()->Visit(&for_body); | 1202 node->body()->Visit(&for_body); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1218 | 1220 |
| 1219 // The fragment is composed as follows: | 1221 // The fragment is composed as follows: |
| 1220 // a) body-entry-join | 1222 // a) body-entry-join |
| 1221 // b) [ body ] | 1223 // b) [ body ] |
| 1222 // c) test-entry (continue-join or body-exit-target) | 1224 // c) test-entry (continue-join or body-exit-target) |
| 1223 // d) [ test-entry ] -> (back-target, loop-exit-target) | 1225 // d) [ test-entry ] -> (back-target, loop-exit-target) |
| 1224 // e) back-target -> (body-entry-join) | 1226 // e) back-target -> (body-entry-join) |
| 1225 // f) loop-exit-target | 1227 // f) loop-exit-target |
| 1226 // g) break-join | 1228 // g) break-join |
| 1227 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { | 1229 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { |
| 1230 InlineBailout("EffectGraphVisitor::VisitDoWhileNode (control)"); |
| 1228 // Traverse body first in order to generate continue and break labels. | 1231 // Traverse body first in order to generate continue and break labels. |
| 1229 EffectGraphVisitor for_body(owner(), temp_index()); | 1232 EffectGraphVisitor for_body(owner(), temp_index()); |
| 1230 for_body.AddInstruction( | 1233 for_body.AddInstruction( |
| 1231 new CheckStackOverflowInstr(node->token_pos())); | 1234 new CheckStackOverflowInstr(node->token_pos())); |
| 1232 node->body()->Visit(&for_body); | 1235 node->body()->Visit(&for_body); |
| 1233 | 1236 |
| 1234 TestGraphVisitor for_test(owner(), | 1237 TestGraphVisitor for_test(owner(), |
| 1235 temp_index(), | 1238 temp_index(), |
| 1236 node->condition()->token_pos()); | 1239 node->condition()->token_pos()); |
| 1237 node->condition()->Visit(&for_test); | 1240 node->condition()->Visit(&for_test); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1272 // a) [ initializer ] | 1275 // a) [ initializer ] |
| 1273 // b) loop-join | 1276 // b) loop-join |
| 1274 // c) [ test ] -> (body-entry-target, loop-exit-target) | 1277 // c) [ test ] -> (body-entry-target, loop-exit-target) |
| 1275 // d) body-entry-target | 1278 // d) body-entry-target |
| 1276 // e) [ body ] | 1279 // e) [ body ] |
| 1277 // f) continue-join (optional) | 1280 // f) continue-join (optional) |
| 1278 // g) [ increment ] -> (loop-join) | 1281 // g) [ increment ] -> (loop-join) |
| 1279 // h) loop-exit-target | 1282 // h) loop-exit-target |
| 1280 // i) break-join | 1283 // i) break-join |
| 1281 void EffectGraphVisitor::VisitForNode(ForNode* node) { | 1284 void EffectGraphVisitor::VisitForNode(ForNode* node) { |
| 1285 InlineBailout("EffectGraphVisitor::VisitForNode (control)"); |
| 1282 EffectGraphVisitor for_initializer(owner(), temp_index()); | 1286 EffectGraphVisitor for_initializer(owner(), temp_index()); |
| 1283 node->initializer()->Visit(&for_initializer); | 1287 node->initializer()->Visit(&for_initializer); |
| 1284 Append(for_initializer); | 1288 Append(for_initializer); |
| 1285 ASSERT(is_open()); | 1289 ASSERT(is_open()); |
| 1286 | 1290 |
| 1287 // Compose body to set any jump labels. | 1291 // Compose body to set any jump labels. |
| 1288 EffectGraphVisitor for_body(owner(), temp_index()); | 1292 EffectGraphVisitor for_body(owner(), temp_index()); |
| 1289 for_body.AddInstruction( | 1293 for_body.AddInstruction( |
| 1290 new CheckStackOverflowInstr(node->token_pos())); | 1294 new CheckStackOverflowInstr(node->token_pos())); |
| 1291 node->body()->Visit(&for_body); | 1295 node->body()->Visit(&for_body); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1345 exit_ = for_test.CreateFalseSuccessor(); | 1349 exit_ = for_test.CreateFalseSuccessor(); |
| 1346 } else { | 1350 } else { |
| 1347 for_test.IfFalseGoto(node->label()->join_for_break()); | 1351 for_test.IfFalseGoto(node->label()->join_for_break()); |
| 1348 exit_ = node->label()->join_for_break(); | 1352 exit_ = node->label()->join_for_break(); |
| 1349 } | 1353 } |
| 1350 } | 1354 } |
| 1351 } | 1355 } |
| 1352 | 1356 |
| 1353 | 1357 |
| 1354 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { | 1358 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { |
| 1359 InlineBailout("EffectGraphVisitor::VisitJumpNode (control)"); |
| 1355 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { | 1360 for (intptr_t i = 0; i < node->inlined_finally_list_length(); i++) { |
| 1356 EffectGraphVisitor for_effect(owner(), temp_index()); | 1361 EffectGraphVisitor for_effect(owner(), temp_index()); |
| 1357 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); | 1362 node->InlinedFinallyNodeAt(i)->Visit(&for_effect); |
| 1358 Append(for_effect); | 1363 Append(for_effect); |
| 1359 if (!is_open()) return; | 1364 if (!is_open()) return; |
| 1360 } | 1365 } |
| 1361 | 1366 |
| 1362 // Unchain the context(s) up to the outer context level of the scope which | 1367 // Unchain the context(s) up to the outer context level of the scope which |
| 1363 // contains the destination label. | 1368 // contains the destination label. |
| 1364 SourceLabel* label = node->label(); | 1369 SourceLabel* label = node->label(); |
| (...skipping 1259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2624 // TODO(kmillikin): We can eliminate stack checks in some cases (e.g., the | 2629 // TODO(kmillikin): We can eliminate stack checks in some cases (e.g., the |
| 2625 // stack check on entry for leaf routines). | 2630 // stack check on entry for leaf routines). |
| 2626 Instruction* check = new CheckStackOverflowInstr(function.token_pos()); | 2631 Instruction* check = new CheckStackOverflowInstr(function.token_pos()); |
| 2627 // If we are inlining don't actually attach the stack check. We must still | 2632 // If we are inlining don't actually attach the stack check. We must still |
| 2628 // create the stack check inorder to allocate a deopt id. | 2633 // create the stack check inorder to allocate a deopt id. |
| 2629 if (!InInliningContext()) for_effect.AddInstruction(check); | 2634 if (!InInliningContext()) for_effect.AddInstruction(check); |
| 2630 parsed_function().node_sequence()->Visit(&for_effect); | 2635 parsed_function().node_sequence()->Visit(&for_effect); |
| 2631 AppendFragment(normal_entry, for_effect); | 2636 AppendFragment(normal_entry, for_effect); |
| 2632 // Check that the graph is properly terminated. | 2637 // Check that the graph is properly terminated. |
| 2633 ASSERT(!for_effect.is_open()); | 2638 ASSERT(!for_effect.is_open()); |
| 2634 FlowGraph* graph = new FlowGraph(*this, graph_entry_, last_used_block_id_); | 2639 FlowGraph* graph = new FlowGraph(*this, graph_entry_); |
| 2635 if (InInliningContext()) graph->set_exits(exits_); | 2640 if (InInliningContext()) graph->set_exits(exits_); |
| 2636 return graph; | 2641 return graph; |
| 2637 } | 2642 } |
| 2638 | 2643 |
| 2639 | 2644 |
| 2640 void FlowGraphBuilder::Bailout(const char* reason) { | 2645 void FlowGraphBuilder::Bailout(const char* reason) { |
| 2641 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; | 2646 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; |
| 2642 const char* function_name = parsed_function_.function().ToCString(); | 2647 const char* function_name = parsed_function_.function().ToCString(); |
| 2643 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 2648 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 2644 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 2649 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
| 2645 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2650 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 2646 const Error& error = Error::Handle( | 2651 const Error& error = Error::Handle( |
| 2647 LanguageError::New(String::Handle(String::New(chars)))); | 2652 LanguageError::New(String::Handle(String::New(chars)))); |
| 2648 Isolate::Current()->long_jump_base()->Jump(1, error); | 2653 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2649 } | 2654 } |
| 2650 | 2655 |
| 2651 | 2656 |
| 2652 } // namespace dart | 2657 } // namespace dart |
| OLD | NEW |