| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 abstract class OptimizationPhase { | 7 abstract class OptimizationPhase { |
| 8 String get name; | 8 String get name; |
| 9 void visitGraph(HGraph graph); | 9 void visitGraph(HGraph graph); |
| 10 } | 10 } |
| (...skipping 1688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1699 <HInstruction, Map<HInstruction, HInstruction>> {}; | 1699 <HInstruction, Map<HInstruction, HInstruction>> {}; |
| 1700 | 1700 |
| 1701 /** | 1701 /** |
| 1702 * Set of objects that we know don't escape the current function. | 1702 * Set of objects that we know don't escape the current function. |
| 1703 */ | 1703 */ |
| 1704 final Setlet<HInstruction> nonEscapingReceivers = new Setlet<HInstruction>(); | 1704 final Setlet<HInstruction> nonEscapingReceivers = new Setlet<HInstruction>(); |
| 1705 | 1705 |
| 1706 MemorySet(this.compiler); | 1706 MemorySet(this.compiler); |
| 1707 | 1707 |
| 1708 /** | 1708 /** |
| 1709 * Returns whether [first] and [second] always alias to the same object. | 1709 * Returns whether [first] and [second] may alias to the same |
| 1710 */ | 1710 * object. |
| 1711 bool mustAlias(HInstruction first, HInstruction second) { | |
| 1712 return first == second; | |
| 1713 } | |
| 1714 | |
| 1715 /** | |
| 1716 * Returns whether [first] and [second] may alias to the same object. | |
| 1717 */ | 1711 */ |
| 1718 bool mayAlias(HInstruction first, HInstruction second) { | 1712 bool mayAlias(HInstruction first, HInstruction second) { |
| 1719 if (mustAlias(first, second)) return true; | 1713 if (first == second) return true; |
| 1720 if (isConcrete(first) && isConcrete(second)) return false; | 1714 if (isConcrete(first) && isConcrete(second)) return false; |
| 1721 if (nonEscapingReceivers.contains(first)) return false; | 1715 if (nonEscapingReceivers.contains(first)) return false; |
| 1722 if (nonEscapingReceivers.contains(second)) return false; | 1716 if (nonEscapingReceivers.contains(second)) return false; |
| 1723 // Typed arrays of different types might have a shared buffer. | |
| 1724 if (couldBeTypedArray(first) && couldBeTypedArray(second)) return true; | |
| 1725 TypeMask intersection = first.instructionType.intersection( | 1717 TypeMask intersection = first.instructionType.intersection( |
| 1726 second.instructionType, compiler); | 1718 second.instructionType, compiler); |
| 1727 if (intersection.isEmpty) return false; | 1719 if (intersection.isEmpty) return false; |
| 1728 return true; | 1720 return true; |
| 1729 } | 1721 } |
| 1730 | 1722 |
| 1731 bool isFinal(Element element) { | 1723 bool isFinal(Element element) { |
| 1732 return compiler.world.fieldNeverChanges(element); | 1724 return compiler.world.fieldNeverChanges(element); |
| 1733 } | 1725 } |
| 1734 | 1726 |
| 1735 bool isConcrete(HInstruction instruction) { | 1727 bool isConcrete(HInstruction instruction) { |
| 1736 return instruction is HForeignNew | 1728 return instruction is HForeignNew |
| 1737 || instruction is HConstant | 1729 || instruction is HConstant |
| 1738 || instruction is HLiteralList; | 1730 || instruction is HLiteralList; |
| 1739 } | 1731 } |
| 1740 | 1732 |
| 1741 bool couldBeTypedArray(HInstruction receiver) { | |
| 1742 return compiler.backend.couldBeTypedArray(receiver.instructionType); | |
| 1743 } | |
| 1744 | |
| 1745 /** | 1733 /** |
| 1746 * Returns whether [receiver] escapes the current function. | 1734 * Returns whether [receiver] escapes the current function. |
| 1747 */ | 1735 */ |
| 1748 bool escapes(HInstruction receiver) { | 1736 bool escapes(HInstruction receiver) { |
| 1749 return !nonEscapingReceivers.contains(receiver); | 1737 return !nonEscapingReceivers.contains(receiver); |
| 1750 } | 1738 } |
| 1751 | 1739 |
| 1752 void registerAllocation(HInstruction instruction) { | 1740 void registerAllocation(HInstruction instruction) { |
| 1753 nonEscapingReceivers.add(instruction); | 1741 nonEscapingReceivers.add(instruction); |
| 1754 } | 1742 } |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1854 /** | 1842 /** |
| 1855 * Sets `receiver[index]` to contain [value]. Kills all potential | 1843 * Sets `receiver[index]` to contain [value]. Kills all potential |
| 1856 * places that may be affected by this update. | 1844 * places that may be affected by this update. |
| 1857 */ | 1845 */ |
| 1858 void registerKeyedValueUpdate(HInstruction receiver, | 1846 void registerKeyedValueUpdate(HInstruction receiver, |
| 1859 HInstruction index, | 1847 HInstruction index, |
| 1860 HInstruction value) { | 1848 HInstruction value) { |
| 1861 nonEscapingReceivers.remove(value); | 1849 nonEscapingReceivers.remove(value); |
| 1862 keyedValues.forEach((key, values) { | 1850 keyedValues.forEach((key, values) { |
| 1863 if (mayAlias(receiver, key)) { | 1851 if (mayAlias(receiver, key)) { |
| 1864 // Typed arrays that are views of the same buffer may have different | |
| 1865 // offsets or element sizes, unless they are the same typed array. | |
| 1866 bool weakIndex = couldBeTypedArray(key) && !mustAlias(receiver, key); | |
| 1867 values.forEach((otherIndex, otherValue) { | 1852 values.forEach((otherIndex, otherValue) { |
| 1868 if (weakIndex || mayAlias(index, otherIndex)) { | 1853 if (mayAlias(index, otherIndex)) values[otherIndex] = null; |
| 1869 values[otherIndex] = null; | |
| 1870 } | |
| 1871 }); | 1854 }); |
| 1872 } | 1855 } |
| 1873 }); | 1856 }); |
| 1874 | 1857 |
| 1858 JavaScriptBackend backend = compiler.backend; |
| 1875 // Typed arrays may narrow incoming values. | 1859 // Typed arrays may narrow incoming values. |
| 1876 if (couldBeTypedArray(receiver)) return; | 1860 if (backend.couldBeTypedArray(receiver.instructionType)) return; |
| 1877 | 1861 |
| 1878 Map<HInstruction, HInstruction> map = keyedValues.putIfAbsent( | 1862 Map<HInstruction, HInstruction> map = keyedValues.putIfAbsent( |
| 1879 receiver, () => <HInstruction, HInstruction> {}); | 1863 receiver, () => <HInstruction, HInstruction> {}); |
| 1880 map[index] = value; | 1864 map[index] = value; |
| 1881 } | 1865 } |
| 1882 | 1866 |
| 1883 /** | 1867 /** |
| 1884 * Returns null if either [first] or [second] is null. Otherwise | 1868 * Returns null if either [first] or [second] is null. Otherwise |
| 1885 * returns [first] if [first] and [second] are equal. Otherwise | 1869 * returns [first] if [first] and [second] are equal. Otherwise |
| 1886 * creates or re-uses a phi in [block] that holds [first] and [second]. | 1870 * creates or re-uses a phi in [block] that holds [first] and [second]. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1965 | 1949 |
| 1966 keyedValues.forEach((receiver, values) { | 1950 keyedValues.forEach((receiver, values) { |
| 1967 result.keyedValues[receiver] = | 1951 result.keyedValues[receiver] = |
| 1968 new Map<HInstruction, HInstruction>.from(values); | 1952 new Map<HInstruction, HInstruction>.from(values); |
| 1969 }); | 1953 }); |
| 1970 | 1954 |
| 1971 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 1955 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
| 1972 return result; | 1956 return result; |
| 1973 } | 1957 } |
| 1974 } | 1958 } |
| OLD | NEW |