| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 /** | 5 /** |
| 6 * This library is capable of producing linked summaries from unlinked | 6 * This library is capable of producing linked summaries from unlinked |
| 7 * ones (or prelinked ones). It functions by building a miniature | 7 * ones (or prelinked ones). It functions by building a miniature |
| 8 * element model to represent the contents of the summaries, and then | 8 * element model to represent the contents of the summaries, and then |
| 9 * scanning the element model to gather linked information and adding | 9 * scanning the element model to gather linked information and adding |
| 10 * it to the summary data structures. | 10 * it to the summary data structures. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 import 'package:analyzer/src/dart/element/element.dart'; | 65 import 'package:analyzer/src/dart/element/element.dart'; |
| 66 import 'package:analyzer/src/dart/element/type.dart'; | 66 import 'package:analyzer/src/dart/element/type.dart'; |
| 67 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart'; | 67 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart'; |
| 68 import 'package:analyzer/src/generated/engine.dart'; | 68 import 'package:analyzer/src/generated/engine.dart'; |
| 69 import 'package:analyzer/src/generated/resolver.dart'; | 69 import 'package:analyzer/src/generated/resolver.dart'; |
| 70 import 'package:analyzer/src/generated/utilities_dart.dart'; | 70 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| 71 import 'package:analyzer/src/summary/format.dart'; | 71 import 'package:analyzer/src/summary/format.dart'; |
| 72 import 'package:analyzer/src/summary/idl.dart'; | 72 import 'package:analyzer/src/summary/idl.dart'; |
| 73 import 'package:analyzer/src/summary/prelink.dart'; | 73 import 'package:analyzer/src/summary/prelink.dart'; |
| 74 import 'package:analyzer/src/task/strong_mode.dart'; | 74 import 'package:analyzer/src/task/strong_mode.dart'; |
| 75 import 'package:front_end/src/dependency_walker.dart'; |
| 75 | 76 |
| 76 bool isIncrementOrDecrement(UnlinkedExprAssignOperator operator) { | 77 bool isIncrementOrDecrement(UnlinkedExprAssignOperator operator) { |
| 77 switch (operator) { | 78 switch (operator) { |
| 78 case UnlinkedExprAssignOperator.prefixDecrement: | 79 case UnlinkedExprAssignOperator.prefixDecrement: |
| 79 case UnlinkedExprAssignOperator.prefixIncrement: | 80 case UnlinkedExprAssignOperator.prefixIncrement: |
| 80 case UnlinkedExprAssignOperator.postfixDecrement: | 81 case UnlinkedExprAssignOperator.postfixDecrement: |
| 81 case UnlinkedExprAssignOperator.postfixIncrement: | 82 case UnlinkedExprAssignOperator.postfixIncrement: |
| 82 return true; | 83 return true; |
| 83 default: | 84 default: |
| 84 return false; | 85 return false; |
| (...skipping 1660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1745 AnalysisOptionsForLink get analysisOptions => _linker.analysisOptions; | 1746 AnalysisOptionsForLink get analysisOptions => _linker.analysisOptions; |
| 1746 | 1747 |
| 1747 @override | 1748 @override |
| 1748 TypeSystem get typeSystem => _linker.typeSystem; | 1749 TypeSystem get typeSystem => _linker.typeSystem; |
| 1749 | 1750 |
| 1750 @override | 1751 @override |
| 1751 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); | 1752 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
| 1752 } | 1753 } |
| 1753 | 1754 |
| 1754 /** | 1755 /** |
| 1755 * An instance of [DependencyWalker] contains the core algorithms for | |
| 1756 * walking a dependency graph and evaluating nodes in a safe order. | |
| 1757 */ | |
| 1758 abstract class DependencyWalker<NodeType extends Node<NodeType>> { | |
| 1759 /** | |
| 1760 * Called by [walk] to evaluate a single non-cyclical node, after | |
| 1761 * all that node's dependencies have been evaluated. | |
| 1762 */ | |
| 1763 void evaluate(NodeType v); | |
| 1764 | |
| 1765 /** | |
| 1766 * Called by [walk] to evaluate a strongly connected component | |
| 1767 * containing one or more nodes. All dependencies of the strongly | |
| 1768 * connected component have been evaluated. | |
| 1769 */ | |
| 1770 void evaluateScc(List<NodeType> scc); | |
| 1771 | |
| 1772 /** | |
| 1773 * Walk the dependency graph starting at [startingPoint], finding | |
| 1774 * strongly connected components and evaluating them in a safe order | |
| 1775 * by calling [evaluate] and [evaluateScc]. | |
| 1776 * | |
| 1777 * This is an implementation of Tarjan's strongly connected | |
| 1778 * components algorithm | |
| 1779 * (https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_alg
orithm). | |
| 1780 */ | |
| 1781 void walk(NodeType startingPoint) { | |
| 1782 // TODO(paulberry): consider rewriting in a non-recursive way so | |
| 1783 // that long dependency chains don't cause stack overflow. | |
| 1784 | |
| 1785 // TODO(paulberry): in the event that an exception occurs during | |
| 1786 // the walk, restore the state of the [Node] data structures so | |
| 1787 // that further evaluation will be safe. | |
| 1788 | |
| 1789 // The index which will be assigned to the next node that is | |
| 1790 // freshly visited. | |
| 1791 int index = 1; | |
| 1792 | |
| 1793 // Stack of nodes which have been seen so far and whose strongly | |
| 1794 // connected component is still being determined. Nodes are only | |
| 1795 // popped off the stack when they are evaluated, so sometimes the | |
| 1796 // stack contains nodes that were visited after the current node. | |
| 1797 List<NodeType> stack = <NodeType>[]; | |
| 1798 | |
| 1799 void strongConnect(NodeType node) { | |
| 1800 bool hasTrivialCycle = false; | |
| 1801 | |
| 1802 // Assign the current node an index and add it to the stack. We | |
| 1803 // haven't seen any of its dependencies yet, so set its lowLink | |
| 1804 // to its index, indicating that so far it is the only node in | |
| 1805 // its strongly connected component. | |
| 1806 node.index = node.lowLink = index++; | |
| 1807 stack.add(node); | |
| 1808 | |
| 1809 // Consider the node's dependencies one at a time. | |
| 1810 for (NodeType dependency in node.dependencies) { | |
| 1811 // If the dependency has already been evaluated, it can't be | |
| 1812 // part of this node's strongly connected component, so we can | |
| 1813 // skip it. | |
| 1814 if (dependency.isEvaluated) { | |
| 1815 continue; | |
| 1816 } | |
| 1817 if (identical(node, dependency)) { | |
| 1818 // If a node includes itself as a dependency, there is no need to | |
| 1819 // explore the dependency further. | |
| 1820 hasTrivialCycle = true; | |
| 1821 } else if (dependency.index == 0) { | |
| 1822 // The dependency hasn't been seen yet, so recurse on it. | |
| 1823 strongConnect(dependency); | |
| 1824 // If the dependency's lowLink refers to a node that was | |
| 1825 // visited before the current node, that means that the | |
| 1826 // current node, the dependency, and the node referred to by | |
| 1827 // the dependency's lowLink are all part of the same | |
| 1828 // strongly connected component, so we need to update the | |
| 1829 // current node's lowLink accordingly. | |
| 1830 if (dependency.lowLink < node.lowLink) { | |
| 1831 node.lowLink = dependency.lowLink; | |
| 1832 } | |
| 1833 } else { | |
| 1834 // The dependency has already been seen, so it is part of | |
| 1835 // the current node's strongly connected component. If it | |
| 1836 // was visited earlier than the current node's lowLink, then | |
| 1837 // it is a new addition to the current node's strongly | |
| 1838 // connected component, so we need to update the current | |
| 1839 // node's lowLink accordingly. | |
| 1840 if (dependency.index < node.lowLink) { | |
| 1841 node.lowLink = dependency.index; | |
| 1842 } | |
| 1843 } | |
| 1844 } | |
| 1845 | |
| 1846 // If the current node's lowLink is the same as its index, then | |
| 1847 // we have finished visiting a strongly connected component, so | |
| 1848 // pop the stack and evaluate it before moving on. | |
| 1849 if (node.lowLink == node.index) { | |
| 1850 // The strongly connected component has only one node. If there is a | |
| 1851 // cycle, it's a trivial one. | |
| 1852 if (identical(stack.last, node)) { | |
| 1853 stack.removeLast(); | |
| 1854 if (hasTrivialCycle) { | |
| 1855 evaluateScc(<NodeType>[node]); | |
| 1856 } else { | |
| 1857 evaluate(node); | |
| 1858 } | |
| 1859 } else { | |
| 1860 // There are multiple nodes in the strongly connected | |
| 1861 // component. | |
| 1862 List<NodeType> scc = <NodeType>[]; | |
| 1863 while (true) { | |
| 1864 NodeType otherNode = stack.removeLast(); | |
| 1865 scc.add(otherNode); | |
| 1866 if (identical(otherNode, node)) { | |
| 1867 break; | |
| 1868 } | |
| 1869 } | |
| 1870 evaluateScc(scc); | |
| 1871 } | |
| 1872 } | |
| 1873 } | |
| 1874 | |
| 1875 // Kick off the algorithm starting with the starting point. | |
| 1876 strongConnect(startingPoint); | |
| 1877 } | |
| 1878 } | |
| 1879 | |
| 1880 /** | |
| 1881 * Base class for executable elements resynthesized from a summary during | 1756 * Base class for executable elements resynthesized from a summary during |
| 1882 * linking. | 1757 * linking. |
| 1883 */ | 1758 */ |
| 1884 abstract class ExecutableElementForLink extends Object | 1759 abstract class ExecutableElementForLink extends Object |
| 1885 with TypeParameterizedElementMixin, ParameterParentElementForLink | 1760 with TypeParameterizedElementMixin, ParameterParentElementForLink |
| 1886 implements ExecutableElementImpl { | 1761 implements ExecutableElementImpl { |
| 1887 /** | 1762 /** |
| 1888 * The unlinked representation of the method in the summary. | 1763 * The unlinked representation of the method in the summary. |
| 1889 */ | 1764 */ |
| 1890 final UnlinkedExecutable _unlinkedExecutable; | 1765 final UnlinkedExecutable _unlinkedExecutable; |
| (...skipping 1958 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3849 } | 3724 } |
| 3850 | 3725 |
| 3851 @override | 3726 @override |
| 3852 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); | 3727 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
| 3853 | 3728 |
| 3854 @override | 3729 @override |
| 3855 String toString() => '$enclosingElement.$name'; | 3730 String toString() => '$enclosingElement.$name'; |
| 3856 } | 3731 } |
| 3857 | 3732 |
| 3858 /** | 3733 /** |
| 3859 * Instances of [Node] represent nodes in a dependency graph. The | |
| 3860 * type parameter, [NodeType], is the derived type (this affords some | |
| 3861 * extra type safety by making it difficult to accidentally construct | |
| 3862 * bridges between unrelated dependency graphs). | |
| 3863 */ | |
| 3864 abstract class Node<NodeType> { | |
| 3865 /** | |
| 3866 * Index used by Tarjan's strongly connected components algorithm. | |
| 3867 * Zero means the node has not been visited yet; a nonzero value | |
| 3868 * counts the order in which the node was visited. | |
| 3869 */ | |
| 3870 int index = 0; | |
| 3871 | |
| 3872 /** | |
| 3873 * Low link used by Tarjan's strongly connected components | |
| 3874 * algorithm. This represents the smallest [index] of all the nodes | |
| 3875 * in the strongly connected component to which this node belongs. | |
| 3876 */ | |
| 3877 int lowLink = 0; | |
| 3878 | |
| 3879 List<NodeType> _dependencies; | |
| 3880 | |
| 3881 /** | |
| 3882 * Retrieve the dependencies of this node. | |
| 3883 */ | |
| 3884 List<NodeType> get dependencies => _dependencies ??= computeDependencies(); | |
| 3885 | |
| 3886 /** | |
| 3887 * Indicates whether this node has been evaluated yet. | |
| 3888 */ | |
| 3889 bool get isEvaluated; | |
| 3890 | |
| 3891 /** | |
| 3892 * Compute the dependencies of this node. | |
| 3893 */ | |
| 3894 List<NodeType> computeDependencies(); | |
| 3895 } | |
| 3896 | |
| 3897 /** | |
| 3898 * Element used for references that result from trying to access a non-static | 3734 * Element used for references that result from trying to access a non-static |
| 3899 * member of an element that is not a container (e.g. accessing the "length" | 3735 * member of an element that is not a container (e.g. accessing the "length" |
| 3900 * property of a constant). | 3736 * property of a constant). |
| 3901 * | 3737 * |
| 3902 * Accesses to a chain of non-static members separated by '.' are andled by | 3738 * Accesses to a chain of non-static members separated by '.' are andled by |
| 3903 * creating a [NonstaticMemberElementForLink] that points to another | 3739 * creating a [NonstaticMemberElementForLink] that points to another |
| 3904 * [NonstaticMemberElementForLink], to whatever nesting level is necessary. | 3740 * [NonstaticMemberElementForLink], to whatever nesting level is necessary. |
| 3905 */ | 3741 */ |
| 3906 class NonstaticMemberElementForLink extends Object | 3742 class NonstaticMemberElementForLink extends Object |
| 3907 with ReferenceableElementForLink { | 3743 with ReferenceableElementForLink { |
| (...skipping 1204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5112 * there are no type parameters in scope. | 4948 * there are no type parameters in scope. |
| 5113 */ | 4949 */ |
| 5114 TypeParameterizedElementMixin get _typeParameterContext; | 4950 TypeParameterizedElementMixin get _typeParameterContext; |
| 5115 | 4951 |
| 5116 @override | 4952 @override |
| 5117 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); | 4953 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); |
| 5118 | 4954 |
| 5119 @override | 4955 @override |
| 5120 String toString() => '$enclosingElement.$name'; | 4956 String toString() => '$enclosingElement.$name'; |
| 5121 } | 4957 } |
| OLD | NEW |