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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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(Local 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(Local parameter, TypeInformation type); | 117 void setDefaultTypeOfParameter(Local parameter, TypeInformation type, |
| 118 {bool isInstanceMember}); |
118 | 119 |
119 Iterable<MemberEntity> getCallersOf(MemberEntity element); | 120 Iterable<MemberEntity> getCallersOf(MemberEntity element); |
120 | 121 |
121 // TODO(johnniwinther): Make this private again. | 122 // TODO(johnniwinther): Make this private again. |
122 GlobalTypeInferenceElementData dataOfMember(MemberEntity element); | 123 GlobalTypeInferenceElementData dataOfMember(MemberEntity element); |
123 | 124 |
124 GlobalTypeInferenceElementData lookupDataOfMember(MemberEntity element); | 125 GlobalTypeInferenceElementData lookupDataOfMember(MemberEntity element); |
125 | 126 |
126 bool checkIfExposesThis(ConstructorEntity element); | 127 bool checkIfExposesThis(ConstructorEntity element); |
127 | 128 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 TypeInformation typeOfNativeBehavior(native.NativeBehavior nativeBehavior); | 221 TypeInformation typeOfNativeBehavior(native.NativeBehavior nativeBehavior); |
221 | 222 |
222 bool returnsListElementType(Selector selector, TypeMask mask); | 223 bool returnsListElementType(Selector selector, TypeMask mask); |
223 | 224 |
224 bool returnsMapValueType(Selector selector, TypeMask mask); | 225 bool returnsMapValueType(Selector selector, TypeMask mask); |
225 | 226 |
226 void clear(); | 227 void clear(); |
227 } | 228 } |
228 | 229 |
229 class InferrerEngineImpl extends InferrerEngine { | 230 class InferrerEngineImpl extends InferrerEngine { |
230 final Map<ParameterElement, TypeInformation> defaultTypeOfParameter = | 231 final Map<Local, TypeInformation> defaultTypeOfParameter = |
231 new Map<ParameterElement, TypeInformation>(); | 232 new Map<Local, TypeInformation>(); |
232 final WorkQueue workQueue = new WorkQueue(); | 233 final WorkQueue workQueue = new WorkQueue(); |
233 final FunctionEntity mainElement; | 234 final FunctionEntity mainElement; |
234 final Set<MemberElement> analyzedElements = new Set<MemberElement>(); | 235 final Set<MemberEntity> analyzedElements = new Set<MemberEntity>(); |
235 | 236 |
236 /// The maximum number of times we allow a node in the graph to | 237 /// The maximum number of times we allow a node in the graph to |
237 /// change types. If a node reaches that limit, we give up | 238 /// change types. If a node reaches that limit, we give up |
238 /// inferencing on it and give it the dynamic type. | 239 /// inferencing on it and give it the dynamic type. |
239 final int MAX_CHANGE_COUNT = 6; | 240 final int MAX_CHANGE_COUNT = 6; |
240 | 241 |
241 int overallRefineCount = 0; | 242 int overallRefineCount = 0; |
242 int addedInGraph = 0; | 243 int addedInGraph = 0; |
243 | 244 |
244 final Compiler compiler; | 245 final Compiler compiler; |
245 | 246 |
246 /// The [ClosedWorld] on which inference reasoning is based. | 247 /// The [ClosedWorld] on which inference reasoning is based. |
247 final ClosedWorld closedWorld; | 248 final ClosedWorld closedWorld; |
248 | 249 |
249 final ClosedWorldRefiner closedWorldRefiner; | 250 final ClosedWorldRefiner closedWorldRefiner; |
250 final TypeSystem<ast.Node> types; | 251 final TypeSystem<ast.Node> types; |
251 final Map<ast.Node, TypeInformation> concreteTypes = | 252 final Map<ast.Node, TypeInformation> concreteTypes = |
252 new Map<ast.Node, TypeInformation>(); | 253 new Map<ast.Node, TypeInformation>(); |
253 | 254 |
254 final Map<ir.Node, TypeInformation> concreteKernelTypes = | 255 final Map<ir.Node, TypeInformation> concreteKernelTypes = |
255 new Map<ir.Node, TypeInformation>(); | 256 new Map<ir.Node, TypeInformation>(); |
256 final Set<ConstructorEntity> generativeConstructorsExposingThis = | 257 final Set<ConstructorEntity> generativeConstructorsExposingThis = |
257 new Set<ConstructorEntity>(); | 258 new Set<ConstructorEntity>(); |
258 | 259 |
259 /// Data computed internally within elements, like the type-mask of a send a | 260 /// Data computed internally within elements, like the type-mask of a send a |
260 /// list allocation, or a for-in loop. | 261 /// list allocation, or a for-in loop. |
261 final Map<MemberElement, GlobalTypeInferenceElementData> _memberData = | 262 final Map<MemberEntity, GlobalTypeInferenceElementData> _memberData = |
262 new Map<MemberElement, GlobalTypeInferenceElementData>(); | 263 new Map<MemberEntity, GlobalTypeInferenceElementData>(); |
263 | 264 |
264 InferrerEngineImpl(this.compiler, ClosedWorld closedWorld, | 265 InferrerEngineImpl(this.compiler, ClosedWorld closedWorld, |
265 this.closedWorldRefiner, this.mainElement) | 266 this.closedWorldRefiner, this.mainElement) |
266 : this.types = new TypeSystem<ast.Node>( | 267 : this.types = new TypeSystem<ast.Node>( |
267 closedWorld, const TypeSystemStrategyImpl()), | 268 closedWorld, const TypeSystemStrategyImpl()), |
268 this.closedWorld = closedWorld; | 269 this.closedWorld = closedWorld; |
269 | 270 |
270 void forEachElementMatching( | 271 void forEachElementMatching( |
271 Selector selector, TypeMask mask, bool f(MemberEntity element)) { | 272 Selector selector, TypeMask mask, bool f(MemberEntity element)) { |
272 Iterable<MemberEntity> elements = closedWorld.locateMembers(selector, mask); | 273 Iterable<MemberEntity> elements = closedWorld.locateMembers(selector, mask); |
273 for (MemberElement e in elements) { | 274 for (MemberEntity e in elements) { |
274 if (!f(e)) return; | 275 if (!f(e)) return; |
275 } | 276 } |
276 } | 277 } |
277 | 278 |
278 // TODO(johnniwinther): Make this private again. | 279 // TODO(johnniwinther): Make this private again. |
279 GlobalTypeInferenceElementData dataOfMember(MemberEntity element) => | 280 GlobalTypeInferenceElementData dataOfMember(MemberEntity element) => |
280 _memberData.putIfAbsent( | 281 _memberData.putIfAbsent( |
281 element, () => new GlobalTypeInferenceElementData()); | 282 element, () => new GlobalTypeInferenceElementData()); |
282 | 283 |
283 GlobalTypeInferenceElementData lookupDataOfMember(MemberEntity element) => | 284 GlobalTypeInferenceElementData lookupDataOfMember(MemberEntity element) => |
284 _memberData[element]; | 285 _memberData[element]; |
285 | 286 |
286 /** | 287 /** |
287 * Update [sideEffects] with the side effects of [callee] being | 288 * Update [sideEffects] with the side effects of [callee] being |
288 * called with [selector]. | 289 * called with [selector]. |
289 */ | 290 */ |
290 void updateSideEffects( | 291 void updateSideEffects( |
291 SideEffects sideEffects, Selector selector, MemberElement callee) { | 292 SideEffects sideEffects, Selector selector, MemberEntity callee) { |
| 293 assert(!(callee is MemberElement && !callee.isDeclaration)); |
292 if (callee.isField) { | 294 if (callee.isField) { |
293 if (callee.isInstanceMember) { | 295 if (callee.isInstanceMember) { |
294 if (selector.isSetter) { | 296 if (selector.isSetter) { |
295 sideEffects.setChangesInstanceProperty(); | 297 sideEffects.setChangesInstanceProperty(); |
296 } else if (selector.isGetter) { | 298 } else if (selector.isGetter) { |
297 sideEffects.setDependsOnInstancePropertyStore(); | 299 sideEffects.setDependsOnInstancePropertyStore(); |
298 } else { | 300 } else { |
299 sideEffects.setAllSideEffects(); | 301 sideEffects.setAllSideEffects(); |
300 sideEffects.setDependsOnSomething(); | 302 sideEffects.setDependsOnSomething(); |
301 } | 303 } |
302 } else { | 304 } else { |
303 if (selector.isSetter) { | 305 if (selector.isSetter) { |
304 sideEffects.setChangesStaticProperty(); | 306 sideEffects.setChangesStaticProperty(); |
305 } else if (selector.isGetter) { | 307 } else if (selector.isGetter) { |
306 sideEffects.setDependsOnStaticPropertyStore(); | 308 sideEffects.setDependsOnStaticPropertyStore(); |
307 } else { | 309 } else { |
308 sideEffects.setAllSideEffects(); | 310 sideEffects.setAllSideEffects(); |
309 sideEffects.setDependsOnSomething(); | 311 sideEffects.setDependsOnSomething(); |
310 } | 312 } |
311 } | 313 } |
312 } else if (callee.isGetter && !selector.isGetter) { | 314 } else if (callee.isGetter && !selector.isGetter) { |
313 sideEffects.setAllSideEffects(); | 315 sideEffects.setAllSideEffects(); |
314 sideEffects.setDependsOnSomething(); | 316 sideEffects.setDependsOnSomething(); |
315 } else { | 317 } else { |
316 MethodElement method = callee.declaration; | 318 sideEffects.add(closedWorldRefiner.getCurrentlyKnownSideEffects(callee)); |
317 sideEffects.add(closedWorldRefiner.getCurrentlyKnownSideEffects(method)); | |
318 } | 319 } |
319 } | 320 } |
320 | 321 |
321 TypeInformation typeOfNativeBehavior(native.NativeBehavior nativeBehavior) { | 322 TypeInformation typeOfNativeBehavior(native.NativeBehavior nativeBehavior) { |
322 if (nativeBehavior == null) return types.dynamicType; | 323 if (nativeBehavior == null) return types.dynamicType; |
323 List typesReturned = nativeBehavior.typesReturned; | 324 List typesReturned = nativeBehavior.typesReturned; |
324 if (typesReturned.isEmpty) return types.dynamicType; | 325 if (typesReturned.isEmpty) return types.dynamicType; |
325 TypeInformation returnType; | 326 TypeInformation returnType; |
326 for (var type in typesReturned) { | 327 for (var type in typesReturned) { |
327 TypeInformation mappedType; | 328 TypeInformation mappedType; |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 } | 529 } |
529 if (debug.VERBOSE) { | 530 if (debug.VERBOSE) { |
530 print("traced closure $element as " | 531 print("traced closure $element as " |
531 "${closedWorldRefiner | 532 "${closedWorldRefiner |
532 .getCurrentlyKnownMightBePassedToApply(element)}"); | 533 .getCurrentlyKnownMightBePassedToApply(element)}"); |
533 } | 534 } |
534 }); | 535 }); |
535 } | 536 } |
536 | 537 |
537 if (info is ClosureTypeInformation) { | 538 if (info is ClosureTypeInformation) { |
538 Iterable<MethodElement> elements = [info.closure]; | 539 Iterable<FunctionEntity> elements = [info.closure]; |
539 trace(elements, new ClosureTracerVisitor(elements, info, this)); | 540 trace(elements, new ClosureTracerVisitor(elements, info, this)); |
540 } else if (info is CallSiteTypeInformation) { | 541 } else if (info is CallSiteTypeInformation) { |
541 if (info is StaticCallSiteTypeInformation && | 542 if (info is StaticCallSiteTypeInformation && |
542 info.selector != null && | 543 info.selector != null && |
543 info.selector.isCall) { | 544 info.selector.isCall) { |
544 // This is a constructor call to a class with a call method. So we | 545 // This is a constructor call to a class with a call method. So we |
545 // need to trace the call method here. | 546 // need to trace the call method here. |
546 MethodElement calledElement = info.calledElement; | 547 MethodElement calledElement = info.calledElement; |
547 assert(calledElement.isGenerativeConstructor); | 548 assert(calledElement.isGenerativeConstructor); |
548 ClassElement cls = calledElement.enclosingClass; | 549 ClassElement cls = calledElement.enclosingClass; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 'after ${info.refineCount}'); | 605 'after ${info.refineCount}'); |
605 }); | 606 }); |
606 types.allocatedClosures.forEach((TypeInformation info) { | 607 types.allocatedClosures.forEach((TypeInformation info) { |
607 if (info is ElementTypeInformation) { | 608 if (info is ElementTypeInformation) { |
608 print('${info.getInferredSignature(types)} for ' | 609 print('${info.getInferredSignature(types)} for ' |
609 '${info.debugName}'); | 610 '${info.debugName}'); |
610 } else if (info is ClosureTypeInformation) { | 611 } else if (info is ClosureTypeInformation) { |
611 print('${info.getInferredSignature(types)} for ' | 612 print('${info.getInferredSignature(types)} for ' |
612 '${info.debugName}'); | 613 '${info.debugName}'); |
613 } else if (info is DynamicCallSiteTypeInformation) { | 614 } else if (info is DynamicCallSiteTypeInformation) { |
614 for (MemberElement target in info.targets) { | 615 for (MemberEntity target in info.targets) { |
615 if (target is MethodElement) { | 616 if (target is FunctionEntity) { |
616 print( | 617 print( |
617 '${types.getInferredSignatureOfMethod(target)} for ${target}')
; | 618 '${types.getInferredSignatureOfMethod(target)} for ${target}')
; |
618 } else { | 619 } else { |
619 print( | 620 print( |
620 '${types.getInferredTypeOfMember(target).type} for ${target}')
; | 621 '${types.getInferredTypeOfMember(target).type} for ${target}')
; |
621 } | 622 } |
622 } | 623 } |
623 } else if (info is StaticCallSiteTypeInformation) { | 624 } else if (info is StaticCallSiteTypeInformation) { |
624 ClassElement cls = info.calledElement.enclosingClass; | 625 ClassElement cls = info.calledElement.enclosingClass; |
625 MethodElement callMethod = cls.lookupMember(Identifiers.call); | 626 MethodElement callMethod = cls.lookupMember(Identifiers.call); |
626 print('${types.getInferredSignatureOfMethod(callMethod)} for ${cls}'); | 627 print('${types.getInferredSignatureOfMethod(callMethod)} for ${cls}'); |
627 } else { | 628 } else { |
628 print('${info.type} for some unknown kind of closure'); | 629 print('${info.type} for some unknown kind of closure'); |
629 } | 630 } |
630 }); | 631 }); |
631 analyzedElements.forEach((MemberElement elem) { | 632 analyzedElements.forEach((MemberEntity elem) { |
632 TypeInformation type = types.getInferredTypeOfMember(elem); | 633 TypeInformation type = types.getInferredTypeOfMember(elem); |
633 print('${elem} :: ${type} from ${type.assignments} '); | 634 print('${elem} :: ${type} from ${type.assignments} '); |
634 }); | 635 }); |
635 } | 636 } |
636 dump?.afterAnalysis(); | 637 dump?.afterAnalysis(); |
637 | 638 |
638 reporter.log('Inferred $overallRefineCount types.'); | 639 reporter.log('Inferred $overallRefineCount types.'); |
639 | 640 |
640 processLoopInformation(); | 641 processLoopInformation(); |
641 } | 642 } |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
729 types.allocatedCalls.forEach((dynamic info) { | 730 types.allocatedCalls.forEach((dynamic info) { |
730 if (!info.inLoop) return; | 731 if (!info.inLoop) return; |
731 if (info is StaticCallSiteTypeInformation) { | 732 if (info is StaticCallSiteTypeInformation) { |
732 MemberEntity member = info.calledElement; | 733 MemberEntity member = info.calledElement; |
733 closedWorldRefiner.addFunctionCalledInLoop(member); | 734 closedWorldRefiner.addFunctionCalledInLoop(member); |
734 } else if (info.mask != null && !info.mask.containsAll(closedWorld)) { | 735 } else if (info.mask != null && !info.mask.containsAll(closedWorld)) { |
735 // For instance methods, we only register a selector called in a | 736 // For instance methods, we only register a selector called in a |
736 // loop if it is a typed selector, to avoid marking too many | 737 // loop if it is a typed selector, to avoid marking too many |
737 // methods as being called from within a loop. This cuts down | 738 // methods as being called from within a loop. This cuts down |
738 // on the code bloat. | 739 // on the code bloat. |
739 info.targets.forEach((MemberElement element) { | 740 info.targets.forEach((MemberEntity element) { |
740 closedWorldRefiner.addFunctionCalledInLoop(element); | 741 closedWorldRefiner.addFunctionCalledInLoop(element); |
741 }); | 742 }); |
742 } | 743 } |
743 }); | 744 }); |
744 } | 745 } |
745 | 746 |
746 void refine() { | 747 void refine() { |
747 while (!workQueue.isEmpty) { | 748 while (!workQueue.isEmpty) { |
748 if (compiler.shouldPrintProgress) { | 749 if (compiler.shouldPrintProgress) { |
749 reporter.log('Inferred $overallRefineCount types.'); | 750 reporter.log('Inferred $overallRefineCount types.'); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 info.removeAssignment(type); | 849 info.removeAssignment(type); |
849 } else { | 850 } else { |
850 info.addAssignment(type); | 851 info.addAssignment(type); |
851 } | 852 } |
852 parameterIndex++; | 853 parameterIndex++; |
853 if (addToQueue) workQueue.add(info); | 854 if (addToQueue) workQueue.add(info); |
854 }); | 855 }); |
855 } | 856 } |
856 } | 857 } |
857 | 858 |
858 void setDefaultTypeOfParameter( | 859 void setDefaultTypeOfParameter(Local parameter, TypeInformation type, |
859 covariant ParameterElement parameter, TypeInformation type) { | 860 {bool isInstanceMember}) { |
860 assert(parameter.functionDeclaration.isImplementation); | 861 assert(!(parameter is ParameterElement && !parameter.isImplementation)); |
861 TypeInformation existing = defaultTypeOfParameter[parameter]; | 862 TypeInformation existing = defaultTypeOfParameter[parameter]; |
862 defaultTypeOfParameter[parameter] = type; | 863 defaultTypeOfParameter[parameter] = type; |
863 TypeInformation info = types.getInferredTypeOfParameter(parameter); | 864 TypeInformation info = types.getInferredTypeOfParameter(parameter); |
864 if (existing != null && existing is PlaceholderTypeInformation) { | 865 if (existing != null && existing is PlaceholderTypeInformation) { |
865 // Replace references to [existing] to use [type] instead. | 866 // Replace references to [existing] to use [type] instead. |
866 if (parameter.functionDeclaration.isInstanceMember) { | 867 if (isInstanceMember) { |
867 ParameterAssignments assignments = info.assignments; | 868 ParameterAssignments assignments = info.assignments; |
868 assignments.replace(existing, type); | 869 assignments.replace(existing, type); |
869 } else { | 870 } else { |
870 List<TypeInformation> assignments = info.assignments; | 871 List<TypeInformation> assignments = info.assignments; |
871 for (int i = 0; i < assignments.length; i++) { | 872 for (int i = 0; i < assignments.length; i++) { |
872 if (assignments[i] == existing) { | 873 if (assignments[i] == existing) { |
873 assignments[i] = type; | 874 assignments[i] = type; |
874 } | 875 } |
875 } | 876 } |
876 } | 877 } |
877 // Also forward all users. | 878 // Also forward all users. |
878 type.addUsersOf(existing); | 879 type.addUsersOf(existing); |
879 } else { | 880 } else { |
880 assert(existing == null); | 881 assert(existing == null); |
881 } | 882 } |
882 } | 883 } |
883 | 884 |
884 TypeInformation getDefaultTypeOfParameter(Local parameter) { | 885 TypeInformation getDefaultTypeOfParameter(Local parameter) { |
| 886 assert(!(parameter is ParameterElement && !parameter.isImplementation)); |
885 return defaultTypeOfParameter.putIfAbsent(parameter, () { | 887 return defaultTypeOfParameter.putIfAbsent(parameter, () { |
886 return new PlaceholderTypeInformation(types.currentMember); | 888 return new PlaceholderTypeInformation(types.currentMember); |
887 }); | 889 }); |
888 } | 890 } |
889 | 891 |
890 bool hasAlreadyComputedTypeOfParameterDefault(Local parameter) { | 892 bool hasAlreadyComputedTypeOfParameterDefault(Local parameter) { |
| 893 assert(!(parameter is ParameterElement && !parameter.isImplementation)); |
891 TypeInformation seen = defaultTypeOfParameter[parameter]; | 894 TypeInformation seen = defaultTypeOfParameter[parameter]; |
892 return (seen != null && seen is! PlaceholderTypeInformation); | 895 return (seen != null && seen is! PlaceholderTypeInformation); |
893 } | 896 } |
894 | 897 |
895 TypeInformation typeOfParameter(Local element) { | 898 TypeInformation typeOfParameter(Local element) { |
896 return types.getInferredTypeOfParameter(element); | 899 return types.getInferredTypeOfParameter(element); |
897 } | 900 } |
898 | 901 |
899 TypeInformation typeOfMember(MemberEntity element) { | 902 TypeInformation typeOfMember(MemberEntity element) { |
900 if (element is FunctionEntity) return types.functionType; | 903 if (element is FunctionEntity) return types.functionType; |
(...skipping 14 matching lines...) Expand all Loading... |
915 if (element.name == '==') { | 918 if (element.name == '==') { |
916 // Even if x.== doesn't return a bool, 'x == null' evaluates to 'false'. | 919 // Even if x.== doesn't return a bool, 'x == null' evaluates to 'false'. |
917 info.addAssignment(types.boolType); | 920 info.addAssignment(types.boolType); |
918 } | 921 } |
919 // TODO(ngeoffray): Clean up. We do these checks because | 922 // TODO(ngeoffray): Clean up. We do these checks because |
920 // [SimpleTypesInferrer] deals with two different inferrers. | 923 // [SimpleTypesInferrer] deals with two different inferrers. |
921 if (type == null) return; | 924 if (type == null) return; |
922 if (info.assignments.isEmpty) info.addAssignment(type); | 925 if (info.assignments.isEmpty) info.addAssignment(type); |
923 } | 926 } |
924 | 927 |
925 TypeInformation addReturnTypeForMethod(covariant MethodElement element, | 928 TypeInformation addReturnTypeForMethod( |
926 TypeInformation unused, TypeInformation newType) { | 929 FunctionEntity element, TypeInformation unused, TypeInformation newType) { |
927 TypeInformation type = types.getInferredTypeOfMember(element); | 930 TypeInformation type = types.getInferredTypeOfMember(element); |
928 // TODO(ngeoffray): Clean up. We do this check because | 931 // TODO(ngeoffray): Clean up. We do this check because |
929 // [SimpleTypesInferrer] deals with two different inferrers. | 932 // [SimpleTypesInferrer] deals with two different inferrers. |
930 if (element.isGenerativeConstructor) return type; | 933 if (element is ConstructorEntity && element.isGenerativeConstructor) { |
| 934 return type; |
| 935 } |
931 type.addAssignment(newType); | 936 type.addAssignment(newType); |
932 return type; | 937 return type; |
933 } | 938 } |
934 | 939 |
935 TypeInformation registerCalledMember( | 940 TypeInformation registerCalledMember( |
936 Spannable node, | 941 Spannable node, |
937 Selector selector, | 942 Selector selector, |
938 TypeMask mask, | 943 TypeMask mask, |
939 MemberEntity caller, | 944 MemberEntity caller, |
940 covariant MemberElement callee, | 945 MemberEntity callee, |
941 ArgumentsTypes arguments, | 946 ArgumentsTypes arguments, |
942 SideEffects sideEffects, | 947 SideEffects sideEffects, |
943 bool inLoop) { | 948 bool inLoop) { |
944 CallSiteTypeInformation info = new StaticCallSiteTypeInformation( | 949 CallSiteTypeInformation info = new StaticCallSiteTypeInformation( |
945 types.currentMember, | 950 types.currentMember, |
946 node, | 951 node, |
947 caller, | 952 caller, |
948 callee, | 953 callee, |
949 selector, | 954 selector, |
950 mask, | 955 mask, |
951 arguments, | 956 arguments, |
952 inLoop); | 957 inLoop); |
953 // If this class has a 'call' method then we have essentially created a | 958 // If this class has a 'call' method then we have essentially created a |
954 // closure here. Register it as such so that it is traced. | 959 // closure here. Register it as such so that it is traced. |
955 // Note: we exclude factory constructors because they don't always create an | 960 // Note: we exclude factory constructors because they don't always create an |
956 // instance of the type. They are static methods that delegate to some other | 961 // instance of the type. They are static methods that delegate to some other |
957 // generative constructor to do the actual creation of the object. | 962 // generative constructor to do the actual creation of the object. |
958 if (selector != null && selector.isCall && callee.isGenerativeConstructor) { | 963 if (selector != null && |
| 964 selector.isCall && |
| 965 callee is ConstructorEntity && |
| 966 callee.isGenerativeConstructor) { |
959 ClassElement cls = callee.enclosingClass; | 967 ClassElement cls = callee.enclosingClass; |
960 if (cls.callType != null) { | 968 if (cls.callType != null) { |
961 types.allocatedClosures.add(info); | 969 types.allocatedClosures.add(info); |
962 } | 970 } |
963 } | 971 } |
964 info.addToGraph(this); | 972 info.addToGraph(this); |
965 types.allocatedCalls.add(info); | 973 types.allocatedCalls.add(info); |
966 updateSideEffects(sideEffects, selector, callee); | 974 updateSideEffects(sideEffects, selector, callee); |
967 return info; | 975 return info; |
968 } | 976 } |
969 | 977 |
970 TypeInformation registerCalledSelector( | 978 TypeInformation registerCalledSelector( |
971 ast.Node node, | 979 ast.Node node, |
972 Selector selector, | 980 Selector selector, |
973 TypeMask mask, | 981 TypeMask mask, |
974 TypeInformation receiverType, | 982 TypeInformation receiverType, |
975 MemberEntity caller, | 983 MemberEntity caller, |
976 ArgumentsTypes arguments, | 984 ArgumentsTypes arguments, |
977 SideEffects sideEffects, | 985 SideEffects sideEffects, |
978 bool inLoop, | 986 bool inLoop, |
979 bool isConditional) { | 987 bool isConditional) { |
980 if (selector.isClosureCall) { | 988 if (selector.isClosureCall) { |
981 return registerCalledClosure(node, selector, mask, receiverType, caller, | 989 return registerCalledClosure(node, selector, mask, receiverType, caller, |
982 arguments, sideEffects, inLoop); | 990 arguments, sideEffects, inLoop); |
983 } | 991 } |
984 | 992 |
985 closedWorld.locateMembers(selector, mask).forEach((_callee) { | 993 closedWorld.locateMembers(selector, mask).forEach((callee) { |
986 MemberElement callee = _callee; | |
987 updateSideEffects(sideEffects, selector, callee); | 994 updateSideEffects(sideEffects, selector, callee); |
988 }); | 995 }); |
989 | 996 |
990 CallSiteTypeInformation info = new DynamicCallSiteTypeInformation( | 997 CallSiteTypeInformation info = new DynamicCallSiteTypeInformation( |
991 types.currentMember, | 998 types.currentMember, |
992 node, | 999 node, |
993 caller, | 1000 caller, |
994 selector, | 1001 selector, |
995 mask, | 1002 mask, |
996 receiverType, | 1003 receiverType, |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1242 @override | 1249 @override |
1243 bool checkPhiNode(ast.Node node) { | 1250 bool checkPhiNode(ast.Node node) { |
1244 return true; | 1251 return true; |
1245 } | 1252 } |
1246 | 1253 |
1247 @override | 1254 @override |
1248 bool checkClassEntity(covariant ClassElement cls) { | 1255 bool checkClassEntity(covariant ClassElement cls) { |
1249 return cls.isDeclaration; | 1256 return cls.isDeclaration; |
1250 } | 1257 } |
1251 } | 1258 } |
OLD | NEW |