OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
6 | 6 |
7 import '../common.dart'; | 7 import '../common.dart'; |
8 import '../common/names.dart'; | 8 import '../common/names.dart'; |
9 import '../compiler.dart'; | 9 import '../compiler.dart'; |
10 import '../constants/expressions.dart'; | 10 import '../constants/expressions.dart'; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 void analyze(ResolvedAst resolvedAst, ArgumentsTypes arguments); | 79 void analyze(ResolvedAst resolvedAst, ArgumentsTypes arguments); |
80 void analyzeListAndEnqueue(ListTypeInformation info); | 80 void analyzeListAndEnqueue(ListTypeInformation info); |
81 void analyzeMapAndEnqueue(MapTypeInformation info); | 81 void analyzeMapAndEnqueue(MapTypeInformation info); |
82 | 82 |
83 /// Notifies to the inferrer that [analyzedElement] can have return type | 83 /// Notifies to the inferrer that [analyzedElement] can have return type |
84 /// [newType]. [currentType] is the type the [ElementGraphBuilder] currently | 84 /// [newType]. [currentType] is the type the [ElementGraphBuilder] currently |
85 /// found. | 85 /// found. |
86 /// | 86 /// |
87 /// Returns the new type for [analyzedElement]. | 87 /// Returns the new type for [analyzedElement]. |
88 TypeInformation addReturnTypeForMethod( | 88 TypeInformation addReturnTypeForMethod( |
89 MethodElement element, TypeInformation unused, TypeInformation newType); | 89 FunctionEntity element, TypeInformation unused, TypeInformation newType); |
90 | 90 |
91 /// Applies [f] to all elements in the universe that match [selector] and | 91 /// Applies [f] to all elements in the universe that match [selector] and |
92 /// [mask]. If [f] returns false, aborts the iteration. | 92 /// [mask]. If [f] returns false, aborts the iteration. |
93 void forEachElementMatching( | 93 void forEachElementMatching( |
94 Selector selector, TypeMask mask, bool f(Element element)); | 94 Selector selector, TypeMask mask, bool f(MemberEntity element)); |
95 | 95 |
96 /// Returns the [TypeInformation] node for the default value of a parameter. | 96 /// Returns the [TypeInformation] node for the default value of a parameter. |
97 /// If this is queried before it is set by [setDefaultTypeOfParameter], a | 97 /// If this is queried before it is set by [setDefaultTypeOfParameter], a |
98 /// [PlaceholderTypeInformation] is returned, which will later be replaced | 98 /// [PlaceholderTypeInformation] is returned, which will later be replaced |
99 /// by the actual node when [setDefaultTypeOfParameter] is called. | 99 /// by the actual node when [setDefaultTypeOfParameter] is called. |
100 /// | 100 /// |
101 /// Invariant: After graph construction, no [PlaceholderTypeInformation] nodes | 101 /// Invariant: After graph construction, no [PlaceholderTypeInformation] nodes |
102 /// should be present and a default type for each parameter should exist. | 102 /// should be present and a default type for each parameter should exist. |
103 TypeInformation getDefaultTypeOfParameter(ParameterElement parameter); | 103 TypeInformation getDefaultTypeOfParameter(Local parameter); |
104 | 104 |
105 /// This helper breaks abstractions but is currently required to work around | 105 /// This helper breaks abstractions but is currently required to work around |
106 /// the wrong modeling of default values of optional parameters of | 106 /// the wrong modeling of default values of optional parameters of |
107 /// synthetic constructors. | 107 /// synthetic constructors. |
108 /// | 108 /// |
109 /// TODO(johnniwinther): Remove once default values of synthetic parameters | 109 /// TODO(johnniwinther): Remove once default values of synthetic parameters |
110 /// are fixed. | 110 /// are fixed. |
111 bool hasAlreadyComputedTypeOfParameterDefault(ParameterElement parameter); | 111 bool hasAlreadyComputedTypeOfParameterDefault(Local parameter); |
112 | 112 |
113 /// Sets the type of a parameter's default value to [type]. If the global | 113 /// Sets the type of a parameter's default value to [type]. If the global |
114 /// mapping in [defaultTypeOfParameter] already contains a type, it must be | 114 /// mapping in [defaultTypeOfParameter] already contains a type, it must be |
115 /// a [PlaceholderTypeInformation], which will be replaced. All its uses are | 115 /// a [PlaceholderTypeInformation], which will be replaced. All its uses are |
116 /// updated. | 116 /// updated. |
117 void setDefaultTypeOfParameter( | 117 void setDefaultTypeOfParameter(Local parameter, TypeInformation type); |
118 ParameterElement parameter, TypeInformation type); | |
119 | 118 |
120 Iterable<MemberEntity> getCallersOf(MemberElement element); | 119 Iterable<MemberEntity> getCallersOf(MemberEntity element); |
121 | 120 |
122 // TODO(johnniwinther): Make this private again. | 121 // TODO(johnniwinther): Make this private again. |
123 GlobalTypeInferenceElementData dataOfMember(MemberElement element); | 122 GlobalTypeInferenceElementData dataOfMember(MemberEntity element); |
124 | 123 |
125 GlobalTypeInferenceElementData lookupDataOfMember(MemberElement element); | 124 GlobalTypeInferenceElementData lookupDataOfMember(MemberEntity element); |
126 | 125 |
127 bool checkIfExposesThis(ConstructorElement element); | 126 bool checkIfExposesThis(ConstructorEntity element); |
128 | 127 |
129 void recordExposesThis(ConstructorElement element, bool exposesThis); | 128 void recordExposesThis(ConstructorEntity element, bool exposesThis); |
130 | 129 |
131 /// Records that the return type [element] is of type [type]. | 130 /// Records that the return type [element] is of type [type]. |
132 void recordReturnType(MethodElement element, TypeInformation type); | 131 void recordReturnType(FunctionEntity element, TypeInformation type); |
133 | 132 |
134 /// Records that [element] is of type [type]. | 133 /// Records that [element] is of type [type]. |
135 void recordTypeOfField(FieldElement element, TypeInformation type); | 134 void recordTypeOfField(FieldEntity element, TypeInformation type); |
136 | 135 |
137 /// Registers a call to await with an expression of type [argumentType] as | 136 /// Registers a call to await with an expression of type [argumentType] as |
138 /// argument. | 137 /// argument. |
139 TypeInformation registerAwait(ast.Node node, TypeInformation argument); | 138 TypeInformation registerAwait(ast.Node node, TypeInformation argument); |
140 | 139 |
141 /// Registers a call to yield with an expression of type [argumentType] as | 140 /// Registers a call to yield with an expression of type [argumentType] as |
142 /// argument. | 141 /// argument. |
143 TypeInformation registerYield(ast.Node node, TypeInformation argument); | 142 TypeInformation registerYield(ast.Node node, TypeInformation argument); |
144 | 143 |
145 /// Registers that [caller] calls [closure] with [arguments]. | 144 /// Registers that [caller] calls [closure] with [arguments]. |
146 /// | 145 /// |
147 /// [sideEffects] will be updated to incorporate the potential callees' side | 146 /// [sideEffects] will be updated to incorporate the potential callees' side |
148 /// effects. | 147 /// effects. |
149 /// | 148 /// |
150 /// [inLoop] tells whether the call happens in a loop. | 149 /// [inLoop] tells whether the call happens in a loop. |
151 TypeInformation registerCalledClosure( | 150 TypeInformation registerCalledClosure( |
152 ast.Node node, | 151 ast.Node node, |
153 Selector selector, | 152 Selector selector, |
154 TypeMask mask, | 153 TypeMask mask, |
155 TypeInformation closure, | 154 TypeInformation closure, |
156 MemberElement caller, | 155 MemberEntity caller, |
157 ArgumentsTypes arguments, | 156 ArgumentsTypes arguments, |
158 SideEffects sideEffects, | 157 SideEffects sideEffects, |
159 bool inLoop); | 158 bool inLoop); |
160 | 159 |
161 /// Registers that [caller] calls [callee] at location [node], with | 160 /// Registers that [caller] calls [callee] at location [node], with |
162 /// [selector], and [arguments]. Note that [selector] is null for forwarding | 161 /// [selector], and [arguments]. Note that [selector] is null for forwarding |
163 /// constructors. | 162 /// constructors. |
164 /// | 163 /// |
165 /// [sideEffects] will be updated to incorporate [callee]'s side effects. | 164 /// [sideEffects] will be updated to incorporate [callee]'s side effects. |
166 /// | 165 /// |
167 /// [inLoop] tells whether the call happens in a loop. | 166 /// [inLoop] tells whether the call happens in a loop. |
168 TypeInformation registerCalledMember( | 167 TypeInformation registerCalledMember( |
169 Spannable node, | 168 Spannable node, |
170 Selector selector, | 169 Selector selector, |
171 TypeMask mask, | 170 TypeMask mask, |
172 MemberElement caller, | 171 MemberEntity caller, |
173 MemberElement callee, | 172 MemberEntity callee, |
174 ArgumentsTypes arguments, | 173 ArgumentsTypes arguments, |
175 SideEffects sideEffects, | 174 SideEffects sideEffects, |
176 bool inLoop); | 175 bool inLoop); |
177 | 176 |
178 /// Registers that [caller] calls [selector] with [receiverType] as receiver, | 177 /// Registers that [caller] calls [selector] with [receiverType] as receiver, |
179 /// and [arguments]. | 178 /// and [arguments]. |
180 /// | 179 /// |
181 /// [sideEffects] will be updated to incorporate the potential callees' side | 180 /// [sideEffects] will be updated to incorporate the potential callees' side |
182 /// effects. | 181 /// effects. |
183 /// | 182 /// |
184 /// [inLoop] tells whether the call happens in a loop. | 183 /// [inLoop] tells whether the call happens in a loop. |
185 TypeInformation registerCalledSelector( | 184 TypeInformation registerCalledSelector( |
186 ast.Node node, | 185 ast.Node node, |
187 Selector selector, | 186 Selector selector, |
188 TypeMask mask, | 187 TypeMask mask, |
189 TypeInformation receiverType, | 188 TypeInformation receiverType, |
190 MemberElement caller, | 189 MemberEntity caller, |
191 ArgumentsTypes arguments, | 190 ArgumentsTypes arguments, |
192 SideEffects sideEffects, | 191 SideEffects sideEffects, |
193 bool inLoop, | 192 bool inLoop, |
194 bool isConditional); | 193 bool isConditional); |
195 | 194 |
196 /// Update the assignments to parameters in the graph. [remove] tells whether | 195 /// Update the assignments to parameters in the graph. [remove] tells whether |
197 /// assignments must be added or removed. If [init] is false, parameters are | 196 /// assignments must be added or removed. If [init] is false, parameters are |
198 /// added to the work queue. | 197 /// added to the work queue. |
199 void updateParameterAssignments(TypeInformation caller, MemberEntity callee, | 198 void updateParameterAssignments(TypeInformation caller, MemberEntity callee, |
200 ArgumentsTypes arguments, Selector selector, TypeMask mask, | 199 ArgumentsTypes arguments, Selector selector, TypeMask mask, |
201 {bool remove, bool addToQueue: true}); | 200 {bool remove, bool addToQueue: true}); |
202 | 201 |
203 void updateSelectorInMember( | 202 void updateSelectorInMember( |
204 MemberElement owner, Spannable node, Selector selector, TypeMask mask); | 203 MemberEntity owner, ast.Node node, Selector selector, TypeMask mask); |
205 | 204 |
206 /// Returns the return type of [element]. | 205 /// Returns the return type of [element]. |
207 TypeInformation returnTypeOfMember(MemberElement element); | 206 TypeInformation returnTypeOfMember(MemberEntity element); |
208 | 207 |
209 /// Returns the type of [element] when being called with [selector]. | 208 /// Returns the type of [element] when being called with [selector]. |
210 TypeInformation typeOfMemberWithSelector( | 209 TypeInformation typeOfMemberWithSelector( |
211 MemberElement element, Selector selector); | 210 MemberEntity element, Selector selector); |
212 | 211 |
213 /// Returns the type of [element]. | 212 /// Returns the type of [element]. |
214 TypeInformation typeOfMember(MemberElement element); | 213 TypeInformation typeOfMember(MemberEntity element); |
215 | 214 |
216 /// Returns the type of [element]. | 215 /// Returns the type of [element]. |
217 TypeInformation typeOfParameter(ParameterElement element); | 216 TypeInformation typeOfParameter(Local element); |
218 | 217 |
219 /// Returns the type for [nativeBehavior]. See documentation on | 218 /// Returns the type for [nativeBehavior]. See documentation on |
220 /// [native.NativeBehavior]. | 219 /// [native.NativeBehavior]. |
221 TypeInformation typeOfNativeBehavior(native.NativeBehavior nativeBehavior); | 220 TypeInformation typeOfNativeBehavior(native.NativeBehavior nativeBehavior); |
222 | 221 |
223 bool returnsListElementType(Selector selector, TypeMask mask); | 222 bool returnsListElementType(Selector selector, TypeMask mask); |
224 | 223 |
225 bool returnsMapValueType(Selector selector, TypeMask mask); | 224 bool returnsMapValueType(Selector selector, TypeMask mask); |
226 | 225 |
227 void clear(); | 226 void clear(); |
(...skipping 19 matching lines...) Expand all Loading... |
247 /// The [ClosedWorld] on which inference reasoning is based. | 246 /// The [ClosedWorld] on which inference reasoning is based. |
248 final ClosedWorld closedWorld; | 247 final ClosedWorld closedWorld; |
249 | 248 |
250 final ClosedWorldRefiner closedWorldRefiner; | 249 final ClosedWorldRefiner closedWorldRefiner; |
251 final TypeSystem<ast.Node> types; | 250 final TypeSystem<ast.Node> types; |
252 final Map<ast.Node, TypeInformation> concreteTypes = | 251 final Map<ast.Node, TypeInformation> concreteTypes = |
253 new Map<ast.Node, TypeInformation>(); | 252 new Map<ast.Node, TypeInformation>(); |
254 | 253 |
255 final Map<ir.Node, TypeInformation> concreteKernelTypes = | 254 final Map<ir.Node, TypeInformation> concreteKernelTypes = |
256 new Map<ir.Node, TypeInformation>(); | 255 new Map<ir.Node, TypeInformation>(); |
257 final Set<ConstructorElement> generativeConstructorsExposingThis = | 256 final Set<ConstructorEntity> generativeConstructorsExposingThis = |
258 new Set<ConstructorElement>(); | 257 new Set<ConstructorEntity>(); |
259 | 258 |
260 /// Data computed internally within elements, like the type-mask of a send a | 259 /// Data computed internally within elements, like the type-mask of a send a |
261 /// list allocation, or a for-in loop. | 260 /// list allocation, or a for-in loop. |
262 final Map<MemberElement, GlobalTypeInferenceElementData> _memberData = | 261 final Map<MemberElement, GlobalTypeInferenceElementData> _memberData = |
263 new Map<MemberElement, GlobalTypeInferenceElementData>(); | 262 new Map<MemberElement, GlobalTypeInferenceElementData>(); |
264 | 263 |
265 InferrerEngineImpl(this.compiler, ClosedWorld closedWorld, | 264 InferrerEngineImpl(this.compiler, ClosedWorld closedWorld, |
266 this.closedWorldRefiner, this.mainElement) | 265 this.closedWorldRefiner, this.mainElement) |
267 : this.types = new TypeSystem<ast.Node>( | 266 : this.types = new TypeSystem<ast.Node>( |
268 closedWorld, const TypeSystemStrategyImpl()), | 267 closedWorld, const TypeSystemStrategyImpl()), |
269 this.closedWorld = closedWorld; | 268 this.closedWorld = closedWorld; |
270 | 269 |
271 void forEachElementMatching( | 270 void forEachElementMatching( |
272 Selector selector, TypeMask mask, bool f(Element element)) { | 271 Selector selector, TypeMask mask, bool f(MemberEntity element)) { |
273 Iterable<MemberEntity> elements = closedWorld.locateMembers(selector, mask); | 272 Iterable<MemberEntity> elements = closedWorld.locateMembers(selector, mask); |
274 for (MemberElement e in elements) { | 273 for (MemberElement e in elements) { |
275 if (!f(e.implementation)) return; | 274 if (!f(e)) return; |
276 } | 275 } |
277 } | 276 } |
278 | 277 |
279 // TODO(johnniwinther): Make this private again. | 278 // TODO(johnniwinther): Make this private again. |
280 GlobalTypeInferenceElementData dataOfMember(MemberElement element) => | 279 GlobalTypeInferenceElementData dataOfMember(MemberEntity element) => |
281 _memberData.putIfAbsent( | 280 _memberData.putIfAbsent( |
282 element, () => new GlobalTypeInferenceElementData()); | 281 element, () => new GlobalTypeInferenceElementData()); |
283 | 282 |
284 GlobalTypeInferenceElementData lookupDataOfMember(MemberElement element) => | 283 GlobalTypeInferenceElementData lookupDataOfMember(MemberEntity element) => |
285 _memberData[element]; | 284 _memberData[element]; |
286 | 285 |
287 /** | 286 /** |
288 * Update [sideEffects] with the side effects of [callee] being | 287 * Update [sideEffects] with the side effects of [callee] being |
289 * called with [selector]. | 288 * called with [selector]. |
290 */ | 289 */ |
291 void updateSideEffects( | 290 void updateSideEffects( |
292 SideEffects sideEffects, Selector selector, MemberElement callee) { | 291 SideEffects sideEffects, Selector selector, MemberElement callee) { |
293 if (callee.isField) { | 292 if (callee.isField) { |
294 if (callee.isInstanceMember) { | 293 if (callee.isInstanceMember) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 } | 350 } |
352 returnType = types.computeLUB(returnType, mappedType); | 351 returnType = types.computeLUB(returnType, mappedType); |
353 if (returnType == types.dynamicType) { | 352 if (returnType == types.dynamicType) { |
354 break; | 353 break; |
355 } | 354 } |
356 } | 355 } |
357 return returnType; | 356 return returnType; |
358 } | 357 } |
359 | 358 |
360 void updateSelectorInMember( | 359 void updateSelectorInMember( |
361 MemberElement owner, Spannable node, Selector selector, TypeMask mask) { | 360 MemberEntity owner, ast.Node node, Selector selector, TypeMask mask) { |
362 GlobalTypeInferenceElementData data = dataOfMember(owner); | 361 GlobalTypeInferenceElementData data = dataOfMember(owner); |
363 ast.Node astNode = node; | 362 if (node.asSendSet() != null) { |
364 if (astNode.asSendSet() != null) { | |
365 if (selector.isSetter || selector.isIndexSet) { | 363 if (selector.isSetter || selector.isIndexSet) { |
366 data.setTypeMask(node, mask); | 364 data.setTypeMask(node, mask); |
367 } else if (selector.isGetter || selector.isIndex) { | 365 } else if (selector.isGetter || selector.isIndex) { |
368 data.setGetterTypeMaskInComplexSendSet(node, mask); | 366 data.setGetterTypeMaskInComplexSendSet(node, mask); |
369 } else { | 367 } else { |
370 assert(selector.isOperator); | 368 assert(selector.isOperator); |
371 data.setOperatorTypeMaskInComplexSendSet(node, mask); | 369 data.setOperatorTypeMaskInComplexSendSet(node, mask); |
372 } | 370 } |
373 } else if (astNode.asSend() != null) { | 371 } else if (node.asSend() != null) { |
374 data.setTypeMask(node, mask); | 372 data.setTypeMask(node, mask); |
375 } else { | 373 } else { |
376 assert(astNode.asForIn() != null); | 374 assert(node.asForIn() != null); |
377 if (selector == Selectors.iterator) { | 375 if (selector == Selectors.iterator) { |
378 data.setIteratorTypeMask(node, mask); | 376 data.setIteratorTypeMask(node, mask); |
379 } else if (selector == Selectors.current) { | 377 } else if (selector == Selectors.current) { |
380 data.setCurrentTypeMask(node, mask); | 378 data.setCurrentTypeMask(node, mask); |
381 } else { | 379 } else { |
382 assert(selector == Selectors.moveNext); | 380 assert(selector == Selectors.moveNext); |
383 data.setMoveNextTypeMask(node, mask); | 381 data.setMoveNextTypeMask(node, mask); |
384 } | 382 } |
385 } | 383 } |
386 } | 384 } |
387 | 385 |
388 bool checkIfExposesThis(ConstructorElement element) { | 386 bool checkIfExposesThis(ConstructorEntity element) { |
389 element = element.implementation; | 387 assert(!(element is ConstructorElement && !element.isDeclaration)); |
390 return generativeConstructorsExposingThis.contains(element); | 388 return generativeConstructorsExposingThis.contains(element); |
391 } | 389 } |
392 | 390 |
393 void recordExposesThis(ConstructorElement element, bool exposesThis) { | 391 void recordExposesThis(ConstructorEntity element, bool exposesThis) { |
394 element = element.implementation; | 392 assert(!(element is ConstructorElement && !element.isDeclaration)); |
395 if (exposesThis) { | 393 if (exposesThis) { |
396 generativeConstructorsExposingThis.add(element); | 394 generativeConstructorsExposingThis.add(element); |
397 } | 395 } |
398 } | 396 } |
399 | 397 |
400 bool returnsListElementType(Selector selector, TypeMask mask) { | 398 bool returnsListElementType(Selector selector, TypeMask mask) { |
401 return mask != null && | 399 return mask != null && |
402 mask.isContainer && | 400 mask.isContainer && |
403 returnsListElementTypeSet.contains(selector); | 401 returnsListElementTypeSet.contains(selector); |
404 } | 402 } |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 ? new KernelTypeGraphBuilder(element, resolvedAst, compiler, this) | 649 ? new KernelTypeGraphBuilder(element, resolvedAst, compiler, this) |
652 : new ElementGraphBuilder(element, resolvedAst, compiler, this); | 650 : new ElementGraphBuilder(element, resolvedAst, compiler, this); |
653 TypeInformation type; | 651 TypeInformation type; |
654 reporter.withCurrentElement(element, () { | 652 reporter.withCurrentElement(element, () { |
655 // ignore: UNDEFINED_METHOD | 653 // ignore: UNDEFINED_METHOD |
656 type = visitor.run(); | 654 type = visitor.run(); |
657 }); | 655 }); |
658 addedInGraph++; | 656 addedInGraph++; |
659 | 657 |
660 if (element.isField) { | 658 if (element.isField) { |
661 FieldElement fieldElement = element; | 659 FieldElement field = element; |
662 ast.Node initializer = resolvedAst.body; | 660 ast.Node initializer = resolvedAst.body; |
663 if (element.isFinal || element.isConst) { | 661 if (field.isFinal || field.isConst) { |
664 // If [element] is final and has an initializer, we record | 662 // If [element] is final and has an initializer, we record |
665 // the inferred type. | 663 // the inferred type. |
666 if (resolvedAst.body != null) { | 664 if (resolvedAst.body != null) { |
667 if (type is! ListTypeInformation && type is! MapTypeInformation) { | 665 if (type is! ListTypeInformation && type is! MapTypeInformation) { |
668 // For non-container types, the constant handler does | 666 // For non-container types, the constant handler does |
669 // constant folding that could give more precise results. | 667 // constant folding that could give more precise results. |
670 ConstantExpression constant = fieldElement.constant; | 668 ConstantExpression constant = field.constant; |
671 if (constant != null) { | 669 if (constant != null) { |
672 ConstantValue value = | 670 ConstantValue value = |
673 compiler.backend.constants.getConstantValue(constant); | 671 compiler.backend.constants.getConstantValue(constant); |
674 if (value != null) { | 672 if (value != null) { |
675 if (value.isFunction) { | 673 if (value.isFunction) { |
676 FunctionConstantValue functionConstant = value; | 674 FunctionConstantValue functionConstant = value; |
677 MethodElement function = functionConstant.element; | 675 MethodElement function = functionConstant.element; |
678 type = types.allocateClosure(function); | 676 type = types.allocateClosure(function); |
679 } else { | 677 } else { |
680 // Although we might find a better type, we have to keep | 678 // Although we might find a better type, we have to keep |
681 // the old type around to ensure that we get a complete view | 679 // the old type around to ensure that we get a complete view |
682 // of the type graph and do not drop any flow edges. | 680 // of the type graph and do not drop any flow edges. |
683 TypeMask refinedType = computeTypeMask(closedWorld, value); | 681 TypeMask refinedType = computeTypeMask(closedWorld, value); |
684 assert(TypeMask.assertIsNormalized(refinedType, closedWorld)); | 682 assert(TypeMask.assertIsNormalized(refinedType, closedWorld)); |
685 type = new NarrowTypeInformation(type, refinedType); | 683 type = new NarrowTypeInformation(type, refinedType); |
686 types.allocatedTypes.add(type); | 684 types.allocatedTypes.add(type); |
687 } | 685 } |
688 } else { | 686 } else { |
689 assert( | 687 assert( |
690 fieldElement.isInstanceMember || | 688 field.isInstanceMember || |
691 constant.isImplicit || | 689 constant.isImplicit || |
692 constant.isPotential, | 690 constant.isPotential, |
693 failedAt( | 691 failedAt( |
694 fieldElement, | 692 field, |
695 "Constant expression without value: " | 693 "Constant expression without value: " |
696 "${constant.toStructuredText()}.")); | 694 "${constant.toStructuredText()}.")); |
697 } | 695 } |
698 } | 696 } |
699 } | 697 } |
700 recordTypeOfField(element, type); | 698 recordTypeOfField(field, type); |
701 } else if (!element.isInstanceMember) { | 699 } else if (!element.isInstanceMember) { |
702 recordTypeOfField(element, types.nullType); | 700 recordTypeOfField(field, types.nullType); |
703 } | 701 } |
704 } else if (initializer == null) { | 702 } else if (initializer == null) { |
705 // Only update types of static fields if there is no | 703 // Only update types of static fields if there is no |
706 // assignment. Instance fields are dealt with in the constructor. | 704 // assignment. Instance fields are dealt with in the constructor. |
707 if (Elements.isStaticOrTopLevelField(element)) { | 705 if (Elements.isStaticOrTopLevelField(element)) { |
708 recordTypeOfField(element, type); | 706 recordTypeOfField(field, type); |
709 } | 707 } |
710 } else { | 708 } else { |
711 recordTypeOfField(element, type); | 709 recordTypeOfField(field, type); |
712 } | 710 } |
713 if (Elements.isStaticOrTopLevelField(element) && | 711 if (Elements.isStaticOrTopLevelField(field) && |
714 resolvedAst.body != null && | 712 resolvedAst.body != null && |
715 !element.isConst) { | 713 !element.isConst) { |
716 dynamic argument = resolvedAst.body; | 714 dynamic argument = resolvedAst.body; |
717 // TODO(13429): We could do better here by using the | 715 // TODO(13429): We could do better here by using the |
718 // constant handler to figure out if it's a lazy field or not. | 716 // constant handler to figure out if it's a lazy field or not. |
719 if (argument.asSend() != null || | 717 if (argument.asSend() != null || |
720 (argument.asNewExpression() != null && !argument.isConst)) { | 718 (argument.asNewExpression() != null && !argument.isConst)) { |
721 recordTypeOfField(element, types.nullType); | 719 recordTypeOfField(field, types.nullType); |
722 } | 720 } |
723 } | 721 } |
724 } else { | 722 } else { |
725 recordReturnType(element, type); | 723 MethodElement method = element; |
| 724 recordReturnType(method, type); |
726 } | 725 } |
727 } | 726 } |
728 | 727 |
729 void processLoopInformation() { | 728 void processLoopInformation() { |
730 types.allocatedCalls.forEach((dynamic info) { | 729 types.allocatedCalls.forEach((dynamic info) { |
731 if (!info.inLoop) return; | 730 if (!info.inLoop) return; |
732 if (info is StaticCallSiteTypeInformation) { | 731 if (info is StaticCallSiteTypeInformation) { |
733 MemberEntity member = info.calledElement; | 732 MemberEntity member = info.calledElement; |
734 closedWorldRefiner.addFunctionCalledInLoop(member); | 733 closedWorldRefiner.addFunctionCalledInLoop(member); |
735 } else if (info.mask != null && !info.mask.containsAll(closedWorld)) { | 734 } else if (info.mask != null && !info.mask.containsAll(closedWorld)) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
850 } else { | 849 } else { |
851 info.addAssignment(type); | 850 info.addAssignment(type); |
852 } | 851 } |
853 parameterIndex++; | 852 parameterIndex++; |
854 if (addToQueue) workQueue.add(info); | 853 if (addToQueue) workQueue.add(info); |
855 }); | 854 }); |
856 } | 855 } |
857 } | 856 } |
858 | 857 |
859 void setDefaultTypeOfParameter( | 858 void setDefaultTypeOfParameter( |
860 ParameterElement parameter, TypeInformation type) { | 859 covariant ParameterElement parameter, TypeInformation type) { |
861 assert(parameter.functionDeclaration.isImplementation); | 860 assert(parameter.functionDeclaration.isImplementation); |
862 TypeInformation existing = defaultTypeOfParameter[parameter]; | 861 TypeInformation existing = defaultTypeOfParameter[parameter]; |
863 defaultTypeOfParameter[parameter] = type; | 862 defaultTypeOfParameter[parameter] = type; |
864 TypeInformation info = types.getInferredTypeOfParameter(parameter); | 863 TypeInformation info = types.getInferredTypeOfParameter(parameter); |
865 if (existing != null && existing is PlaceholderTypeInformation) { | 864 if (existing != null && existing is PlaceholderTypeInformation) { |
866 // Replace references to [existing] to use [type] instead. | 865 // Replace references to [existing] to use [type] instead. |
867 if (parameter.functionDeclaration.isInstanceMember) { | 866 if (parameter.functionDeclaration.isInstanceMember) { |
868 ParameterAssignments assignments = info.assignments; | 867 ParameterAssignments assignments = info.assignments; |
869 assignments.replace(existing, type); | 868 assignments.replace(existing, type); |
870 } else { | 869 } else { |
871 List<TypeInformation> assignments = info.assignments; | 870 List<TypeInformation> assignments = info.assignments; |
872 for (int i = 0; i < assignments.length; i++) { | 871 for (int i = 0; i < assignments.length; i++) { |
873 if (assignments[i] == existing) { | 872 if (assignments[i] == existing) { |
874 assignments[i] = type; | 873 assignments[i] = type; |
875 } | 874 } |
876 } | 875 } |
877 } | 876 } |
878 // Also forward all users. | 877 // Also forward all users. |
879 type.addUsersOf(existing); | 878 type.addUsersOf(existing); |
880 } else { | 879 } else { |
881 assert(existing == null); | 880 assert(existing == null); |
882 } | 881 } |
883 } | 882 } |
884 | 883 |
885 TypeInformation getDefaultTypeOfParameter(ParameterElement parameter) { | 884 TypeInformation getDefaultTypeOfParameter(Local parameter) { |
886 return defaultTypeOfParameter.putIfAbsent(parameter, () { | 885 return defaultTypeOfParameter.putIfAbsent(parameter, () { |
887 return new PlaceholderTypeInformation(types.currentMember); | 886 return new PlaceholderTypeInformation(types.currentMember); |
888 }); | 887 }); |
889 } | 888 } |
890 | 889 |
891 bool hasAlreadyComputedTypeOfParameterDefault(ParameterElement parameter) { | 890 bool hasAlreadyComputedTypeOfParameterDefault(Local parameter) { |
892 TypeInformation seen = defaultTypeOfParameter[parameter]; | 891 TypeInformation seen = defaultTypeOfParameter[parameter]; |
893 return (seen != null && seen is! PlaceholderTypeInformation); | 892 return (seen != null && seen is! PlaceholderTypeInformation); |
894 } | 893 } |
895 | 894 |
896 TypeInformation typeOfParameter(ParameterElement element) { | 895 TypeInformation typeOfParameter(Local element) { |
897 return types.getInferredTypeOfParameter(element); | 896 return types.getInferredTypeOfParameter(element); |
898 } | 897 } |
899 | 898 |
900 TypeInformation typeOfMember(MemberElement element) { | 899 TypeInformation typeOfMember(MemberEntity element) { |
901 if (element is MethodElement) return types.functionType; | 900 if (element is FunctionEntity) return types.functionType; |
902 return types.getInferredTypeOfMember(element); | 901 return types.getInferredTypeOfMember(element); |
903 } | 902 } |
904 | 903 |
905 TypeInformation returnTypeOfMember(MemberElement element) { | 904 TypeInformation returnTypeOfMember(MemberEntity element) { |
906 if (element is! MethodElement) return types.dynamicType; | 905 if (element is! FunctionEntity) return types.dynamicType; |
907 return types.getInferredTypeOfMember(element); | 906 return types.getInferredTypeOfMember(element); |
908 } | 907 } |
909 | 908 |
910 void recordTypeOfField(FieldElement element, TypeInformation type) { | 909 void recordTypeOfField(FieldEntity element, TypeInformation type) { |
911 types.getInferredTypeOfMember(element).addAssignment(type); | 910 types.getInferredTypeOfMember(element).addAssignment(type); |
912 } | 911 } |
913 | 912 |
914 void recordReturnType(MethodElement element, TypeInformation type) { | 913 void recordReturnType(FunctionEntity element, TypeInformation type) { |
915 TypeInformation info = types.getInferredTypeOfMember(element); | 914 TypeInformation info = types.getInferredTypeOfMember(element); |
916 if (element.name == '==') { | 915 if (element.name == '==') { |
917 // Even if x.== doesn't return a bool, 'x == null' evaluates to 'false'. | 916 // Even if x.== doesn't return a bool, 'x == null' evaluates to 'false'. |
918 info.addAssignment(types.boolType); | 917 info.addAssignment(types.boolType); |
919 } | 918 } |
920 // TODO(ngeoffray): Clean up. We do these checks because | 919 // TODO(ngeoffray): Clean up. We do these checks because |
921 // [SimpleTypesInferrer] deals with two different inferrers. | 920 // [SimpleTypesInferrer] deals with two different inferrers. |
922 if (type == null) return; | 921 if (type == null) return; |
923 if (info.assignments.isEmpty) info.addAssignment(type); | 922 if (info.assignments.isEmpty) info.addAssignment(type); |
924 } | 923 } |
925 | 924 |
926 TypeInformation addReturnTypeForMethod( | 925 TypeInformation addReturnTypeForMethod(covariant MethodElement element, |
927 MethodElement element, TypeInformation unused, TypeInformation newType) { | 926 TypeInformation unused, TypeInformation newType) { |
928 TypeInformation type = types.getInferredTypeOfMember(element); | 927 TypeInformation type = types.getInferredTypeOfMember(element); |
929 // TODO(ngeoffray): Clean up. We do this check because | 928 // TODO(ngeoffray): Clean up. We do this check because |
930 // [SimpleTypesInferrer] deals with two different inferrers. | 929 // [SimpleTypesInferrer] deals with two different inferrers. |
931 if (element.isGenerativeConstructor) return type; | 930 if (element.isGenerativeConstructor) return type; |
932 type.addAssignment(newType); | 931 type.addAssignment(newType); |
933 return type; | 932 return type; |
934 } | 933 } |
935 | 934 |
936 TypeInformation registerCalledMember( | 935 TypeInformation registerCalledMember( |
937 Spannable node, | 936 Spannable node, |
938 Selector selector, | 937 Selector selector, |
939 TypeMask mask, | 938 TypeMask mask, |
940 MemberElement caller, | 939 MemberEntity caller, |
941 MemberElement callee, | 940 covariant MemberElement callee, |
942 ArgumentsTypes arguments, | 941 ArgumentsTypes arguments, |
943 SideEffects sideEffects, | 942 SideEffects sideEffects, |
944 bool inLoop) { | 943 bool inLoop) { |
945 CallSiteTypeInformation info = new StaticCallSiteTypeInformation( | 944 CallSiteTypeInformation info = new StaticCallSiteTypeInformation( |
946 types.currentMember, | 945 types.currentMember, |
947 node, | 946 node, |
948 caller, | 947 caller, |
949 callee, | 948 callee, |
950 selector, | 949 selector, |
951 mask, | 950 mask, |
(...skipping 14 matching lines...) Expand all Loading... |
966 types.allocatedCalls.add(info); | 965 types.allocatedCalls.add(info); |
967 updateSideEffects(sideEffects, selector, callee); | 966 updateSideEffects(sideEffects, selector, callee); |
968 return info; | 967 return info; |
969 } | 968 } |
970 | 969 |
971 TypeInformation registerCalledSelector( | 970 TypeInformation registerCalledSelector( |
972 ast.Node node, | 971 ast.Node node, |
973 Selector selector, | 972 Selector selector, |
974 TypeMask mask, | 973 TypeMask mask, |
975 TypeInformation receiverType, | 974 TypeInformation receiverType, |
976 MemberElement caller, | 975 MemberEntity caller, |
977 ArgumentsTypes arguments, | 976 ArgumentsTypes arguments, |
978 SideEffects sideEffects, | 977 SideEffects sideEffects, |
979 bool inLoop, | 978 bool inLoop, |
980 bool isConditional) { | 979 bool isConditional) { |
981 if (selector.isClosureCall) { | 980 if (selector.isClosureCall) { |
982 return registerCalledClosure(node, selector, mask, receiverType, caller, | 981 return registerCalledClosure(node, selector, mask, receiverType, caller, |
983 arguments, sideEffects, inLoop); | 982 arguments, sideEffects, inLoop); |
984 } | 983 } |
985 | 984 |
986 closedWorld.locateMembers(selector, mask).forEach((_callee) { | 985 closedWorld.locateMembers(selector, mask).forEach((_callee) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1018 info.addAssignment(argument); | 1017 info.addAssignment(argument); |
1019 types.allocatedTypes.add(info); | 1018 types.allocatedTypes.add(info); |
1020 return info; | 1019 return info; |
1021 } | 1020 } |
1022 | 1021 |
1023 TypeInformation registerCalledClosure( | 1022 TypeInformation registerCalledClosure( |
1024 ast.Node node, | 1023 ast.Node node, |
1025 Selector selector, | 1024 Selector selector, |
1026 TypeMask mask, | 1025 TypeMask mask, |
1027 TypeInformation closure, | 1026 TypeInformation closure, |
1028 MemberElement caller, | 1027 MemberEntity caller, |
1029 ArgumentsTypes arguments, | 1028 ArgumentsTypes arguments, |
1030 SideEffects sideEffects, | 1029 SideEffects sideEffects, |
1031 bool inLoop) { | 1030 bool inLoop) { |
1032 sideEffects.setDependsOnSomething(); | 1031 sideEffects.setDependsOnSomething(); |
1033 sideEffects.setAllSideEffects(); | 1032 sideEffects.setAllSideEffects(); |
1034 CallSiteTypeInformation info = new ClosureCallSiteTypeInformation( | 1033 CallSiteTypeInformation info = new ClosureCallSiteTypeInformation( |
1035 types.currentMember, | 1034 types.currentMember, |
1036 node, | 1035 node, |
1037 caller, | 1036 caller, |
1038 selector, | 1037 selector, |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1104 types.allocatedClosures.forEach(cleanup); | 1103 types.allocatedClosures.forEach(cleanup); |
1105 types.allocatedClosures.clear(); | 1104 types.allocatedClosures.clear(); |
1106 | 1105 |
1107 analyzedElements.clear(); | 1106 analyzedElements.clear(); |
1108 generativeConstructorsExposingThis.clear(); | 1107 generativeConstructorsExposingThis.clear(); |
1109 | 1108 |
1110 types.allocatedMaps.values.forEach(cleanup); | 1109 types.allocatedMaps.values.forEach(cleanup); |
1111 types.allocatedLists.values.forEach(cleanup); | 1110 types.allocatedLists.values.forEach(cleanup); |
1112 } | 1111 } |
1113 | 1112 |
1114 Iterable<MemberEntity> getCallersOf(MemberElement element) { | 1113 Iterable<MemberEntity> getCallersOf(MemberEntity element) { |
1115 if (compiler.disableTypeInference) { | 1114 if (compiler.disableTypeInference) { |
1116 throw new UnsupportedError( | 1115 throw new UnsupportedError( |
1117 "Cannot query the type inferrer when type inference is disabled."); | 1116 "Cannot query the type inferrer when type inference is disabled."); |
1118 } | 1117 } |
1119 MemberTypeInformation info = types.getInferredTypeOfMember(element); | 1118 MemberTypeInformation info = types.getInferredTypeOfMember(element); |
1120 return info.callers; | 1119 return info.callers; |
1121 } | 1120 } |
1122 | 1121 |
1123 TypeInformation typeOfMemberWithSelector( | 1122 TypeInformation typeOfMemberWithSelector( |
1124 MemberElement element, Selector selector) { | 1123 covariant MemberElement element, Selector selector) { |
1125 if (element.name == Identifiers.noSuchMethod_ && | 1124 if (element.name == Identifiers.noSuchMethod_ && |
1126 selector.name != element.name) { | 1125 selector.name != element.name) { |
1127 // An invocation can resolve to a [noSuchMethod], in which case | 1126 // An invocation can resolve to a [noSuchMethod], in which case |
1128 // we get the return type of [noSuchMethod]. | 1127 // we get the return type of [noSuchMethod]. |
1129 return returnTypeOfMember(element); | 1128 return returnTypeOfMember(element); |
1130 } else if (selector.isGetter) { | 1129 } else if (selector.isGetter) { |
1131 if (element.isFunction) { | 1130 if (element.isFunction) { |
1132 // [functionType] is null if the inferrer did not run. | 1131 // [functionType] is null if the inferrer did not run. |
1133 return types.functionType == null | 1132 return types.functionType == null |
1134 ? types.dynamicType | 1133 ? types.dynamicType |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1243 @override | 1242 @override |
1244 bool checkPhiNode(ast.Node node) { | 1243 bool checkPhiNode(ast.Node node) { |
1245 return true; | 1244 return true; |
1246 } | 1245 } |
1247 | 1246 |
1248 @override | 1247 @override |
1249 bool checkClassEntity(covariant ClassElement cls) { | 1248 bool checkClassEntity(covariant ClassElement cls) { |
1250 return cls.isDeclaration; | 1249 return cls.isDeclaration; |
1251 } | 1250 } |
1252 } | 1251 } |
OLD | NEW |