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 |