| 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 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 Element element = | 417 Element element = |
| 418 compiler.world.locateSingleElement(node.selector, receiverType); | 418 compiler.world.locateSingleElement(node.selector, receiverType); |
| 419 // TODO(ngeoffray): Also fold if it's a getter or variable. | 419 // TODO(ngeoffray): Also fold if it's a getter or variable. |
| 420 if (element != null | 420 if (element != null |
| 421 && element.isFunction | 421 && element.isFunction |
| 422 // If we found out that the only target is a [:noSuchMethod:], | 422 // If we found out that the only target is a [:noSuchMethod:], |
| 423 // we just ignore it. | 423 // we just ignore it. |
| 424 && element.name == node.selector.name) { | 424 && element.name == node.selector.name) { |
| 425 FunctionElement method = element; | 425 FunctionElement method = element; |
| 426 | 426 |
| 427 if (method.isNative) { | 427 if (backend.isNative(method)) { |
| 428 HInstruction folded = tryInlineNativeMethod(node, method); | 428 HInstruction folded = tryInlineNativeMethod(node, method); |
| 429 if (folded != null) return folded; | 429 if (folded != null) return folded; |
| 430 } else { | 430 } else { |
| 431 // TODO(ngeoffray): If the method has optional parameters, | 431 // TODO(ngeoffray): If the method has optional parameters, |
| 432 // we should pass the default values. | 432 // we should pass the default values. |
| 433 FunctionSignature parameters = method.functionSignature; | 433 FunctionSignature parameters = method.functionSignature; |
| 434 if (parameters.optionalParameterCount == 0 || | 434 if (parameters.optionalParameterCount == 0 || |
| 435 parameters.parameterCount == | 435 parameters.parameterCount == |
| 436 node.selector.argumentCount) { | 436 node.selector.argumentCount) { |
| 437 node.element = element; | 437 node.element = element; |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 Element field = findConcreteFieldForDynamicAccess( | 851 Element field = findConcreteFieldForDynamicAccess( |
| 852 receiver, node.selector); | 852 receiver, node.selector); |
| 853 if (field == null) return node; | 853 if (field == null) return node; |
| 854 return directFieldGet(receiver, field); | 854 return directFieldGet(receiver, field); |
| 855 } | 855 } |
| 856 | 856 |
| 857 HInstruction directFieldGet(HInstruction receiver, Element field) { | 857 HInstruction directFieldGet(HInstruction receiver, Element field) { |
| 858 bool isAssignable = !compiler.world.fieldNeverChanges(field); | 858 bool isAssignable = !compiler.world.fieldNeverChanges(field); |
| 859 | 859 |
| 860 TypeMask type; | 860 TypeMask type; |
| 861 if (field.enclosingClass.isNative) { | 861 if (backend.isNative(field.enclosingClass)) { |
| 862 type = TypeMaskFactory.fromNativeBehavior( | 862 type = TypeMaskFactory.fromNativeBehavior( |
| 863 native.NativeBehavior.ofFieldLoad(field, compiler), | 863 native.NativeBehavior.ofFieldLoad(field, compiler), |
| 864 compiler); | 864 compiler); |
| 865 } else { | 865 } else { |
| 866 type = TypeMaskFactory.inferredTypeForElement(field, compiler); | 866 type = TypeMaskFactory.inferredTypeForElement(field, compiler); |
| 867 } | 867 } |
| 868 | 868 |
| 869 return new HFieldGet( | 869 return new HFieldGet( |
| 870 field, receiver, type, isAssignable: isAssignable); | 870 field, receiver, type, isAssignable: isAssignable); |
| 871 } | 871 } |
| (...skipping 1250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2122 final Map<HInstruction, Map<HInstruction, HInstruction>> keyedValues = | 2122 final Map<HInstruction, Map<HInstruction, HInstruction>> keyedValues = |
| 2123 <HInstruction, Map<HInstruction, HInstruction>> {}; | 2123 <HInstruction, Map<HInstruction, HInstruction>> {}; |
| 2124 | 2124 |
| 2125 /** | 2125 /** |
| 2126 * Set of objects that we know don't escape the current function. | 2126 * Set of objects that we know don't escape the current function. |
| 2127 */ | 2127 */ |
| 2128 final Setlet<HInstruction> nonEscapingReceivers = new Setlet<HInstruction>(); | 2128 final Setlet<HInstruction> nonEscapingReceivers = new Setlet<HInstruction>(); |
| 2129 | 2129 |
| 2130 MemorySet(this.compiler); | 2130 MemorySet(this.compiler); |
| 2131 | 2131 |
| 2132 JavaScriptBackend get backend => compiler.backend; |
| 2133 |
| 2132 /** | 2134 /** |
| 2133 * Returns whether [first] and [second] always alias to the same object. | 2135 * Returns whether [first] and [second] always alias to the same object. |
| 2134 */ | 2136 */ |
| 2135 bool mustAlias(HInstruction first, HInstruction second) { | 2137 bool mustAlias(HInstruction first, HInstruction second) { |
| 2136 return first == second; | 2138 return first == second; |
| 2137 } | 2139 } |
| 2138 | 2140 |
| 2139 /** | 2141 /** |
| 2140 * Returns whether [first] and [second] may alias to the same object. | 2142 * Returns whether [first] and [second] may alias to the same object. |
| 2141 */ | 2143 */ |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2178 nonEscapingReceivers.add(instruction); | 2180 nonEscapingReceivers.add(instruction); |
| 2179 } | 2181 } |
| 2180 | 2182 |
| 2181 /** | 2183 /** |
| 2182 * Sets `receiver.element` to contain [value]. Kills all potential | 2184 * Sets `receiver.element` to contain [value]. Kills all potential |
| 2183 * places that may be affected by this update. | 2185 * places that may be affected by this update. |
| 2184 */ | 2186 */ |
| 2185 void registerFieldValueUpdate(Element element, | 2187 void registerFieldValueUpdate(Element element, |
| 2186 HInstruction receiver, | 2188 HInstruction receiver, |
| 2187 HInstruction value) { | 2189 HInstruction value) { |
| 2188 if (element.isNative) return; // TODO(14955): Remove this restriction? | 2190 if (backend.isNative(element)) { |
| 2191 return; // TODO(14955): Remove this restriction? |
| 2192 } |
| 2189 // [value] is being set in some place in memory, we remove it from | 2193 // [value] is being set in some place in memory, we remove it from |
| 2190 // the non-escaping set. | 2194 // the non-escaping set. |
| 2191 nonEscapingReceivers.remove(value); | 2195 nonEscapingReceivers.remove(value); |
| 2192 Map<HInstruction, HInstruction> map = fieldValues.putIfAbsent( | 2196 Map<HInstruction, HInstruction> map = fieldValues.putIfAbsent( |
| 2193 element, () => <HInstruction, HInstruction> {}); | 2197 element, () => <HInstruction, HInstruction> {}); |
| 2194 map.forEach((key, value) { | 2198 map.forEach((key, value) { |
| 2195 if (mayAlias(receiver, key)) map[key] = null; | 2199 if (mayAlias(receiver, key)) map[key] = null; |
| 2196 }); | 2200 }); |
| 2197 map[receiver] = value; | 2201 map[receiver] = value; |
| 2198 } | 2202 } |
| 2199 | 2203 |
| 2200 /** | 2204 /** |
| 2201 * Registers that `receiver.element` is now [value]. | 2205 * Registers that `receiver.element` is now [value]. |
| 2202 */ | 2206 */ |
| 2203 void registerFieldValue(Element element, | 2207 void registerFieldValue(Element element, |
| 2204 HInstruction receiver, | 2208 HInstruction receiver, |
| 2205 HInstruction value) { | 2209 HInstruction value) { |
| 2206 if (element.isNative) return; // TODO(14955): Remove this restriction? | 2210 if (backend.isNative(element)) { |
| 2211 return; // TODO(14955): Remove this restriction? |
| 2212 } |
| 2207 Map<HInstruction, HInstruction> map = fieldValues.putIfAbsent( | 2213 Map<HInstruction, HInstruction> map = fieldValues.putIfAbsent( |
| 2208 element, () => <HInstruction, HInstruction> {}); | 2214 element, () => <HInstruction, HInstruction> {}); |
| 2209 map[receiver] = value; | 2215 map[receiver] = value; |
| 2210 } | 2216 } |
| 2211 | 2217 |
| 2212 /** | 2218 /** |
| 2213 * Returns the value stored in `receiver.element`. Returns null if | 2219 * Returns the value stored in `receiver.element`. Returns null if |
| 2214 * we don't know. | 2220 * we don't know. |
| 2215 */ | 2221 */ |
| 2216 HInstruction lookupFieldValue(Element element, HInstruction receiver) { | 2222 HInstruction lookupFieldValue(Element element, HInstruction receiver) { |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2390 | 2396 |
| 2391 keyedValues.forEach((receiver, values) { | 2397 keyedValues.forEach((receiver, values) { |
| 2392 result.keyedValues[receiver] = | 2398 result.keyedValues[receiver] = |
| 2393 new Map<HInstruction, HInstruction>.from(values); | 2399 new Map<HInstruction, HInstruction>.from(values); |
| 2394 }); | 2400 }); |
| 2395 | 2401 |
| 2396 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2402 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
| 2397 return result; | 2403 return result; |
| 2398 } | 2404 } |
| 2399 } | 2405 } |
| OLD | NEW |