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/flags.h" | 8 #include "vm/flags.h" |
9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
(...skipping 1310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1321 | 1321 |
1322 | 1322 |
1323 void EffectGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) { | 1323 void EffectGraphVisitor::VisitInlinedFinallyNode(InlinedFinallyNode* node) { |
1324 Bailout("EffectGraphVisitor::VisitInlinedFinallyNode"); | 1324 Bailout("EffectGraphVisitor::VisitInlinedFinallyNode"); |
1325 } | 1325 } |
1326 | 1326 |
1327 | 1327 |
1328 // Graph printing. | 1328 // Graph printing. |
1329 class FlowGraphPrinter : public FlowGraphVisitor { | 1329 class FlowGraphPrinter : public FlowGraphVisitor { |
1330 public: | 1330 public: |
1331 explicit FlowGraphPrinter(const Function& function) : function_(function) { } | 1331 explicit FlowGraphPrinter(const Function& function, |
1332 const GrowableArray<BlockEntryInstr*>& block_order) | |
srdjan
2012/03/16 22:01:17
remove explicit.
Kevin Millikin (Google)
2012/03/16 22:18:32
Thanks.
| |
1333 : FlowGraphVisitor(block_order), function_(function) { } | |
1332 | 1334 |
1333 virtual ~FlowGraphPrinter() {} | 1335 virtual ~FlowGraphPrinter() {} |
1334 | 1336 |
1335 // Print the instructions in a block terminated by newlines. Add "goto N" | 1337 // Print the instructions in a block terminated by newlines. Add "goto N" |
1336 // to the end of the block if it ends with an unconditional jump to | 1338 // to the end of the block if it ends with an unconditional jump to |
1337 // another block and that block is not next in reverse postorder. | 1339 // another block and that block is not next in reverse postorder. |
1338 void VisitBlocks(const GrowableArray<BlockEntryInstr*>& block_order); | 1340 void VisitBlocks(); |
1339 | 1341 |
1340 // Visiting a computation prints it with no indentation or newline. | 1342 // Visiting a computation prints it with no indentation or newline. |
1341 #define DECLARE_VISIT_COMPUTATION(ShortName, ClassName) \ | 1343 #define DECLARE_VISIT_COMPUTATION(ShortName, ClassName) \ |
1342 virtual void Visit##ShortName(ClassName* comp); | 1344 virtual void Visit##ShortName(ClassName* comp); |
1343 | 1345 |
1344 // Visiting an instruction prints it with a four space indent and no | 1346 // Visiting an instruction prints it with a four space indent and no |
1345 // trailing newline. Basic block entries are labeled with their block | 1347 // trailing newline. Basic block entries are labeled with their block |
1346 // number. | 1348 // number. |
1347 #define DECLARE_VISIT_INSTRUCTION(ShortName) \ | 1349 #define DECLARE_VISIT_INSTRUCTION(ShortName) \ |
1348 virtual void Visit##ShortName(ShortName##Instr* instr); | 1350 virtual void Visit##ShortName(ShortName##Instr* instr); |
1349 | 1351 |
1350 FOR_EACH_COMPUTATION(DECLARE_VISIT_COMPUTATION) | 1352 FOR_EACH_COMPUTATION(DECLARE_VISIT_COMPUTATION) |
1351 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) | 1353 FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) |
1352 | 1354 |
1353 #undef DECLARE_VISIT_COMPUTATION | 1355 #undef DECLARE_VISIT_COMPUTATION |
1354 #undef DECLARE_VISIT_INSTRUCTION | 1356 #undef DECLARE_VISIT_INSTRUCTION |
1355 | 1357 |
1356 private: | 1358 private: |
1357 const Function& function_; | 1359 const Function& function_; |
1358 | 1360 |
1359 DISALLOW_COPY_AND_ASSIGN(FlowGraphPrinter); | 1361 DISALLOW_COPY_AND_ASSIGN(FlowGraphPrinter); |
1360 }; | 1362 }; |
1361 | 1363 |
1362 | 1364 |
1363 void FlowGraphPrinter::VisitBlocks( | 1365 void FlowGraphPrinter::VisitBlocks() { |
1364 const GrowableArray<BlockEntryInstr*>& block_order) { | |
1365 OS::Print("==== %s\n", function_.ToFullyQualifiedCString()); | 1366 OS::Print("==== %s\n", function_.ToFullyQualifiedCString()); |
1366 | 1367 |
1367 for (intptr_t i = block_order.length() - 1; i >= 0; --i) { | 1368 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
1368 // Print the block entry. | 1369 // Print the block entry. |
1369 Instruction* current = block_order[i]->Accept(this); | 1370 Instruction* current = block_order_[i]->Accept(this); |
1370 // And all the successors until an exit, branch, or a block entry. | 1371 // And all the successors until an exit, branch, or a block entry. |
1371 while ((current != NULL) && !current->IsBlockEntry()) { | 1372 while ((current != NULL) && !current->IsBlockEntry()) { |
1372 OS::Print("\n"); | 1373 OS::Print("\n"); |
1373 current = current->Accept(this); | 1374 current = current->Accept(this); |
1374 } | 1375 } |
1375 BlockEntryInstr* successor = | 1376 BlockEntryInstr* successor = |
1376 (current == NULL) ? NULL : current->AsBlockEntry(); | 1377 (current == NULL) ? NULL : current->AsBlockEntry(); |
1377 if (successor != NULL) { | 1378 if (successor != NULL) { |
1378 OS::Print(" goto %d", successor->block_number()); | 1379 // For readability label blocks with their reverse postorder index, |
1380 // not their postorder block number, so the first block is 0 (not | |
1381 // n-1). | |
1382 OS::Print(" goto %d", reverse_index(successor->postorder_number())); | |
1379 } | 1383 } |
1380 OS::Print("\n"); | 1384 OS::Print("\n"); |
1381 } | 1385 } |
1382 } | 1386 } |
1383 | 1387 |
1384 | 1388 |
1385 void FlowGraphPrinter::VisitTemp(TempVal* val) { | 1389 void FlowGraphPrinter::VisitTemp(TempVal* val) { |
1386 OS::Print("t%d", val->index()); | 1390 OS::Print("t%d", val->index()); |
1387 } | 1391 } |
1388 | 1392 |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1582 ExtractConstructorInstantiatorComp* comp) { | 1586 ExtractConstructorInstantiatorComp* comp) { |
1583 OS::Print("ExtractConstructorInstantiator("); | 1587 OS::Print("ExtractConstructorInstantiator("); |
1584 comp->instantiator()->Accept(this); | 1588 comp->instantiator()->Accept(this); |
1585 OS::Print(", "); | 1589 OS::Print(", "); |
1586 comp->discard_value()->Accept(this); | 1590 comp->discard_value()->Accept(this); |
1587 OS::Print(")"); | 1591 OS::Print(")"); |
1588 } | 1592 } |
1589 | 1593 |
1590 | 1594 |
1591 void FlowGraphPrinter::VisitJoinEntry(JoinEntryInstr* instr) { | 1595 void FlowGraphPrinter::VisitJoinEntry(JoinEntryInstr* instr) { |
1592 OS::Print("%2d: [join]", instr->block_number()); | 1596 OS::Print("%2d: [join]", reverse_index(instr->postorder_number())); |
1593 } | 1597 } |
1594 | 1598 |
1595 | 1599 |
1596 void FlowGraphPrinter::VisitTargetEntry(TargetEntryInstr* instr) { | 1600 void FlowGraphPrinter::VisitTargetEntry(TargetEntryInstr* instr) { |
1597 OS::Print("%2d: [target]", instr->block_number()); | 1601 OS::Print("%2d: [target]", reverse_index(instr->postorder_number())); |
1598 } | 1602 } |
1599 | 1603 |
1600 | 1604 |
1601 void FlowGraphPrinter::VisitPickTemp(PickTempInstr* instr) { | 1605 void FlowGraphPrinter::VisitPickTemp(PickTempInstr* instr) { |
1602 OS::Print(" t%d <- Pick(t%d)", instr->destination(), instr->source()); | 1606 OS::Print(" t%d <- Pick(t%d)", instr->destination(), instr->source()); |
1603 } | 1607 } |
1604 | 1608 |
1605 | 1609 |
1606 void FlowGraphPrinter::VisitTuckTemp(TuckTempInstr* instr) { | 1610 void FlowGraphPrinter::VisitTuckTemp(TuckTempInstr* instr) { |
1607 OS::Print(" t%d := t%d", instr->destination(), instr->source()); | 1611 OS::Print(" t%d := t%d", instr->destination(), instr->source()); |
(...skipping 30 matching lines...) Expand all Loading... | |
1638 instr->exception()->Accept(this); | 1642 instr->exception()->Accept(this); |
1639 OS::Print(", "); | 1643 OS::Print(", "); |
1640 instr->stack_trace()->Accept(this); | 1644 instr->stack_trace()->Accept(this); |
1641 OS::Print(")"); | 1645 OS::Print(")"); |
1642 } | 1646 } |
1643 | 1647 |
1644 | 1648 |
1645 void FlowGraphPrinter::VisitBranch(BranchInstr* instr) { | 1649 void FlowGraphPrinter::VisitBranch(BranchInstr* instr) { |
1646 OS::Print(" if "); | 1650 OS::Print(" if "); |
1647 instr->value()->Accept(this); | 1651 instr->value()->Accept(this); |
1648 OS::Print(" goto(%d, %d)", instr->true_successor()->block_number(), | 1652 OS::Print(" goto(%d, %d)", |
1649 instr->false_successor()->block_number()); | 1653 reverse_index(instr->true_successor()->postorder_number()), |
1654 reverse_index(instr->false_successor()->postorder_number())); | |
1650 } | 1655 } |
1651 | 1656 |
1652 | 1657 |
1653 void FlowGraphBuilder::BuildGraph() { | 1658 void FlowGraphBuilder::BuildGraph() { |
1654 if (FLAG_print_ast) { | 1659 if (FLAG_print_ast) { |
1655 // Print the function ast before IL generation. | 1660 // Print the function ast before IL generation. |
1656 AstPrinter::PrintFunctionNodes(parsed_function()); | 1661 AstPrinter::PrintFunctionNodes(parsed_function()); |
1657 } | 1662 } |
1658 const Function& function = parsed_function().function(); | 1663 const Function& function = parsed_function().function(); |
1659 EffectGraphVisitor for_effect(this, 0); | 1664 EffectGraphVisitor for_effect(this, 0); |
1660 for_effect.AddInstruction(new TargetEntryInstr()); | 1665 for_effect.AddInstruction(new TargetEntryInstr()); |
1661 parsed_function().node_sequence()->Visit(&for_effect); | 1666 parsed_function().node_sequence()->Visit(&for_effect); |
1662 // Check that the graph is properly terminated. | 1667 // Check that the graph is properly terminated. |
1663 ASSERT(!for_effect.is_open()); | 1668 ASSERT(!for_effect.is_open()); |
1664 if (for_effect.entry() != NULL) { | 1669 if (for_effect.entry() != NULL) { |
1665 // Accumulate basic block entries via postorder traversal. | 1670 // Perform a depth-first traversal of the graph to build preorder and |
1666 for_effect.entry()->Postorder(&postorder_block_entries_); | 1671 // postorder block orders. |
1667 // Number the blocks in reverse postorder starting with 0. | 1672 for_effect.entry()->DepthFirstSearch(&preorder_block_entries_, |
1668 intptr_t last_index = postorder_block_entries_.length() - 1; | 1673 &postorder_block_entries_); |
1669 for (intptr_t i = last_index; i >= 0; --i) { | |
1670 postorder_block_entries_[i]->set_block_number(last_index - i); | |
1671 } | |
1672 } | 1674 } |
1673 if (FLAG_print_flow_graph) { | 1675 if (FLAG_print_flow_graph) { |
1674 FlowGraphPrinter printer(function); | 1676 intptr_t length = postorder_block_entries_.length(); |
1675 printer.VisitBlocks(postorder_block_entries_); | 1677 GrowableArray<BlockEntryInstr*> reverse_postorder(length); |
1678 for (intptr_t i = length - 1; i >= 0; --i) { | |
1679 reverse_postorder.Add(postorder_block_entries_[i]); | |
1680 } | |
1681 FlowGraphPrinter printer(function, reverse_postorder); | |
1682 printer.VisitBlocks(); | |
1676 } | 1683 } |
1677 } | 1684 } |
1678 | 1685 |
1679 | 1686 |
1680 void FlowGraphBuilder::Bailout(const char* reason) { | 1687 void FlowGraphBuilder::Bailout(const char* reason) { |
1681 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; | 1688 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; |
1682 const char* function_name = parsed_function_.function().ToCString(); | 1689 const char* function_name = parsed_function_.function().ToCString(); |
1683 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 1690 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
1684 char* chars = reinterpret_cast<char*>( | 1691 char* chars = reinterpret_cast<char*>( |
1685 Isolate::Current()->current_zone()->Allocate(len)); | 1692 Isolate::Current()->current_zone()->Allocate(len)); |
1686 OS::SNPrint(chars, len, kFormat, function_name, reason); | 1693 OS::SNPrint(chars, len, kFormat, function_name, reason); |
1687 const Error& error = Error::Handle( | 1694 const Error& error = Error::Handle( |
1688 LanguageError::New(String::Handle(String::New(chars)))); | 1695 LanguageError::New(String::Handle(String::New(chars)))); |
1689 Isolate::Current()->long_jump_base()->Jump(1, error); | 1696 Isolate::Current()->long_jump_base()->Jump(1, error); |
1690 } | 1697 } |
1691 | 1698 |
1692 | 1699 |
1693 } // namespace dart | 1700 } // namespace dart |
OLD | NEW |