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 "vm/ast_printer.h" | |
| 7 #include "vm/flags.h" | 8 #include "vm/flags.h" |
| 8 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 9 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| 10 #include "vm/os.h" | 11 #include "vm/os.h" |
| 11 #include "vm/parser.h" | 12 #include "vm/parser.h" |
| 12 | 13 |
| 13 namespace dart { | 14 namespace dart { |
| 14 | 15 |
| 15 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph."); | 16 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph."); |
| 16 DECLARE_FLAG(bool, enable_type_checks); | 17 DECLARE_FLAG(bool, enable_type_checks); |
| 18 DECLARE_FLAG(bool, print_ast); | |
| 17 | 19 |
| 18 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) { | 20 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) { |
| 19 ASSERT(is_open()); | 21 ASSERT(is_open()); |
| 20 if (other_fragment.is_empty()) return; | 22 if (other_fragment.is_empty()) return; |
| 21 if (is_empty()) { | 23 if (is_empty()) { |
| 22 entry_ = other_fragment.entry(); | 24 entry_ = other_fragment.entry(); |
| 23 exit_ = other_fragment.exit(); | 25 exit_ = other_fragment.exit(); |
| 24 } else { | 26 } else { |
| 25 exit()->SetSuccessor(other_fragment.entry()); | 27 exit()->SetSuccessor(other_fragment.entry()); |
| 26 exit_ = other_fragment.exit(); | 28 exit_ = other_fragment.exit(); |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 210 } | 212 } |
| 211 | 213 |
| 212 | 214 |
| 213 // <Expression> :: BinaryOp { kind: Token::Kind | 215 // <Expression> :: BinaryOp { kind: Token::Kind |
| 214 // left: <Expression> | 216 // left: <Expression> |
| 215 // right: <Expression> } | 217 // right: <Expression> } |
| 216 void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { | 218 void EffectGraphVisitor::VisitBinaryOpNode(BinaryOpNode* node) { |
| 217 // Operators "&&" and "||" cannot be overloaded therefore do not call | 219 // Operators "&&" and "||" cannot be overloaded therefore do not call |
| 218 // operator. | 220 // operator. |
| 219 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { | 221 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { |
| 222 // Implement short-circuit logic: do not evaluate right if evaluation | |
| 223 // of left is sufficient. | |
| 220 Bailout("EffectGraphVisitor::VisitBinaryOpNode AND/OR"); | 224 Bailout("EffectGraphVisitor::VisitBinaryOpNode AND/OR"); |
| 221 } | 225 } |
| 222 ArgumentGraphVisitor for_left_value(owner(), temp_index()); | 226 ArgumentGraphVisitor for_left_value(owner(), temp_index()); |
| 223 node->left()->Visit(&for_left_value); | 227 node->left()->Visit(&for_left_value); |
| 224 Append(for_left_value); | 228 Append(for_left_value); |
| 225 ArgumentGraphVisitor for_right_value(owner(), for_left_value.temp_index()); | 229 ArgumentGraphVisitor for_right_value(owner(), for_left_value.temp_index()); |
| 226 node->right()->Visit(&for_right_value); | 230 node->right()->Visit(&for_right_value); |
| 227 Append(for_right_value); | 231 Append(for_right_value); |
| 228 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2); | 232 ZoneGrowableArray<Value*>* arguments = new ZoneGrowableArray<Value*>(2); |
| 229 arguments->Add(for_left_value.value()); | 233 arguments->Add(for_left_value.value()); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 432 TestGraphVisitor for_test(owner(), temp_index()); | 436 TestGraphVisitor for_test(owner(), temp_index()); |
| 433 node->condition()->Visit(&for_test); | 437 node->condition()->Visit(&for_test); |
| 434 | 438 |
| 435 EffectGraphVisitor for_body(owner(), temp_index()); | 439 EffectGraphVisitor for_body(owner(), temp_index()); |
| 436 if (for_test.can_be_true()) node->body()->Visit(&for_body); | 440 if (for_test.can_be_true()) node->body()->Visit(&for_body); |
| 437 TieLoop(for_test, for_body); | 441 TieLoop(for_test, for_body); |
| 438 } | 442 } |
| 439 | 443 |
| 440 | 444 |
| 441 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { | 445 void EffectGraphVisitor::VisitDoWhileNode(DoWhileNode* node) { |
| 442 Bailout("EffectGraphVisitor::VisitDoWhileNode"); | 446 EffectGraphVisitor for_body(owner(), temp_index()); |
| 447 node->body()->Visit(&for_body); | |
| 448 TestGraphVisitor for_test(owner(), temp_index()); | |
| 449 node->condition()->Visit(&for_test); | |
| 450 ASSERT(is_open()); | |
| 451 | |
| 452 // Tie do-while loop (test is after the body). | |
|
Kevin Millikin (Google)
2012/03/07 09:15:44
I think we can come up with a generic loop-tying f
| |
| 453 JoinEntryInstr* join = new JoinEntryInstr(); | |
| 454 AddInstruction(join); | |
| 455 join->SetSuccessor(for_body.entry()); | |
| 456 Instruction* body_exit = for_body.is_empty() ? join : for_body.exit(); | |
|
Kevin Millikin (Google)
2012/03/07 09:15:44
This is correct but contains introduces an extra b
| |
| 457 | |
| 458 if (body_exit != NULL) { | |
| 459 TargetEntryInstr* target_entry = new TargetEntryInstr(); | |
| 460 target_entry->SetSuccessor(for_test.entry()); | |
| 461 body_exit->SetSuccessor(target_entry); | |
| 462 } | |
| 463 | |
| 464 *for_test.true_successor_address() = join; | |
| 465 exit_ = *for_test.false_successor_address() = new TargetEntryInstr(); | |
| 443 } | 466 } |
| 444 | 467 |
| 445 | 468 |
| 446 void EffectGraphVisitor::VisitForNode(ForNode* node) { | 469 void EffectGraphVisitor::VisitForNode(ForNode* node) { |
| 447 Bailout("EffectGraphVisitor::VisitForNode"); | 470 Bailout("EffectGraphVisitor::VisitForNode"); |
| 448 } | 471 } |
| 449 | 472 |
| 450 | 473 |
| 451 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { | 474 void EffectGraphVisitor::VisitJumpNode(JumpNode* node) { |
| 452 Bailout("EffectGraphVisitor::VisitJumpNode"); | 475 Bailout("EffectGraphVisitor::VisitJumpNode"); |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 953 | 976 |
| 954 void FlowGraphPrinter::VisitBranch(BranchInstr* instr) { | 977 void FlowGraphPrinter::VisitBranch(BranchInstr* instr) { |
| 955 OS::Print(" if "); | 978 OS::Print(" if "); |
| 956 instr->value()->Accept(this); | 979 instr->value()->Accept(this); |
| 957 OS::Print(" goto(%d, %d)", instr->true_successor()->block_number(), | 980 OS::Print(" goto(%d, %d)", instr->true_successor()->block_number(), |
| 958 instr->false_successor()->block_number()); | 981 instr->false_successor()->block_number()); |
| 959 } | 982 } |
| 960 | 983 |
| 961 | 984 |
| 962 void FlowGraphBuilder::BuildGraph() { | 985 void FlowGraphBuilder::BuildGraph() { |
| 986 if (FLAG_print_ast) { | |
| 987 // Print the function ast before IL generation. | |
| 988 AstPrinter::PrintFunctionNodes(parsed_function_); | |
| 989 } | |
| 963 EffectGraphVisitor for_effect(this, 0); | 990 EffectGraphVisitor for_effect(this, 0); |
| 964 for_effect.AddInstruction(new TargetEntryInstr()); | 991 for_effect.AddInstruction(new TargetEntryInstr()); |
| 965 parsed_function().node_sequence()->Visit(&for_effect); | 992 parsed_function().node_sequence()->Visit(&for_effect); |
| 966 // Check that the graph is properly terminated. | 993 // Check that the graph is properly terminated. |
| 967 ASSERT(!for_effect.is_open()); | 994 ASSERT(!for_effect.is_open()); |
| 968 if (for_effect.entry() != NULL) { | 995 if (for_effect.entry() != NULL) { |
| 969 // Accumulate basic block entries via postorder traversal. | 996 // Accumulate basic block entries via postorder traversal. |
| 970 for_effect.entry()->Postorder(&postorder_block_entries_); | 997 for_effect.entry()->Postorder(&postorder_block_entries_); |
| 971 // Number the blocks in reverse postorder starting with 0. | 998 // Number the blocks in reverse postorder starting with 0. |
| 972 intptr_t last_index = postorder_block_entries_.length() - 1; | 999 intptr_t last_index = postorder_block_entries_.length() - 1; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 988 char* chars = reinterpret_cast<char*>( | 1015 char* chars = reinterpret_cast<char*>( |
| 989 Isolate::Current()->current_zone()->Allocate(len)); | 1016 Isolate::Current()->current_zone()->Allocate(len)); |
| 990 OS::SNPrint(chars, len, kFormat, function_name, reason); | 1017 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 991 const Error& error = Error::Handle( | 1018 const Error& error = Error::Handle( |
| 992 LanguageError::New(String::Handle(String::New(chars)))); | 1019 LanguageError::New(String::Handle(String::New(chars)))); |
| 993 Isolate::Current()->long_jump_base()->Jump(1, error); | 1020 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 994 } | 1021 } |
| 995 | 1022 |
| 996 | 1023 |
| 997 } // namespace dart | 1024 } // namespace dart |
| OLD | NEW |