| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library locals_handler; | 5 library locals_handler; |
| 6 | 6 |
| 7 import 'dart:collection' show IterableMixin; | 7 import 'dart:collection' show IterableMixin; |
| 8 | 8 |
| 9 import '../options.dart' show CompilerOptions; | 9 import '../options.dart' show CompilerOptions; |
| 10 import '../elements/elements.dart'; | 10 import '../elements/elements.dart'; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 if (variables == null) return false; | 95 if (variables == null) return false; |
| 96 return variables.containsKey(variable); | 96 return variables.containsKey(variable); |
| 97 } | 97 } |
| 98 | 98 |
| 99 String toString() { | 99 String toString() { |
| 100 String rest = parent == null ? "null" : parent.toString(); | 100 String rest = parent == null ? "null" : parent.toString(); |
| 101 return '$variables $rest'; | 101 return '$variables $rest'; |
| 102 } | 102 } |
| 103 } | 103 } |
| 104 | 104 |
| 105 /// Tracks initializers via initializations and assignments. |
| 105 class FieldInitializationScope { | 106 class FieldInitializationScope { |
| 106 final TypeSystem types; | 107 final TypeSystem types; |
| 107 Map<Element, TypeInformation> fields; | 108 Map<Element, TypeInformation> fields; |
| 108 bool isThisExposed; | 109 bool isThisExposed; |
| 109 | 110 |
| 110 FieldInitializationScope(this.types) : isThisExposed = false; | 111 /// `true` when control flow prevents accumulating definite assignments, |
| 112 /// e.g. an early return or caught exception. |
| 113 bool isIndefinite; |
| 114 |
| 115 FieldInitializationScope(this.types) |
| 116 : isThisExposed = false, |
| 117 isIndefinite = false; |
| 111 | 118 |
| 112 FieldInitializationScope.internalFrom(FieldInitializationScope other) | 119 FieldInitializationScope.internalFrom(FieldInitializationScope other) |
| 113 : types = other.types, | 120 : types = other.types, |
| 114 isThisExposed = other.isThisExposed; | 121 isThisExposed = other.isThisExposed, |
| 122 isIndefinite = other.isIndefinite; |
| 115 | 123 |
| 116 factory FieldInitializationScope.from(FieldInitializationScope other) { | 124 factory FieldInitializationScope.from(FieldInitializationScope other) { |
| 117 if (other == null) return null; | 125 if (other == null) return null; |
| 118 return new FieldInitializationScope.internalFrom(other); | 126 return new FieldInitializationScope.internalFrom(other); |
| 119 } | 127 } |
| 120 | 128 |
| 121 void updateField(Element field, TypeInformation type) { | 129 void updateField(Element field, TypeInformation type) { |
| 122 if (isThisExposed) return; | 130 if (isThisExposed) return; |
| 123 if (fields == null) fields = new Map<Element, TypeInformation>(); | 131 if (isIndefinite) return; |
| 132 fields ??= new Map<Element, TypeInformation>(); |
| 124 fields[field] = type; | 133 fields[field] = type; |
| 125 } | 134 } |
| 126 | 135 |
| 127 TypeInformation readField(Element field) { | 136 TypeInformation readField(Element field) { |
| 128 return fields == null ? null : fields[field]; | 137 return fields == null ? null : fields[field]; |
| 129 } | 138 } |
| 130 | 139 |
| 131 void forEach(void f(Element element, TypeInformation type)) { | 140 void forEach(void f(Element element, TypeInformation type)) { |
| 132 if (fields == null) return; | 141 fields?.forEach(f); |
| 133 fields.forEach(f); | |
| 134 } | 142 } |
| 135 | 143 |
| 136 void mergeDiamondFlow( | 144 void mergeDiamondFlow( |
| 137 FieldInitializationScope thenScope, FieldInitializationScope elseScope) { | 145 FieldInitializationScope thenScope, FieldInitializationScope elseScope) { |
| 138 // Quick bailout check. If [isThisExposed] is true, we know the | 146 // Quick bailout check. If [isThisExposed] or [isIndefinite] is true, we |
| 139 // code following won'TypeInformation do anything. | 147 // know the code following won'TypeInformation do anything. |
| 140 if (isThisExposed) return; | 148 if (isThisExposed) return; |
| 141 if (elseScope == null || elseScope.fields == null) { | 149 if (isIndefinite) return; |
| 142 elseScope = this; | 150 |
| 143 } | 151 FieldInitializationScope otherScope = |
| 152 (elseScope == null || elseScope.fields == null) ? this : elseScope; |
| 144 | 153 |
| 145 thenScope.forEach((Element field, TypeInformation type) { | 154 thenScope.forEach((Element field, TypeInformation type) { |
| 146 TypeInformation otherType = elseScope.readField(field); | 155 TypeInformation otherType = otherScope.readField(field); |
| 147 if (otherType == null) return; | 156 if (otherType == null) return; |
| 148 updateField(field, types.allocateDiamondPhi(type, otherType)); | 157 updateField(field, types.allocateDiamondPhi(type, otherType)); |
| 149 }); | 158 }); |
| 159 |
| 150 isThisExposed = thenScope.isThisExposed || elseScope.isThisExposed; | 160 isThisExposed = thenScope.isThisExposed || elseScope.isThisExposed; |
| 161 isIndefinite = thenScope.isIndefinite || elseScope.isIndefinite; |
| 151 } | 162 } |
| 152 } | 163 } |
| 153 | 164 |
| 154 /** | 165 /** |
| 155 * Placeholder for inferred arguments types on sends. | 166 * Placeholder for inferred arguments types on sends. |
| 156 */ | 167 */ |
| 157 class ArgumentsTypes extends IterableMixin<TypeInformation> { | 168 class ArgumentsTypes extends IterableMixin<TypeInformation> { |
| 158 final List<TypeInformation> positional; | 169 final List<TypeInformation> positional; |
| 159 final Map<String, TypeInformation> named; | 170 final Map<String, TypeInformation> named; |
| 160 ArgumentsTypes(this.positional, named) | 171 ArgumentsTypes(this.positional, named) |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 if (newType != type) { | 543 if (newType != type) { |
| 533 locals[variable] = newType; | 544 locals[variable] = newType; |
| 534 } | 545 } |
| 535 }); | 546 }); |
| 536 } | 547 } |
| 537 | 548 |
| 538 void updateField(Element element, TypeInformation type) { | 549 void updateField(Element element, TypeInformation type) { |
| 539 fieldScope.updateField(element, type); | 550 fieldScope.updateField(element, type); |
| 540 } | 551 } |
| 541 } | 552 } |
| OLD | NEW |