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/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 1653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1664 } | 1664 } |
| 1665 const Function& function = parsed_function().function(); | 1665 const Function& function = parsed_function().function(); |
| 1666 EffectGraphVisitor for_effect(this, 0); | 1666 EffectGraphVisitor for_effect(this, 0); |
| 1667 for_effect.AddInstruction(new TargetEntryInstr()); | 1667 for_effect.AddInstruction(new TargetEntryInstr()); |
| 1668 parsed_function().node_sequence()->Visit(&for_effect); | 1668 parsed_function().node_sequence()->Visit(&for_effect); |
| 1669 // Check that the graph is properly terminated. | 1669 // Check that the graph is properly terminated. |
| 1670 ASSERT(!for_effect.is_open()); | 1670 ASSERT(!for_effect.is_open()); |
| 1671 if (for_effect.entry() != NULL) { | 1671 if (for_effect.entry() != NULL) { |
| 1672 // Perform a depth-first traversal of the graph to build preorder and | 1672 // Perform a depth-first traversal of the graph to build preorder and |
| 1673 // postorder block orders. | 1673 // postorder block orders. |
| 1674 GrowableArray<BlockEntryInstr*> parent; | 1674 GrowableArray<intptr_t> parent; |
| 1675 for_effect.entry()->DiscoverBlocks(NULL, // Entry block predecessor. | 1675 for_effect.entry()->DiscoverBlocks(NULL, // Entry block predecessor. |
| 1676 &preorder_block_entries_, | 1676 &preorder_block_entries_, |
| 1677 &postorder_block_entries_, | 1677 &postorder_block_entries_, |
| 1678 &parent); | 1678 &parent); |
| 1679 ComputeDominators(&preorder_block_entries_, &parent); | |
| 1679 } | 1680 } |
| 1680 if (FLAG_print_flow_graph) { | 1681 if (FLAG_print_flow_graph) { |
| 1681 intptr_t length = postorder_block_entries_.length(); | 1682 intptr_t length = postorder_block_entries_.length(); |
| 1682 GrowableArray<BlockEntryInstr*> reverse_postorder(length); | 1683 GrowableArray<BlockEntryInstr*> reverse_postorder(length); |
| 1683 for (intptr_t i = length - 1; i >= 0; --i) { | 1684 for (intptr_t i = length - 1; i >= 0; --i) { |
| 1684 reverse_postorder.Add(postorder_block_entries_[i]); | 1685 reverse_postorder.Add(postorder_block_entries_[i]); |
| 1685 } | 1686 } |
| 1686 FlowGraphPrinter printer(function, reverse_postorder); | 1687 FlowGraphPrinter printer(function, reverse_postorder); |
| 1687 printer.VisitBlocks(); | 1688 printer.VisitBlocks(); |
| 1688 } | 1689 } |
| 1689 } | 1690 } |
| 1690 | 1691 |
| 1691 | 1692 |
| 1693 void FlowGraphBuilder::ComputeDominators( | |
| 1694 GrowableArray<BlockEntryInstr*>* preorder, | |
| 1695 GrowableArray<intptr_t>* parent) { | |
| 1696 // Use the SEMI-NCA algorithm to compute dominators. This is a two-pass | |
| 1697 // version of the Lengauer-Tarjan algorithm (LT is normally three passes) | |
| 1698 // that eliminates a pass by using nearest-common ancestor (NCA) to | |
| 1699 // compute immediate dominators from semidominators. It also removes a | |
| 1700 // level of indirection in the link-eval forest data structure. | |
| 1701 // | |
| 1702 // The algorithm is described in Georgiadis, Tarjan, and Werneck's | |
| 1703 // "Finding Dominators in Practice". | |
| 1704 // See http://www.cs.princeton.edu/~rwerneck/dominators/ . | |
| 1705 | |
| 1706 // All arrays are indexed by preorder basic-block number. | |
| 1707 intptr_t size = parent->length(); | |
|
srdjan
2012/03/21 20:57:50
const intptr_t
| |
| 1708 GrowableArray<intptr_t> idom(size); // Immediate dominator. | |
| 1709 GrowableArray<intptr_t> semi(size); // Semidominator index. | |
| 1710 GrowableArray<intptr_t> label(size); // Label for link-eval forest. | |
| 1711 | |
| 1712 // 1. First pass: compute semidominators as in Lengauer-Tarjan. | |
| 1713 // Semidominators are computed from a depth-first spanning tree and are an | |
| 1714 // approximation of immediate dominators. | |
| 1715 | |
| 1716 // Use a link-eval data structure with path compression. Implement path | |
| 1717 // compression in place by mutating the parent array. Each block has a | |
| 1718 // label, which is the minimum block number on the compressed path. | |
| 1719 | |
| 1720 // Initialize idom, semi, and label. | |
| 1721 for (intptr_t i = 0; i < size; ++i) { | |
| 1722 idom.Add((*parent)[i]); | |
| 1723 semi.Add(i); | |
| 1724 label.Add(i); | |
| 1725 } | |
| 1726 | |
| 1727 // Loop over the blocks in reverse preorder (not including the graph | |
| 1728 // entry). | |
| 1729 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) { | |
| 1730 // Loop over the predecessors. | |
| 1731 BlockEntryInstr* block = (*preorder)[block_index]; | |
| 1732 for (intptr_t i = 0; i < block->PredecessorCount(); ++i) { | |
| 1733 BlockEntryInstr* pred = block->PredecessorAt(i); | |
| 1734 ASSERT(pred != NULL); | |
| 1735 | |
| 1736 // Look for the semidominator by ascending the semidominator path | |
| 1737 // starting from pred. | |
| 1738 intptr_t pred_index = pred->preorder_number(); | |
| 1739 intptr_t best = pred_index; | |
| 1740 if (pred_index > block_index) { | |
| 1741 CompressPath(block_index, pred_index, parent, &label); | |
| 1742 best = label[pred_index]; | |
| 1743 } | |
| 1744 | |
| 1745 // Update the semidominator if we've found a better one. | |
| 1746 semi[block_index] = Utils::Minimum(semi[block_index], semi[best]); | |
| 1747 } | |
| 1748 | |
| 1749 // Now use label for the semidominator. | |
| 1750 label[block_index] = semi[block_index]; | |
| 1751 } | |
| 1752 | |
| 1753 // 2. Compute the immediate dominators as the nearest common ancestor of | |
| 1754 // spanning tree parent and semidominator, for all nodes except the entry. | |
| 1755 for (intptr_t block_index = 1; block_index < size; ++block_index) { | |
| 1756 intptr_t dom_index = idom[block_index]; | |
| 1757 while (dom_index > semi[block_index]) { | |
| 1758 dom_index = idom[dom_index]; | |
| 1759 } | |
| 1760 idom[block_index] = dom_index; | |
| 1761 (*preorder)[block_index]->set_dominator((*preorder)[dom_index]); | |
| 1762 } | |
| 1763 } | |
| 1764 | |
| 1765 | |
| 1766 void FlowGraphBuilder::CompressPath(intptr_t start_index, | |
| 1767 intptr_t current_index, | |
| 1768 GrowableArray<intptr_t>* parent, | |
| 1769 GrowableArray<intptr_t>* label) { | |
| 1770 intptr_t next_index = (*parent)[current_index]; | |
| 1771 if (next_index > start_index) { | |
| 1772 CompressPath(start_index, next_index, parent, label); | |
| 1773 (*label)[current_index] = | |
| 1774 Utils::Minimum((*label)[current_index], (*label)[next_index]); | |
| 1775 (*parent)[current_index] = (*parent)[next_index]; | |
| 1776 } | |
| 1777 } | |
| 1778 | |
| 1779 | |
| 1692 void FlowGraphBuilder::Bailout(const char* reason) { | 1780 void FlowGraphBuilder::Bailout(const char* reason) { |
| 1693 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; | 1781 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; |
| 1694 const char* function_name = parsed_function_.function().ToCString(); | 1782 const char* function_name = parsed_function_.function().ToCString(); |
| 1695 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 1783 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 1696 char* chars = reinterpret_cast<char*>( | 1784 char* chars = reinterpret_cast<char*>( |
| 1697 Isolate::Current()->current_zone()->Allocate(len)); | 1785 Isolate::Current()->current_zone()->Allocate(len)); |
| 1698 OS::SNPrint(chars, len, kFormat, function_name, reason); | 1786 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 1699 const Error& error = Error::Handle( | 1787 const Error& error = Error::Handle( |
| 1700 LanguageError::New(String::Handle(String::New(chars)))); | 1788 LanguageError::New(String::Handle(String::New(chars)))); |
| 1701 Isolate::Current()->long_jump_base()->Jump(1, error); | 1789 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 1702 } | 1790 } |
| 1703 | 1791 |
| 1704 | 1792 |
| 1705 } // namespace dart | 1793 } // namespace dart |
| OLD | NEW |