Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(416)

Side by Side Diff: pkg/compiler/lib/src/inferrer/inferrer_engine.dart

Issue 2982713002: Extract interface of InferrerEngine and move implemation to InferrerEngineImpl (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 19 matching lines...) Expand all
30 import 'locals_handler.dart'; 30 import 'locals_handler.dart';
31 import 'list_tracer.dart'; 31 import 'list_tracer.dart';
32 import 'map_tracer.dart'; 32 import 'map_tracer.dart';
33 import 'builder.dart'; 33 import 'builder.dart';
34 import 'builder_kernel.dart'; 34 import 'builder_kernel.dart';
35 import 'type_graph_dump.dart'; 35 import 'type_graph_dump.dart';
36 import 'type_graph_inferrer.dart'; 36 import 'type_graph_inferrer.dart';
37 import 'type_graph_nodes.dart'; 37 import 'type_graph_nodes.dart';
38 import 'type_system.dart'; 38 import 'type_system.dart';
39 39
40 /** 40 /// An inferencing engine that computes a call graph of [TypeInformation] nodes
41 * An inferencing engine that computes a call graph of 41 /// by visiting the AST of the application, and then does the inferencing on the
42 * [TypeInformation] nodes by visiting the AST of the application, and 42 /// graph.
43 * then does the inferencing on the graph. 43 abstract class InferrerEngine {
44 */ 44 /// A set of selector names that [List] implements, that we know return their
45 class InferrerEngine { 45 /// element type.
46 final Set<Selector> returnsListElementTypeSet =
47 new Set<Selector>.from(<Selector>[
48 new Selector.getter(const PublicName('first')),
49 new Selector.getter(const PublicName('last')),
50 new Selector.getter(const PublicName('single')),
51 new Selector.call(const PublicName('singleWhere'), CallStructure.ONE_ARG),
52 new Selector.call(const PublicName('elementAt'), CallStructure.ONE_ARG),
53 new Selector.index(),
54 new Selector.call(const PublicName('removeAt'), CallStructure.ONE_ARG),
55 new Selector.call(const PublicName('removeLast'), CallStructure.NO_ARGS)
56 ]);
57
58 Compiler get compiler;
59 ClosedWorld get closedWorld;
60 ClosedWorldRefiner get closedWorldRefiner;
61 JavaScriptBackend get backend => compiler.backend;
62 OptimizerHintsForTests get optimizerHints => backend.optimizerHints;
63 DiagnosticReporter get reporter => compiler.reporter;
64 CommonMasks get commonMasks => closedWorld.commonMasks;
65 CommonElements get commonElements => closedWorld.commonElements;
66
67 TypeSystem<ast.Node> get types;
68 Map<ast.Node, TypeInformation> get concreteTypes;
69
70 /// Parallel structure for concreteTypes.
71 // TODO(efortuna): Remove concreteTypes and/or parameterize InferrerEngine by
72 // ir.Node or ast.Node type. Then remove this in favor of `concreteTypes`.
73 Map<ir.Node, TypeInformation> get concreteKernelTypes;
74
75 FunctionEntity get mainElement;
76
77 void runOverAllElements();
78
79 void analyze(ResolvedAst resolvedAst, ArgumentsTypes arguments);
80 void analyzeListAndEnqueue(ListTypeInformation info);
81 void analyzeMapAndEnqueue(MapTypeInformation info);
82
83 /// Notifies to the inferrer that [analyzedElement] can have return type
84 /// [newType]. [currentType] is the type the [ElementGraphBuilder] currently
85 /// found.
86 ///
87 /// Returns the new type for [analyzedElement].
88 TypeInformation addReturnTypeForMethod(
89 MethodElement element, TypeInformation unused, TypeInformation newType);
90
91 /// Applies [f] to all elements in the universe that match [selector] and
92 /// [mask]. If [f] returns false, aborts the iteration.
93 void forEachElementMatching(
94 Selector selector, TypeMask mask, bool f(Element element));
95
96 /// Returns the [TypeInformation] node for the default value of a parameter.
97 /// If this is queried before it is set by [setDefaultTypeOfParameter], a
98 /// [PlaceholderTypeInformation] is returned, which will later be replaced
99 /// by the actual node when [setDefaultTypeOfParameter] is called.
100 ///
101 /// Invariant: After graph construction, no [PlaceholderTypeInformation] nodes
102 /// should be present and a default type for each parameter should exist.
103 TypeInformation getDefaultTypeOfParameter(ParameterElement parameter);
104
105 /// This helper breaks abstractions but is currently required to work around
106 /// the wrong modeling of default values of optional parameters of
107 /// synthetic constructors.
108 ///
109 /// TODO(johnniwinther): Remove once default values of synthetic parameters
110 /// are fixed.
111 bool hasAlreadyComputedTypeOfParameterDefault(ParameterElement parameter);
112
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
115 /// a [PlaceholderTypeInformation], which will be replaced. All its uses are
116 /// updated.
117 void setDefaultTypeOfParameter(
118 ParameterElement parameter, TypeInformation type);
119
120 Iterable<MemberEntity> getCallersOf(MemberElement element);
121
122 // TODO(johnniwinther): Make this private again.
123 GlobalTypeInferenceElementData dataOfMember(MemberElement element);
124
125 GlobalTypeInferenceElementData lookupDataOfMember(MemberElement element);
126
127 bool checkIfExposesThis(ConstructorElement element);
128
129 void recordExposesThis(ConstructorElement element, bool exposesThis);
130
131 /// Records that the return type [element] is of type [type].
132 void recordReturnType(MethodElement element, TypeInformation type);
133
134 /// Records that [element] is of type [type].
135 // TODO(johnniwinther): Merge [recordTypeOfFinalField] and
136 // [recordTypeOfNonFinalField] with this?
137 void recordTypeOfField(FieldElement element, TypeInformation type);
138
139 /// Records that [node] sets final field [element] to be of type [type].
140 void recordTypeOfFinalField(FieldElement element, TypeInformation type);
141
142 /// Records that [node] sets non-final field [element] to be of type [type].
143 void recordTypeOfNonFinalField(FieldElement element, TypeInformation type);
144
145 /// Records that the captured variable [local] is read.
146 // TODO(johnniwinther): Remove this.
147 void recordCapturedLocalRead(Local local) {}
148
149 /// Records that the variable [local] is being updated.
150 // TODO(johnniwinther): Remove this.
151 void recordLocalUpdate(Local local, TypeInformation type) {}
152
153 /// Registers a call to await with an expression of type [argumentType] as
154 /// argument.
155 TypeInformation registerAwait(ast.Node node, TypeInformation argument);
156
157 /// Registers a call to yield with an expression of type [argumentType] as
158 /// argument.
159 TypeInformation registerYield(ast.Node node, TypeInformation argument);
160
161 /// Registers that [caller] calls [closure] with [arguments].
162 ///
163 /// [sideEffects] will be updated to incorporate the potential callees' side
164 /// effects.
165 ///
166 /// [inLoop] tells whether the call happens in a loop.
167 TypeInformation registerCalledClosure(
168 ast.Node node,
169 Selector selector,
170 TypeMask mask,
171 TypeInformation closure,
172 MemberElement caller,
173 ArgumentsTypes arguments,
174 SideEffects sideEffects,
175 bool inLoop);
176
177 /// Registers that [caller] calls [callee] at location [node], with
178 /// [selector], and [arguments]. Note that [selector] is null for forwarding
179 /// constructors.
180 ///
181 /// [sideEffects] will be updated to incorporate [callee]'s side effects.
182 ///
183 /// [inLoop] tells whether the call happens in a loop.
184 TypeInformation registerCalledMember(
185 Spannable node,
186 Selector selector,
187 TypeMask mask,
188 MemberElement caller,
189 MemberElement callee,
190 ArgumentsTypes arguments,
191 SideEffects sideEffects,
192 bool inLoop);
193
194 /// Registers that [caller] calls [selector] with [receiverType] as receiver,
195 /// and [arguments].
196 ///
197 /// [sideEffects] will be updated to incorporate the potential callees' side
198 /// effects.
199 ///
200 /// [inLoop] tells whether the call happens in a loop.
201 TypeInformation registerCalledSelector(
202 ast.Node node,
203 Selector selector,
204 TypeMask mask,
205 TypeInformation receiverType,
206 MemberElement caller,
207 ArgumentsTypes arguments,
208 SideEffects sideEffects,
209 bool inLoop,
210 bool isConditional);
211
212 /// Update the assignments to parameters in the graph. [remove] tells whether
213 /// assignments must be added or removed. If [init] is false, parameters are
214 /// added to the work queue.
215 void updateParameterAssignments(TypeInformation caller, MemberEntity callee,
216 ArgumentsTypes arguments, Selector selector, TypeMask mask,
217 {bool remove, bool addToQueue: true});
218
219 void updateSelectorInMember(
220 MemberElement owner, Spannable node, Selector selector, TypeMask mask);
221
222 /// Returns the return type of [element].
223 TypeInformation returnTypeOfMember(MemberElement element);
224
225 /// Returns the type of [element] when being called with [selector].
226 TypeInformation typeOfMemberWithSelector(
227 MemberElement element, Selector selector);
228
229 /// Returns the type of [element].
230 TypeInformation typeOfMember(MemberElement element);
231
232 /// Returns the type of [element].
233 TypeInformation typeOfParameter(ParameterElement element);
234
235 /// Returns the type for [nativeBehavior]. See documentation on
236 /// [native.NativeBehavior].
237 TypeInformation typeOfNativeBehavior(native.NativeBehavior nativeBehavior);
238
239 bool returnsListElementType(Selector selector, TypeMask mask);
240
241 bool returnsMapValueType(Selector selector, TypeMask mask);
242
243 void clear();
244 }
245
246 class InferrerEngineImpl extends InferrerEngine {
46 final Map<ParameterElement, TypeInformation> defaultTypeOfParameter = 247 final Map<ParameterElement, TypeInformation> defaultTypeOfParameter =
47 new Map<ParameterElement, TypeInformation>(); 248 new Map<ParameterElement, TypeInformation>();
48 final WorkQueue workQueue = new WorkQueue(); 249 final WorkQueue workQueue = new WorkQueue();
49 final FunctionEntity mainElement; 250 final FunctionEntity mainElement;
50 final Set<MemberElement> analyzedElements = new Set<MemberElement>(); 251 final Set<MemberElement> analyzedElements = new Set<MemberElement>();
51 252
52 /// The maximum number of times we allow a node in the graph to 253 /// The maximum number of times we allow a node in the graph to
53 /// change types. If a node reaches that limit, we give up 254 /// change types. If a node reaches that limit, we give up
54 /// inferencing on it and give it the dynamic type. 255 /// inferencing on it and give it the dynamic type.
55 final int MAX_CHANGE_COUNT = 6; 256 final int MAX_CHANGE_COUNT = 6;
56 257
57 int overallRefineCount = 0; 258 int overallRefineCount = 0;
58 int addedInGraph = 0; 259 int addedInGraph = 0;
59 260
60 final Compiler compiler; 261 final Compiler compiler;
61 262
62 /// The [ClosedWorld] on which inference reasoning is based. 263 /// The [ClosedWorld] on which inference reasoning is based.
63 final ClosedWorld closedWorld; 264 final ClosedWorld closedWorld;
64 265
65 final ClosedWorldRefiner closedWorldRefiner; 266 final ClosedWorldRefiner closedWorldRefiner;
66 final TypeSystem<ast.Node> types; 267 final TypeSystem<ast.Node> types;
67 final Map<ast.Node, TypeInformation> concreteTypes = 268 final Map<ast.Node, TypeInformation> concreteTypes =
68 new Map<ast.Node, TypeInformation>(); 269 new Map<ast.Node, TypeInformation>();
69 270
70 /// Parallel structure for concreteTypes.
71 // TODO(efortuna): Remove concreteTypes and/or parameterize InferrerEngine by
72 // ir.Node or ast.Node type. Then remove this in favor of `concreteTypes`.
73 final Map<ir.Node, TypeInformation> concreteKernelTypes = 271 final Map<ir.Node, TypeInformation> concreteKernelTypes =
74 new Map<ir.Node, TypeInformation>(); 272 new Map<ir.Node, TypeInformation>();
75 final Set<ConstructorElement> generativeConstructorsExposingThis = 273 final Set<ConstructorElement> generativeConstructorsExposingThis =
76 new Set<ConstructorElement>(); 274 new Set<ConstructorElement>();
77 275
78 /// Data computed internally within elements, like the type-mask of a send a 276 /// Data computed internally within elements, like the type-mask of a send a
79 /// list allocation, or a for-in loop. 277 /// list allocation, or a for-in loop.
80 final Map<MemberElement, GlobalTypeInferenceElementData> _memberData = 278 final Map<MemberElement, GlobalTypeInferenceElementData> _memberData =
81 new Map<MemberElement, GlobalTypeInferenceElementData>(); 279 new Map<MemberElement, GlobalTypeInferenceElementData>();
82 280
83 InferrerEngine(this.compiler, ClosedWorld closedWorld, 281 InferrerEngineImpl(this.compiler, ClosedWorld closedWorld,
84 this.closedWorldRefiner, this.mainElement) 282 this.closedWorldRefiner, this.mainElement)
85 : this.types = new TypeSystem<ast.Node>( 283 : this.types = new TypeSystem<ast.Node>(
86 closedWorld, const TypeSystemStrategyImpl()), 284 closedWorld, const TypeSystemStrategyImpl()),
87 this.closedWorld = closedWorld; 285 this.closedWorld = closedWorld;
88 286
89 CommonElements get commonElements => closedWorld.commonElements;
90
91 /**
92 * Applies [f] to all elements in the universe that match
93 * [selector] and [mask]. If [f] returns false, aborts the iteration.
94 */
95 void forEachElementMatching( 287 void forEachElementMatching(
96 Selector selector, TypeMask mask, bool f(Element element)) { 288 Selector selector, TypeMask mask, bool f(Element element)) {
97 Iterable<MemberEntity> elements = closedWorld.locateMembers(selector, mask); 289 Iterable<MemberEntity> elements = closedWorld.locateMembers(selector, mask);
98 for (MemberElement e in elements) { 290 for (MemberElement e in elements) {
99 if (!f(e.implementation)) return; 291 if (!f(e.implementation)) return;
100 } 292 }
101 } 293 }
102 294
103 // TODO(johnniwinther): Make this private again. 295 // TODO(johnniwinther): Make this private again.
104 GlobalTypeInferenceElementData dataOfMember(MemberElement element) => 296 GlobalTypeInferenceElementData dataOfMember(MemberElement element) =>
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 } 328 }
137 } else if (callee.isGetter && !selector.isGetter) { 329 } else if (callee.isGetter && !selector.isGetter) {
138 sideEffects.setAllSideEffects(); 330 sideEffects.setAllSideEffects();
139 sideEffects.setDependsOnSomething(); 331 sideEffects.setDependsOnSomething();
140 } else { 332 } else {
141 MethodElement method = callee.declaration; 333 MethodElement method = callee.declaration;
142 sideEffects.add(closedWorldRefiner.getCurrentlyKnownSideEffects(method)); 334 sideEffects.add(closedWorldRefiner.getCurrentlyKnownSideEffects(method));
143 } 335 }
144 } 336 }
145 337
146 /**
147 * Returns the type for [nativeBehavior]. See documentation on
148 * [native.NativeBehavior].
149 */
150 TypeInformation typeOfNativeBehavior(native.NativeBehavior nativeBehavior) { 338 TypeInformation typeOfNativeBehavior(native.NativeBehavior nativeBehavior) {
151 if (nativeBehavior == null) return types.dynamicType; 339 if (nativeBehavior == null) return types.dynamicType;
152 List typesReturned = nativeBehavior.typesReturned; 340 List typesReturned = nativeBehavior.typesReturned;
153 if (typesReturned.isEmpty) return types.dynamicType; 341 if (typesReturned.isEmpty) return types.dynamicType;
154 TypeInformation returnType; 342 TypeInformation returnType;
155 for (var type in typesReturned) { 343 for (var type in typesReturned) {
156 TypeInformation mappedType; 344 TypeInformation mappedType;
157 if (type == native.SpecialType.JsObject) { 345 if (type == native.SpecialType.JsObject) {
158 mappedType = types.nonNullExact(commonElements.objectClass); 346 mappedType = types.nonNullExact(commonElements.objectClass);
159 } else if (type == commonElements.stringType) { 347 } else if (type == commonElements.stringType) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 return generativeConstructorsExposingThis.contains(element); 406 return generativeConstructorsExposingThis.contains(element);
219 } 407 }
220 408
221 void recordExposesThis(ConstructorElement element, bool exposesThis) { 409 void recordExposesThis(ConstructorElement element, bool exposesThis) {
222 element = element.implementation; 410 element = element.implementation;
223 if (exposesThis) { 411 if (exposesThis) {
224 generativeConstructorsExposingThis.add(element); 412 generativeConstructorsExposingThis.add(element);
225 } 413 }
226 } 414 }
227 415
228 JavaScriptBackend get backend => compiler.backend;
229 OptimizerHintsForTests get optimizerHints => backend.optimizerHints;
230 DiagnosticReporter get reporter => compiler.reporter;
231 CommonMasks get commonMasks => closedWorld.commonMasks;
232
233 /**
234 * A set of selector names that [List] implements, that we know return
235 * their element type.
236 */
237 final Set<Selector> returnsListElementTypeSet =
238 new Set<Selector>.from(<Selector>[
239 new Selector.getter(const PublicName('first')),
240 new Selector.getter(const PublicName('last')),
241 new Selector.getter(const PublicName('single')),
242 new Selector.call(const PublicName('singleWhere'), CallStructure.ONE_ARG),
243 new Selector.call(const PublicName('elementAt'), CallStructure.ONE_ARG),
244 new Selector.index(),
245 new Selector.call(const PublicName('removeAt'), CallStructure.ONE_ARG),
246 new Selector.call(const PublicName('removeLast'), CallStructure.NO_ARGS)
247 ]);
248
249 bool returnsListElementType(Selector selector, TypeMask mask) { 416 bool returnsListElementType(Selector selector, TypeMask mask) {
250 return mask != null && 417 return mask != null &&
251 mask.isContainer && 418 mask.isContainer &&
252 returnsListElementTypeSet.contains(selector); 419 returnsListElementTypeSet.contains(selector);
253 } 420 }
254 421
255 bool returnsMapValueType(Selector selector, TypeMask mask) { 422 bool returnsMapValueType(Selector selector, TypeMask mask) {
256 return mask != null && mask.isMap && selector.isIndex; 423 return mask != null && mask.isMap && selector.isIndex;
257 } 424 }
258 425
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 } 791 }
625 } 792 }
626 793
627 void buildWorkQueue() { 794 void buildWorkQueue() {
628 workQueue.addAll(types.orderedTypeInformations); 795 workQueue.addAll(types.orderedTypeInformations);
629 workQueue.addAll(types.allocatedTypes); 796 workQueue.addAll(types.allocatedTypes);
630 workQueue.addAll(types.allocatedClosures); 797 workQueue.addAll(types.allocatedClosures);
631 workQueue.addAll(types.allocatedCalls); 798 workQueue.addAll(types.allocatedCalls);
632 } 799 }
633 800
634 /**
635 * Update the assignments to parameters in the graph. [remove] tells
636 * wheter assignments must be added or removed. If [init] is false,
637 * parameters are added to the work queue.
638 */
639 void updateParameterAssignments(TypeInformation caller, MemberEntity callee, 801 void updateParameterAssignments(TypeInformation caller, MemberEntity callee,
640 ArgumentsTypes arguments, Selector selector, TypeMask mask, 802 ArgumentsTypes arguments, Selector selector, TypeMask mask,
641 {bool remove, bool addToQueue: true}) { 803 {bool remove, bool addToQueue: true}) {
642 if (callee.name == Identifiers.noSuchMethod_) return; 804 if (callee.name == Identifiers.noSuchMethod_) return;
643 if (callee.isField) { 805 if (callee.isField) {
644 if (selector.isSetter) { 806 if (selector.isSetter) {
645 ElementTypeInformation info = types.getInferredTypeOfMember(callee); 807 ElementTypeInformation info = types.getInferredTypeOfMember(callee);
646 if (remove) { 808 if (remove) {
647 info.removeAssignment(arguments.positional[0]); 809 info.removeAssignment(arguments.positional[0]);
648 } else { 810 } else {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
703 info.removeAssignment(type); 865 info.removeAssignment(type);
704 } else { 866 } else {
705 info.addAssignment(type); 867 info.addAssignment(type);
706 } 868 }
707 parameterIndex++; 869 parameterIndex++;
708 if (addToQueue) workQueue.add(info); 870 if (addToQueue) workQueue.add(info);
709 }); 871 });
710 } 872 }
711 } 873 }
712 874
713 /**
714 * Sets the type of a parameter's default value to [type]. If the global
715 * mapping in [defaultTypeOfParameter] already contains a type, it must be
716 * a [PlaceholderTypeInformation], which will be replaced. All its uses are
717 * updated.
718 */
719 void setDefaultTypeOfParameter( 875 void setDefaultTypeOfParameter(
720 ParameterElement parameter, TypeInformation type) { 876 ParameterElement parameter, TypeInformation type) {
721 assert(parameter.functionDeclaration.isImplementation); 877 assert(parameter.functionDeclaration.isImplementation);
722 TypeInformation existing = defaultTypeOfParameter[parameter]; 878 TypeInformation existing = defaultTypeOfParameter[parameter];
723 defaultTypeOfParameter[parameter] = type; 879 defaultTypeOfParameter[parameter] = type;
724 TypeInformation info = types.getInferredTypeOfParameter(parameter); 880 TypeInformation info = types.getInferredTypeOfParameter(parameter);
725 if (existing != null && existing is PlaceholderTypeInformation) { 881 if (existing != null && existing is PlaceholderTypeInformation) {
726 // Replace references to [existing] to use [type] instead. 882 // Replace references to [existing] to use [type] instead.
727 if (parameter.functionDeclaration.isInstanceMember) { 883 if (parameter.functionDeclaration.isInstanceMember) {
728 ParameterAssignments assignments = info.assignments; 884 ParameterAssignments assignments = info.assignments;
729 assignments.replace(existing, type); 885 assignments.replace(existing, type);
730 } else { 886 } else {
731 List<TypeInformation> assignments = info.assignments; 887 List<TypeInformation> assignments = info.assignments;
732 for (int i = 0; i < assignments.length; i++) { 888 for (int i = 0; i < assignments.length; i++) {
733 if (assignments[i] == existing) { 889 if (assignments[i] == existing) {
734 assignments[i] = type; 890 assignments[i] = type;
735 } 891 }
736 } 892 }
737 } 893 }
738 // Also forward all users. 894 // Also forward all users.
739 type.addUsersOf(existing); 895 type.addUsersOf(existing);
740 } else { 896 } else {
741 assert(existing == null); 897 assert(existing == null);
742 } 898 }
743 } 899 }
744 900
745 /**
746 * Returns the [TypeInformation] node for the default value of a parameter.
747 * If this is queried before it is set by [setDefaultTypeOfParameter], a
748 * [PlaceholderTypeInformation] is returned, which will later be replaced
749 * by the actual node when [setDefaultTypeOfParameter] is called.
750 *
751 * Invariant: After graph construction, no [PlaceholderTypeInformation] nodes
752 * should be present and a default type for each parameter should
753 * exist.
754 */
755 TypeInformation getDefaultTypeOfParameter(ParameterElement parameter) { 901 TypeInformation getDefaultTypeOfParameter(ParameterElement parameter) {
756 return defaultTypeOfParameter.putIfAbsent(parameter, () { 902 return defaultTypeOfParameter.putIfAbsent(parameter, () {
757 return new PlaceholderTypeInformation(types.currentMember); 903 return new PlaceholderTypeInformation(types.currentMember);
758 }); 904 });
759 } 905 }
760 906
761 /**
762 * This helper breaks abstractions but is currently required to work around
763 * the wrong modeling of default values of optional parameters of
764 * synthetic constructors.
765 *
766 * TODO(johnniwinther): Remove once default values of synthetic parameters
767 * are fixed.
768 */
769 bool hasAlreadyComputedTypeOfParameterDefault(ParameterElement parameter) { 907 bool hasAlreadyComputedTypeOfParameterDefault(ParameterElement parameter) {
770 TypeInformation seen = defaultTypeOfParameter[parameter]; 908 TypeInformation seen = defaultTypeOfParameter[parameter];
771 return (seen != null && seen is! PlaceholderTypeInformation); 909 return (seen != null && seen is! PlaceholderTypeInformation);
772 } 910 }
773 911
774 /**
775 * Returns the type of [element].
776 */
777 TypeInformation typeOfParameter(ParameterElement element) { 912 TypeInformation typeOfParameter(ParameterElement element) {
778 return types.getInferredTypeOfParameter(element); 913 return types.getInferredTypeOfParameter(element);
779 } 914 }
780 915
781 /**
782 * Returns the type of [element].
783 */
784 TypeInformation typeOfMember(MemberElement element) { 916 TypeInformation typeOfMember(MemberElement element) {
785 if (element is MethodElement) return types.functionType; 917 if (element is MethodElement) return types.functionType;
786 return types.getInferredTypeOfMember(element); 918 return types.getInferredTypeOfMember(element);
787 } 919 }
788 920
789 /**
790 * Returns the return type of [element].
791 */
792 TypeInformation returnTypeOfMember(MemberElement element) { 921 TypeInformation returnTypeOfMember(MemberElement element) {
793 if (element is! MethodElement) return types.dynamicType; 922 if (element is! MethodElement) return types.dynamicType;
794 return types.getInferredTypeOfMember(element); 923 return types.getInferredTypeOfMember(element);
795 } 924 }
796 925
797 /**
798 * Records that [node] sets final field [element] to be of type [type].
799 *
800 * [nodeHolder] is the element holder of [node].
801 */
802 void recordTypeOfFinalField(FieldElement element, TypeInformation type) { 926 void recordTypeOfFinalField(FieldElement element, TypeInformation type) {
803 types.getInferredTypeOfMember(element).addAssignment(type); 927 types.getInferredTypeOfMember(element).addAssignment(type);
804 } 928 }
805 929
806 /**
807 * Records that [node] sets non-final field [element] to be of type
808 * [type].
809 */
810 void recordTypeOfNonFinalField(FieldElement element, TypeInformation type) { 930 void recordTypeOfNonFinalField(FieldElement element, TypeInformation type) {
811 types.getInferredTypeOfMember(element).addAssignment(type); 931 types.getInferredTypeOfMember(element).addAssignment(type);
812 } 932 }
813 933
814 /**
815 * Records that [element] is of type [type].
816 */
817 // TODO(johnniwinther): Merge [recordTypeOfFinalField] and
818 // [recordTypeOfNonFinalField] with this?
819 void recordTypeOfField(FieldElement element, TypeInformation type) { 934 void recordTypeOfField(FieldElement element, TypeInformation type) {
820 types.getInferredTypeOfMember(element).addAssignment(type); 935 types.getInferredTypeOfMember(element).addAssignment(type);
821 } 936 }
822 937
823 /**
824 * Records that the return type [element] is of type [type].
825 */
826 void recordReturnType(MethodElement element, TypeInformation type) { 938 void recordReturnType(MethodElement element, TypeInformation type) {
827 TypeInformation info = types.getInferredTypeOfMember(element); 939 TypeInformation info = types.getInferredTypeOfMember(element);
828 if (element.name == '==') { 940 if (element.name == '==') {
829 // Even if x.== doesn't return a bool, 'x == null' evaluates to 'false'. 941 // Even if x.== doesn't return a bool, 'x == null' evaluates to 'false'.
830 info.addAssignment(types.boolType); 942 info.addAssignment(types.boolType);
831 } 943 }
832 // TODO(ngeoffray): Clean up. We do these checks because 944 // TODO(ngeoffray): Clean up. We do these checks because
833 // [SimpleTypesInferrer] deals with two different inferrers. 945 // [SimpleTypesInferrer] deals with two different inferrers.
834 if (type == null) return; 946 if (type == null) return;
835 if (info.assignments.isEmpty) info.addAssignment(type); 947 if (info.assignments.isEmpty) info.addAssignment(type);
836 } 948 }
837 949
838 /**
839 * Notifies to the inferrer that [analyzedElement] can have return
840 * type [newType]. [currentType] is the type the [ElementGraphBuilder]
841 * currently found.
842 *
843 * Returns the new type for [analyzedElement].
844 */
845 TypeInformation addReturnTypeForMethod( 950 TypeInformation addReturnTypeForMethod(
846 MethodElement element, TypeInformation unused, TypeInformation newType) { 951 MethodElement element, TypeInformation unused, TypeInformation newType) {
847 TypeInformation type = types.getInferredTypeOfMember(element); 952 TypeInformation type = types.getInferredTypeOfMember(element);
848 // TODO(ngeoffray): Clean up. We do this check because 953 // TODO(ngeoffray): Clean up. We do this check because
849 // [SimpleTypesInferrer] deals with two different inferrers. 954 // [SimpleTypesInferrer] deals with two different inferrers.
850 if (element.isGenerativeConstructor) return type; 955 if (element.isGenerativeConstructor) return type;
851 type.addAssignment(newType); 956 type.addAssignment(newType);
852 return type; 957 return type;
853 } 958 }
854 959
855 /**
856 * Registers that [caller] calls [callee] at location [node], with
857 * [selector], and [arguments]. Note that [selector] is null for
858 * forwarding constructors.
859 *
860 * [sideEffects] will be updated to incorporate [callee]'s side
861 * effects.
862 *
863 * [inLoop] tells whether the call happens in a loop.
864 */
865 TypeInformation registerCalledMember( 960 TypeInformation registerCalledMember(
866 Spannable node, 961 Spannable node,
867 Selector selector, 962 Selector selector,
868 TypeMask mask, 963 TypeMask mask,
869 MemberElement caller, 964 MemberElement caller,
870 MemberElement callee, 965 MemberElement callee,
871 ArgumentsTypes arguments, 966 ArgumentsTypes arguments,
872 SideEffects sideEffects, 967 SideEffects sideEffects,
873 bool inLoop) { 968 bool inLoop) {
874 CallSiteTypeInformation info = new StaticCallSiteTypeInformation( 969 CallSiteTypeInformation info = new StaticCallSiteTypeInformation(
(...skipping 15 matching lines...) Expand all
890 if (cls.callType != null) { 985 if (cls.callType != null) {
891 types.allocatedClosures.add(info); 986 types.allocatedClosures.add(info);
892 } 987 }
893 } 988 }
894 info.addToGraph(this); 989 info.addToGraph(this);
895 types.allocatedCalls.add(info); 990 types.allocatedCalls.add(info);
896 updateSideEffects(sideEffects, selector, callee); 991 updateSideEffects(sideEffects, selector, callee);
897 return info; 992 return info;
898 } 993 }
899 994
900 /**
901 * Registers that [caller] calls [selector] with [receiverType] as
902 * receiver, and [arguments].
903 *
904 * [sideEffects] will be updated to incorporate the potential
905 * callees' side effects.
906 *
907 * [inLoop] tells whether the call happens in a loop.
908 */
909 TypeInformation registerCalledSelector( 995 TypeInformation registerCalledSelector(
910 ast.Node node, 996 ast.Node node,
911 Selector selector, 997 Selector selector,
912 TypeMask mask, 998 TypeMask mask,
913 TypeInformation receiverType, 999 TypeInformation receiverType,
914 MemberElement caller, 1000 MemberElement caller,
915 ArgumentsTypes arguments, 1001 ArgumentsTypes arguments,
916 SideEffects sideEffects, 1002 SideEffects sideEffects,
917 bool inLoop, 1003 bool inLoop,
918 bool isConditional) { 1004 bool isConditional) {
(...skipping 16 matching lines...) Expand all
935 receiverType, 1021 receiverType,
936 arguments, 1022 arguments,
937 inLoop, 1023 inLoop,
938 isConditional); 1024 isConditional);
939 1025
940 info.addToGraph(this); 1026 info.addToGraph(this);
941 types.allocatedCalls.add(info); 1027 types.allocatedCalls.add(info);
942 return info; 1028 return info;
943 } 1029 }
944 1030
945 /**
946 * Registers a call to await with an expression of type [argumentType] as
947 * argument.
948 */
949 TypeInformation registerAwait(ast.Node node, TypeInformation argument) { 1031 TypeInformation registerAwait(ast.Node node, TypeInformation argument) {
950 AwaitTypeInformation info = 1032 AwaitTypeInformation info =
951 new AwaitTypeInformation<ast.Node>(types.currentMember, node); 1033 new AwaitTypeInformation<ast.Node>(types.currentMember, node);
952 info.addAssignment(argument); 1034 info.addAssignment(argument);
953 types.allocatedTypes.add(info); 1035 types.allocatedTypes.add(info);
954 return info; 1036 return info;
955 } 1037 }
956 1038
957 /**
958 * Registers a call to yield with an expression of type [argumentType] as
959 * argument.
960 */
961 TypeInformation registerYield(ast.Node node, TypeInformation argument) { 1039 TypeInformation registerYield(ast.Node node, TypeInformation argument) {
962 YieldTypeInformation info = 1040 YieldTypeInformation info =
963 new YieldTypeInformation<ast.Node>(types.currentMember, node); 1041 new YieldTypeInformation<ast.Node>(types.currentMember, node);
964 info.addAssignment(argument); 1042 info.addAssignment(argument);
965 types.allocatedTypes.add(info); 1043 types.allocatedTypes.add(info);
966 return info; 1044 return info;
967 } 1045 }
968 1046
969 /**
970 * Registers that [caller] calls [closure] with [arguments].
971 *
972 * [sideEffects] will be updated to incorporate the potential
973 * callees' side effects.
974 *
975 * [inLoop] tells whether the call happens in a loop.
976 */
977 TypeInformation registerCalledClosure( 1047 TypeInformation registerCalledClosure(
978 ast.Node node, 1048 ast.Node node,
979 Selector selector, 1049 Selector selector,
980 TypeMask mask, 1050 TypeMask mask,
981 TypeInformation closure, 1051 TypeInformation closure,
982 MemberElement caller, 1052 MemberElement caller,
983 ArgumentsTypes arguments, 1053 ArgumentsTypes arguments,
984 SideEffects sideEffects, 1054 SideEffects sideEffects,
985 bool inLoop) { 1055 bool inLoop) {
986 sideEffects.setDependsOnSomething(); 1056 sideEffects.setDependsOnSomething();
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 1137
1068 Iterable<MemberEntity> getCallersOf(MemberElement element) { 1138 Iterable<MemberEntity> getCallersOf(MemberElement element) {
1069 if (compiler.disableTypeInference) { 1139 if (compiler.disableTypeInference) {
1070 throw new UnsupportedError( 1140 throw new UnsupportedError(
1071 "Cannot query the type inferrer when type inference is disabled."); 1141 "Cannot query the type inferrer when type inference is disabled.");
1072 } 1142 }
1073 MemberTypeInformation info = types.getInferredTypeOfMember(element); 1143 MemberTypeInformation info = types.getInferredTypeOfMember(element);
1074 return info.callers; 1144 return info.callers;
1075 } 1145 }
1076 1146
1077 /**
1078 * Returns the type of [element] when being called with [selector].
1079 */
1080 TypeInformation typeOfMemberWithSelector( 1147 TypeInformation typeOfMemberWithSelector(
1081 MemberElement element, Selector selector) { 1148 MemberElement element, Selector selector) {
1082 return _typeOfElementWithSelector(element, selector);
1083 }
1084
1085 /**
1086 * Returns the type of [element] when being called with [selector].
1087 */
1088 TypeInformation _typeOfElementWithSelector(
1089 MemberElement element, Selector selector) {
1090 if (element.name == Identifiers.noSuchMethod_ && 1149 if (element.name == Identifiers.noSuchMethod_ &&
1091 selector.name != element.name) { 1150 selector.name != element.name) {
1092 // An invocation can resolve to a [noSuchMethod], in which case 1151 // An invocation can resolve to a [noSuchMethod], in which case
1093 // we get the return type of [noSuchMethod]. 1152 // we get the return type of [noSuchMethod].
1094 return returnTypeOfMember(element); 1153 return returnTypeOfMember(element);
1095 } else if (selector.isGetter) { 1154 } else if (selector.isGetter) {
1096 if (element.isFunction) { 1155 if (element.isFunction) {
1097 // [functionType] is null if the inferrer did not run. 1156 // [functionType] is null if the inferrer did not run.
1098 return types.functionType == null 1157 return types.functionType == null
1099 ? types.dynamicType 1158 ? types.dynamicType
1100 : types.functionType; 1159 : types.functionType;
1101 } else if (element.isField) { 1160 } else if (element.isField) {
1102 return typeOfMember(element); 1161 return typeOfMember(element);
1103 } else if (Elements.isUnresolved(element)) { 1162 } else if (Elements.isUnresolved(element)) {
1104 return types.dynamicType; 1163 return types.dynamicType;
1105 } else { 1164 } else {
1106 assert(element.isGetter); 1165 assert(element.isGetter);
1107 return returnTypeOfMember(element); 1166 return returnTypeOfMember(element);
1108 } 1167 }
1109 } else if (element.isGetter || element.isField) { 1168 } else if (element.isGetter || element.isField) {
1110 assert(selector.isCall || selector.isSetter); 1169 assert(selector.isCall || selector.isSetter);
1111 return types.dynamicType; 1170 return types.dynamicType;
1112 } else { 1171 } else {
1113 return returnTypeOfMember(element); 1172 return returnTypeOfMember(element);
1114 } 1173 }
1115 } 1174 }
1116
1117 /**
1118 * Records that the captured variable [local] is read.
1119 */
1120 void recordCapturedLocalRead(Local local) {}
1121
1122 /**
1123 * Records that the variable [local] is being updated.
1124 */
1125 void recordLocalUpdate(Local local, TypeInformation type) {}
1126 } 1175 }
1127 1176
1128 class TypeSystemStrategyImpl implements TypeSystemStrategy<ast.Node> { 1177 class TypeSystemStrategyImpl implements TypeSystemStrategy<ast.Node> {
1129 const TypeSystemStrategyImpl(); 1178 const TypeSystemStrategyImpl();
1130 1179
1131 @override 1180 @override
1132 MemberTypeInformation createMemberTypeInformation( 1181 MemberTypeInformation createMemberTypeInformation(
1133 covariant MemberElement member) { 1182 covariant MemberElement member) {
1134 assert(member.isDeclaration, failedAt(member)); 1183 assert(member.isDeclaration, failedAt(member));
1135 if (member.isField) { 1184 if (member.isField) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1218 @override 1267 @override
1219 bool checkPhiNode(ast.Node node) { 1268 bool checkPhiNode(ast.Node node) {
1220 return true; 1269 return true;
1221 } 1270 }
1222 1271
1223 @override 1272 @override
1224 bool checkClassEntity(covariant ClassElement cls) { 1273 bool checkClassEntity(covariant ClassElement cls) {
1225 return cls.isDeclaration; 1274 return cls.isDeclaration;
1226 } 1275 }
1227 } 1276 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698