| 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 26 matching lines...) Expand all Loading... |
| 37 import 'type_system.dart'; | 37 import 'type_system.dart'; |
| 38 | 38 |
| 39 /** | 39 /** |
| 40 * An inferencing engine that computes a call graph of | 40 * An inferencing engine that computes a call graph of |
| 41 * [TypeInformation] nodes by visiting the AST of the application, and | 41 * [TypeInformation] nodes by visiting the AST of the application, and |
| 42 * then does the inferencing on the graph. | 42 * then does the inferencing on the graph. |
| 43 */ | 43 */ |
| 44 class InferrerEngine { | 44 class InferrerEngine { |
| 45 final Map<Element, TypeInformation> defaultTypeOfParameter = | 45 final Map<Element, TypeInformation> defaultTypeOfParameter = |
| 46 new Map<Element, TypeInformation>(); | 46 new Map<Element, TypeInformation>(); |
| 47 final List<CallSiteTypeInformation> allocatedCalls = | |
| 48 <CallSiteTypeInformation>[]; | |
| 49 final WorkQueue workQueue = new WorkQueue(); | 47 final WorkQueue workQueue = new WorkQueue(); |
| 50 final Element mainElement; | 48 final Element mainElement; |
| 51 final Set<Element> analyzedElements = new Set<Element>(); | 49 final Set<Element> analyzedElements = new Set<Element>(); |
| 52 | 50 |
| 53 /// The maximum number of times we allow a node in the graph to | 51 /// The maximum number of times we allow a node in the graph to |
| 54 /// change types. If a node reaches that limit, we give up | 52 /// change types. If a node reaches that limit, we give up |
| 55 /// inferencing on it and give it the dynamic type. | 53 /// inferencing on it and give it the dynamic type. |
| 56 final int MAX_CHANGE_COUNT = 6; | 54 final int MAX_CHANGE_COUNT = 6; |
| 57 | 55 |
| 58 int overallRefineCount = 0; | 56 int overallRefineCount = 0; |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 548 (argument.asNewExpression() != null && !argument.isConst)) { | 546 (argument.asNewExpression() != null && !argument.isConst)) { |
| 549 recordType(element, types.nullType); | 547 recordType(element, types.nullType); |
| 550 } | 548 } |
| 551 } | 549 } |
| 552 } else { | 550 } else { |
| 553 recordReturnType(element, type); | 551 recordReturnType(element, type); |
| 554 } | 552 } |
| 555 } | 553 } |
| 556 | 554 |
| 557 void processLoopInformation() { | 555 void processLoopInformation() { |
| 558 allocatedCalls.forEach((info) { | 556 types.allocatedCalls.forEach((info) { |
| 559 if (!info.inLoop) return; | 557 if (!info.inLoop) return; |
| 560 if (info is StaticCallSiteTypeInformation) { | 558 if (info is StaticCallSiteTypeInformation) { |
| 561 closedWorldRefiner.addFunctionCalledInLoop(info.calledElement); | 559 closedWorldRefiner.addFunctionCalledInLoop(info.calledElement); |
| 562 } else if (info.mask != null && !info.mask.containsAll(closedWorld)) { | 560 } else if (info.mask != null && !info.mask.containsAll(closedWorld)) { |
| 563 // For instance methods, we only register a selector called in a | 561 // For instance methods, we only register a selector called in a |
| 564 // loop if it is a typed selector, to avoid marking too many | 562 // loop if it is a typed selector, to avoid marking too many |
| 565 // methods as being called from within a loop. This cuts down | 563 // methods as being called from within a loop. This cuts down |
| 566 // on the code bloat. | 564 // on the code bloat. |
| 567 info.targets.forEach(closedWorldRefiner.addFunctionCalledInLoop); | 565 info.targets.forEach(closedWorldRefiner.addFunctionCalledInLoop); |
| 568 } | 566 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 597 info.stabilize(this); | 595 info.stabilize(this); |
| 598 } | 596 } |
| 599 } | 597 } |
| 600 } | 598 } |
| 601 } | 599 } |
| 602 | 600 |
| 603 void buildWorkQueue() { | 601 void buildWorkQueue() { |
| 604 workQueue.addAll(types.typeInformations.values); | 602 workQueue.addAll(types.typeInformations.values); |
| 605 workQueue.addAll(types.allocatedTypes); | 603 workQueue.addAll(types.allocatedTypes); |
| 606 workQueue.addAll(types.allocatedClosures); | 604 workQueue.addAll(types.allocatedClosures); |
| 607 workQueue.addAll(allocatedCalls); | 605 workQueue.addAll(types.allocatedCalls); |
| 608 } | 606 } |
| 609 | 607 |
| 610 /** | 608 /** |
| 611 * Update the assignments to parameters in the graph. [remove] tells | 609 * Update the assignments to parameters in the graph. [remove] tells |
| 612 * wheter assignments must be added or removed. If [init] is false, | 610 * wheter assignments must be added or removed. If [init] is false, |
| 613 * parameters are added to the work queue. | 611 * parameters are added to the work queue. |
| 614 */ | 612 */ |
| 615 void updateParameterAssignments(TypeInformation caller, Element callee, | 613 void updateParameterAssignments(TypeInformation caller, Element callee, |
| 616 ArgumentsTypes arguments, Selector selector, TypeMask mask, | 614 ArgumentsTypes arguments, Selector selector, TypeMask mask, |
| 617 {bool remove, bool addToQueue: true}) { | 615 {bool remove, bool addToQueue: true}) { |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 inLoop); | 844 inLoop); |
| 847 // If this class has a 'call' method then we have essentially created a | 845 // If this class has a 'call' method then we have essentially created a |
| 848 // closure here. Register it as such so that it is traced. | 846 // closure here. Register it as such so that it is traced. |
| 849 if (selector != null && selector.isCall && callee.isConstructor) { | 847 if (selector != null && selector.isCall && callee.isConstructor) { |
| 850 ClassElement cls = callee.enclosingClass; | 848 ClassElement cls = callee.enclosingClass; |
| 851 if (cls.callType != null) { | 849 if (cls.callType != null) { |
| 852 types.allocatedClosures.add(info); | 850 types.allocatedClosures.add(info); |
| 853 } | 851 } |
| 854 } | 852 } |
| 855 info.addToGraph(this); | 853 info.addToGraph(this); |
| 856 allocatedCalls.add(info); | 854 types.allocatedCalls.add(info); |
| 857 updateSideEffects(sideEffects, selector, callee); | 855 updateSideEffects(sideEffects, selector, callee); |
| 858 return info; | 856 return info; |
| 859 } | 857 } |
| 860 | 858 |
| 861 /** | 859 /** |
| 862 * Registers that [caller] calls [selector] with [receiverType] as | 860 * Registers that [caller] calls [selector] with [receiverType] as |
| 863 * receiver, and [arguments]. | 861 * receiver, and [arguments]. |
| 864 * | 862 * |
| 865 * [sideEffects] will be updated to incorporate the potential | 863 * [sideEffects] will be updated to incorporate the potential |
| 866 * callees' side effects. | 864 * callees' side effects. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 889 types.currentMember, | 887 types.currentMember, |
| 890 node, | 888 node, |
| 891 caller, | 889 caller, |
| 892 selector, | 890 selector, |
| 893 mask, | 891 mask, |
| 894 receiverType, | 892 receiverType, |
| 895 arguments, | 893 arguments, |
| 896 inLoop); | 894 inLoop); |
| 897 | 895 |
| 898 info.addToGraph(this); | 896 info.addToGraph(this); |
| 899 allocatedCalls.add(info); | 897 types.allocatedCalls.add(info); |
| 900 return info; | 898 return info; |
| 901 } | 899 } |
| 902 | 900 |
| 903 /** | 901 /** |
| 904 * Registers a call to await with an expression of type [argumentType] as | 902 * Registers a call to await with an expression of type [argumentType] as |
| 905 * argument. | 903 * argument. |
| 906 */ | 904 */ |
| 907 TypeInformation registerAwait(ast.Node node, TypeInformation argument) { | 905 TypeInformation registerAwait(ast.Node node, TypeInformation argument) { |
| 908 AwaitTypeInformation info = | 906 AwaitTypeInformation info = |
| 909 new AwaitTypeInformation(types.currentMember, node); | 907 new AwaitTypeInformation(types.currentMember, node); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 934 CallSiteTypeInformation info = new ClosureCallSiteTypeInformation( | 932 CallSiteTypeInformation info = new ClosureCallSiteTypeInformation( |
| 935 types.currentMember, | 933 types.currentMember, |
| 936 node, | 934 node, |
| 937 caller, | 935 caller, |
| 938 selector, | 936 selector, |
| 939 mask, | 937 mask, |
| 940 closure, | 938 closure, |
| 941 arguments, | 939 arguments, |
| 942 inLoop); | 940 inLoop); |
| 943 info.addToGraph(this); | 941 info.addToGraph(this); |
| 944 allocatedCalls.add(info); | 942 types.allocatedCalls.add(info); |
| 945 return info; | 943 return info; |
| 946 } | 944 } |
| 947 | 945 |
| 948 // Sorts the resolved elements by size. We do this for this inferrer | 946 // Sorts the resolved elements by size. We do this for this inferrer |
| 949 // to get the same results for [ListTracer] compared to the | 947 // to get the same results for [ListTracer] compared to the |
| 950 // [SimpleTypesInferrer]. | 948 // [SimpleTypesInferrer]. |
| 951 Iterable<ResolvedAst> sortResolvedAsts() { | 949 Iterable<ResolvedAst> sortResolvedAsts() { |
| 952 int max = 0; | 950 int max = 0; |
| 953 Map<int, Setlet<ResolvedAst>> methodSizes = <int, Setlet<ResolvedAst>>{}; | 951 Map<int, Setlet<ResolvedAst>> methodSizes = <int, Setlet<ResolvedAst>>{}; |
| 954 compiler.enqueuer.resolution.processedEntities | 952 compiler.enqueuer.resolution.processedEntities |
| (...skipping 27 matching lines...) Expand all Loading... |
| 982 for (int i = 0; i <= max; i++) { | 980 for (int i = 0; i <= max; i++) { |
| 983 Setlet<ResolvedAst> set = methodSizes[i]; | 981 Setlet<ResolvedAst> set = methodSizes[i]; |
| 984 if (set != null) result.addAll(set); | 982 if (set != null) result.addAll(set); |
| 985 } | 983 } |
| 986 return result; | 984 return result; |
| 987 } | 985 } |
| 988 | 986 |
| 989 void clear() { | 987 void clear() { |
| 990 void cleanup(TypeInformation info) => info.cleanup(); | 988 void cleanup(TypeInformation info) => info.cleanup(); |
| 991 | 989 |
| 992 allocatedCalls.forEach(cleanup); | 990 types.allocatedCalls.forEach(cleanup); |
| 993 allocatedCalls.clear(); | 991 types.allocatedCalls.clear(); |
| 994 | 992 |
| 995 defaultTypeOfParameter.clear(); | 993 defaultTypeOfParameter.clear(); |
| 996 | 994 |
| 997 types.typeInformations.values.forEach(cleanup); | 995 types.typeInformations.values.forEach(cleanup); |
| 998 | 996 |
| 999 types.allocatedTypes.forEach(cleanup); | 997 types.allocatedTypes.forEach(cleanup); |
| 1000 types.allocatedTypes.clear(); | 998 types.allocatedTypes.clear(); |
| 1001 | 999 |
| 1002 types.concreteTypes.clear(); | 1000 types.concreteTypes.clear(); |
| 1003 | 1001 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 /** | 1053 /** |
| 1056 * Records that the captured variable [local] is read. | 1054 * Records that the captured variable [local] is read. |
| 1057 */ | 1055 */ |
| 1058 void recordCapturedLocalRead(Local local) {} | 1056 void recordCapturedLocalRead(Local local) {} |
| 1059 | 1057 |
| 1060 /** | 1058 /** |
| 1061 * Records that the variable [local] is being updated. | 1059 * Records that the variable [local] is being updated. |
| 1062 */ | 1060 */ |
| 1063 void recordLocalUpdate(Local local, TypeInformation type) {} | 1061 void recordLocalUpdate(Local local, TypeInformation type) {} |
| 1064 } | 1062 } |
| OLD | NEW |