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