OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library simple_types_inferrer; | 5 library simple_types_inferrer; |
6 | 6 |
7 import '../closure.dart' show | 7 import '../closure.dart' show ClosureClassMap, ClosureScope; |
8 ClosureClassMap, | |
9 ClosureScope; | |
10 import '../common.dart'; | 8 import '../common.dart'; |
11 import '../common/names.dart' show | 9 import '../common/names.dart' show Selectors; |
12 Selectors; | 10 import '../compiler.dart' show Compiler; |
13 import '../compiler.dart' show | 11 import '../constants/values.dart' show ConstantValue, IntConstantValue; |
14 Compiler; | 12 import '../core_types.dart' show CoreClasses, CoreTypes; |
15 import '../constants/values.dart' show | 13 import '../cps_ir/cps_ir_nodes.dart' as cps_ir show Node; |
16 ConstantValue, | 14 import '../dart_types.dart' |
17 IntConstantValue; | 15 show DartType, FunctionType, InterfaceType, TypeKind; |
18 import '../core_types.dart' show | |
19 CoreClasses, | |
20 CoreTypes; | |
21 import '../cps_ir/cps_ir_nodes.dart' as cps_ir show | |
22 Node; | |
23 import '../dart_types.dart' show | |
24 DartType, | |
25 FunctionType, | |
26 InterfaceType, | |
27 TypeKind; | |
28 import '../elements/elements.dart'; | 16 import '../elements/elements.dart'; |
29 import '../js_backend/js_backend.dart' as js; | 17 import '../js_backend/js_backend.dart' as js; |
30 import '../native/native.dart' as native; | 18 import '../native/native.dart' as native; |
31 import '../resolution/tree_elements.dart' show | 19 import '../resolution/tree_elements.dart' show TreeElements; |
32 TreeElements; | |
33 import '../resolution/operators.dart' as op; | 20 import '../resolution/operators.dart' as op; |
34 import '../tree/tree.dart' as ast; | 21 import '../tree/tree.dart' as ast; |
35 import '../types/types.dart' show | 22 import '../types/types.dart' |
36 TypesInferrer, | 23 show |
37 FlatTypeMask, | 24 TypesInferrer, |
38 TypeMask, | 25 FlatTypeMask, |
39 ContainerTypeMask, | 26 TypeMask, |
40 ValueTypeMask; | 27 ContainerTypeMask, |
41 import '../util/util.dart' show | 28 ValueTypeMask; |
42 Link, | 29 import '../util/util.dart' show Link, Setlet; |
43 Setlet; | 30 import '../universe/call_structure.dart' show CallStructure; |
44 import '../universe/call_structure.dart' show | 31 import '../universe/selector.dart' show Selector; |
45 CallStructure; | 32 import '../universe/side_effects.dart' show SideEffects; |
46 import '../universe/selector.dart' show | |
47 Selector; | |
48 import '../universe/side_effects.dart' show | |
49 SideEffects; | |
50 import '../world.dart' show ClassWorld; | 33 import '../world.dart' show ClassWorld; |
51 | 34 |
52 import 'inferrer_visitor.dart'; | 35 import 'inferrer_visitor.dart'; |
53 | 36 |
54 /** | 37 /** |
55 * Common super class used by [SimpleTypeInferrerVisitor] to propagate | 38 * Common super class used by [SimpleTypeInferrerVisitor] to propagate |
56 * type information about visited nodes, as well as to request type | 39 * type information about visited nodes, as well as to request type |
57 * information of elements. | 40 * information of elements. |
58 */ | 41 */ |
59 abstract class InferrerEngine<T, V extends TypeSystem> | 42 abstract class InferrerEngine<T, V extends TypeSystem> |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 /** | 78 /** |
96 * Returns the return type of [element]. | 79 * Returns the return type of [element]. |
97 */ | 80 */ |
98 T returnTypeOfElement(Element element); | 81 T returnTypeOfElement(Element element); |
99 | 82 |
100 /** | 83 /** |
101 * Records that [node] sets final field [element] to be of type [type]. | 84 * Records that [node] sets final field [element] to be of type [type]. |
102 * | 85 * |
103 * [nodeHolder] is the element holder of [node]. | 86 * [nodeHolder] is the element holder of [node]. |
104 */ | 87 */ |
105 void recordTypeOfFinalField(ast.Node node, | 88 void recordTypeOfFinalField( |
106 Element nodeHolder, | 89 ast.Node node, Element nodeHolder, Element field, T type); |
107 Element field, | |
108 T type); | |
109 | 90 |
110 /** | 91 /** |
111 * Records that [node] sets non-final field [element] to be of type | 92 * Records that [node] sets non-final field [element] to be of type |
112 * [type]. | 93 * [type]. |
113 */ | 94 */ |
114 void recordTypeOfNonFinalField(Spannable node, Element field, T type); | 95 void recordTypeOfNonFinalField(Spannable node, Element field, T type); |
115 | 96 |
116 /** | 97 /** |
117 * Records that [element] is of type [type]. | 98 * Records that [element] is of type [type]. |
118 */ | 99 */ |
119 void recordType(Element element, T type); | 100 void recordType(Element element, T type); |
120 | 101 |
121 /** | 102 /** |
122 * Records that the return type [element] is of type [type]. | 103 * Records that the return type [element] is of type [type]. |
123 */ | 104 */ |
124 void recordReturnType(Element element, T type); | 105 void recordReturnType(Element element, T type); |
125 | 106 |
126 /** | 107 /** |
127 * Registers that [caller] calls [callee] at location [node], with | 108 * Registers that [caller] calls [callee] at location [node], with |
128 * [selector], and [arguments]. Note that [selector] is null for | 109 * [selector], and [arguments]. Note that [selector] is null for |
129 * forwarding constructors. | 110 * forwarding constructors. |
130 * | 111 * |
131 * [sideEffects] will be updated to incorporate [callee]'s side | 112 * [sideEffects] will be updated to incorporate [callee]'s side |
132 * effects. | 113 * effects. |
133 * | 114 * |
134 * [inLoop] tells whether the call happens in a loop. | 115 * [inLoop] tells whether the call happens in a loop. |
135 */ | 116 */ |
136 T registerCalledElement(Spannable node, | 117 T registerCalledElement( |
137 Selector selector, | 118 Spannable node, |
138 TypeMask mask, | 119 Selector selector, |
139 Element caller, | 120 TypeMask mask, |
140 Element callee, | 121 Element caller, |
141 ArgumentsTypes<T> arguments, | 122 Element callee, |
142 SideEffects sideEffects, | 123 ArgumentsTypes<T> arguments, |
143 bool inLoop); | 124 SideEffects sideEffects, |
| 125 bool inLoop); |
144 | 126 |
145 /** | 127 /** |
146 * Registers that [caller] calls [selector] with [receiverType] as | 128 * Registers that [caller] calls [selector] with [receiverType] as |
147 * receiver, and [arguments]. | 129 * receiver, and [arguments]. |
148 * | 130 * |
149 * [sideEffects] will be updated to incorporate the potential | 131 * [sideEffects] will be updated to incorporate the potential |
150 * callees' side effects. | 132 * callees' side effects. |
151 * | 133 * |
152 * [inLoop] tells whether the call happens in a loop. | 134 * [inLoop] tells whether the call happens in a loop. |
153 */ | 135 */ |
154 T registerCalledSelector(ast.Node node, | 136 T registerCalledSelector( |
155 Selector selector, | 137 ast.Node node, |
156 TypeMask mask, | 138 Selector selector, |
157 T receiverType, | 139 TypeMask mask, |
158 Element caller, | 140 T receiverType, |
159 ArgumentsTypes<T> arguments, | 141 Element caller, |
160 SideEffects sideEffects, | 142 ArgumentsTypes<T> arguments, |
161 bool inLoop); | 143 SideEffects sideEffects, |
| 144 bool inLoop); |
162 | 145 |
163 /** | 146 /** |
164 * Registers that [caller] calls [closure] with [arguments]. | 147 * Registers that [caller] calls [closure] with [arguments]. |
165 * | 148 * |
166 * [sideEffects] will be updated to incorporate the potential | 149 * [sideEffects] will be updated to incorporate the potential |
167 * callees' side effects. | 150 * callees' side effects. |
168 * | 151 * |
169 * [inLoop] tells whether the call happens in a loop. | 152 * [inLoop] tells whether the call happens in a loop. |
170 */ | 153 */ |
171 T registerCalledClosure(ast.Node node, | 154 T registerCalledClosure( |
172 Selector selector, | 155 ast.Node node, |
173 TypeMask mask, | 156 Selector selector, |
174 T closure, | 157 TypeMask mask, |
175 Element caller, | 158 T closure, |
176 ArgumentsTypes<T> arguments, | 159 Element caller, |
177 SideEffects sideEffects, | 160 ArgumentsTypes<T> arguments, |
178 bool inLoop); | 161 SideEffects sideEffects, |
| 162 bool inLoop); |
179 | 163 |
180 /** | 164 /** |
181 * Registers a call to await with an expression of type [argumentType] as | 165 * Registers a call to await with an expression of type [argumentType] as |
182 * argument. | 166 * argument. |
183 */ | 167 */ |
184 T registerAwait(ast.Node node, T argumentType); | 168 T registerAwait(ast.Node node, T argumentType); |
185 | 169 |
186 /** | 170 /** |
187 * Notifies to the inferrer that [analyzedElement] can have return | 171 * Notifies to the inferrer that [analyzedElement] can have return |
188 * type [newType]. [currentType] is the type the [InferrerVisitor] | 172 * type [newType]. [currentType] is the type the [InferrerVisitor] |
189 * currently found. | 173 * currently found. |
190 * | 174 * |
191 * Returns the new type for [analyzedElement]. | 175 * Returns the new type for [analyzedElement]. |
192 */ | 176 */ |
193 T addReturnTypeFor(Element analyzedElement, T currentType, T newType); | 177 T addReturnTypeFor(Element analyzedElement, T currentType, T newType); |
194 | 178 |
195 /** | 179 /** |
196 * Applies [f] to all elements in the universe that match | 180 * Applies [f] to all elements in the universe that match |
197 * [selector] and [mask]. If [f] returns false, aborts the iteration. | 181 * [selector] and [mask]. If [f] returns false, aborts the iteration. |
198 */ | 182 */ |
199 void forEachElementMatching(Selector selector, | 183 void forEachElementMatching( |
200 TypeMask mask, | 184 Selector selector, TypeMask mask, bool f(Element element)) { |
201 bool f(Element element)) { | |
202 Iterable<Element> elements = | 185 Iterable<Element> elements = |
203 compiler.world.allFunctions.filter(selector, mask); | 186 compiler.world.allFunctions.filter(selector, mask); |
204 for (Element e in elements) { | 187 for (Element e in elements) { |
205 if (!f(e.implementation)) return; | 188 if (!f(e.implementation)) return; |
206 } | 189 } |
207 } | 190 } |
208 | 191 |
209 /** | 192 /** |
210 * Update [sideEffects] with the side effects of [callee] being | 193 * Update [sideEffects] with the side effects of [callee] being |
211 * called with [selector]. | 194 * called with [selector]. |
212 */ | 195 */ |
213 void updateSideEffects(SideEffects sideEffects, | 196 void updateSideEffects( |
214 Selector selector, | 197 SideEffects sideEffects, Selector selector, Element callee) { |
215 Element callee) { | |
216 if (callee.isField) { | 198 if (callee.isField) { |
217 if (callee.isInstanceMember) { | 199 if (callee.isInstanceMember) { |
218 if (selector.isSetter) { | 200 if (selector.isSetter) { |
219 sideEffects.setChangesInstanceProperty(); | 201 sideEffects.setChangesInstanceProperty(); |
220 } else if (selector.isGetter) { | 202 } else if (selector.isGetter) { |
221 sideEffects.setDependsOnInstancePropertyStore(); | 203 sideEffects.setDependsOnInstancePropertyStore(); |
222 } else { | 204 } else { |
223 sideEffects.setAllSideEffects(); | 205 sideEffects.setAllSideEffects(); |
224 sideEffects.setDependsOnSomething(); | 206 sideEffects.setDependsOnSomething(); |
225 } | 207 } |
(...skipping 25 matching lines...) Expand all Loading... |
251 if (typesReturned.isEmpty) return types.dynamicType; | 233 if (typesReturned.isEmpty) return types.dynamicType; |
252 T returnType; | 234 T returnType; |
253 for (var type in typesReturned) { | 235 for (var type in typesReturned) { |
254 T mappedType; | 236 T mappedType; |
255 if (type == native.SpecialType.JsObject) { | 237 if (type == native.SpecialType.JsObject) { |
256 mappedType = types.nonNullExact(coreClasses.objectClass); | 238 mappedType = types.nonNullExact(coreClasses.objectClass); |
257 } else if (type == coreTypes.stringType) { | 239 } else if (type == coreTypes.stringType) { |
258 mappedType = types.stringType; | 240 mappedType = types.stringType; |
259 } else if (type == coreTypes.intType) { | 241 } else if (type == coreTypes.intType) { |
260 mappedType = types.intType; | 242 mappedType = types.intType; |
261 } else if (type == coreTypes.numType || | 243 } else if (type == coreTypes.numType || type == coreTypes.doubleType) { |
262 type == coreTypes.doubleType) { | |
263 // Note: the backend double class is specifically for non-integer | 244 // Note: the backend double class is specifically for non-integer |
264 // doubles, and a native behavior returning 'double' does not guarantee | 245 // doubles, and a native behavior returning 'double' does not guarantee |
265 // a non-integer return type, so we return the number type for those. | 246 // a non-integer return type, so we return the number type for those. |
266 mappedType = types.numType; | 247 mappedType = types.numType; |
267 } else if (type == coreTypes.boolType) { | 248 } else if (type == coreTypes.boolType) { |
268 mappedType = types.boolType; | 249 mappedType = types.boolType; |
269 } else if (type == coreTypes.nullType) { | 250 } else if (type == coreTypes.nullType) { |
270 mappedType = types.nullType; | 251 mappedType = types.nullType; |
271 } else if (type.isVoid) { | 252 } else if (type.isVoid) { |
272 mappedType = types.nullType; | 253 mappedType = types.nullType; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 elements.setCurrentTypeMask(node, mask); | 291 elements.setCurrentTypeMask(node, mask); |
311 } else { | 292 } else { |
312 assert(selector == Selectors.moveNext); | 293 assert(selector == Selectors.moveNext); |
313 elements.setMoveNextTypeMask(node, mask); | 294 elements.setMoveNextTypeMask(node, mask); |
314 } | 295 } |
315 } | 296 } |
316 } | 297 } |
317 | 298 |
318 bool isNativeElement(Element element) { | 299 bool isNativeElement(Element element) { |
319 if (compiler.backend.isNative(element)) return true; | 300 if (compiler.backend.isNative(element)) return true; |
320 return element.isClassMember | 301 return element.isClassMember && |
321 && compiler.backend.isNative(element.enclosingClass) | 302 compiler.backend.isNative(element.enclosingClass) && |
322 && element.isField; | 303 element.isField; |
323 } | 304 } |
324 | 305 |
325 void analyze(Element element, ArgumentsTypes arguments); | 306 void analyze(Element element, ArgumentsTypes arguments); |
326 | 307 |
327 bool checkIfExposesThis(Element element) { | 308 bool checkIfExposesThis(Element element) { |
328 element = element.implementation; | 309 element = element.implementation; |
329 return generativeConstructorsExposingThis.contains(element); | 310 return generativeConstructorsExposingThis.contains(element); |
330 } | 311 } |
331 | 312 |
332 void recordExposesThis(Element element, bool exposesThis) { | 313 void recordExposesThis(Element element, bool exposesThis) { |
(...skipping 17 matching lines...) Expand all Loading... |
350 extends InferrerVisitor<T, InferrerEngine<T, TypeSystem<T>>> { | 331 extends InferrerVisitor<T, InferrerEngine<T, TypeSystem<T>>> { |
351 T returnType; | 332 T returnType; |
352 bool visitingInitializers = false; | 333 bool visitingInitializers = false; |
353 bool isConstructorRedirect = false; | 334 bool isConstructorRedirect = false; |
354 bool seenSuperConstructorCall = false; | 335 bool seenSuperConstructorCall = false; |
355 SideEffects sideEffects = new SideEffects.empty(); | 336 SideEffects sideEffects = new SideEffects.empty(); |
356 final Element outermostElement; | 337 final Element outermostElement; |
357 final InferrerEngine<T, TypeSystem<T>> inferrer; | 338 final InferrerEngine<T, TypeSystem<T>> inferrer; |
358 final Setlet<Entity> capturedVariables = new Setlet<Entity>(); | 339 final Setlet<Entity> capturedVariables = new Setlet<Entity>(); |
359 | 340 |
360 SimpleTypeInferrerVisitor.internal(analyzedElement, | 341 SimpleTypeInferrerVisitor.internal( |
361 this.outermostElement, | 342 analyzedElement, this.outermostElement, inferrer, compiler, locals) |
362 inferrer, | 343 : super(analyzedElement, inferrer, inferrer.types, compiler, locals), |
363 compiler, | 344 this.inferrer = inferrer { |
364 locals) | |
365 : super(analyzedElement, inferrer, inferrer.types, compiler, locals), | |
366 this.inferrer = inferrer { | |
367 assert(outermostElement != null); | 345 assert(outermostElement != null); |
368 } | 346 } |
369 | 347 |
370 SimpleTypeInferrerVisitor(Element element, | 348 SimpleTypeInferrerVisitor(Element element, Compiler compiler, |
371 Compiler compiler, | 349 InferrerEngine<T, TypeSystem<T>> inferrer, [LocalsHandler<T> handler]) |
372 InferrerEngine<T, TypeSystem<T>> inferrer, | 350 : this.internal( |
373 [LocalsHandler<T> handler]) | 351 element, |
374 : this.internal(element, | 352 element.outermostEnclosingMemberOrTopLevel.implementation, |
375 element.outermostEnclosingMemberOrTopLevel.implementation, | 353 inferrer, |
376 inferrer, compiler, handler); | 354 compiler, |
| 355 handler); |
377 | 356 |
378 void analyzeSuperConstructorCall(Element target, ArgumentsTypes arguments) { | 357 void analyzeSuperConstructorCall(Element target, ArgumentsTypes arguments) { |
379 inferrer.analyze(target, arguments); | 358 inferrer.analyze(target, arguments); |
380 isThisExposed = isThisExposed || inferrer.checkIfExposesThis(target); | 359 isThisExposed = isThisExposed || inferrer.checkIfExposesThis(target); |
381 } | 360 } |
382 | 361 |
383 T run() { | 362 T run() { |
384 var node = analyzedElement.node; | 363 var node = analyzedElement.node; |
385 ast.Expression initializer; | 364 ast.Expression initializer; |
386 if (analyzedElement.isField) { | 365 if (analyzedElement.isField) { |
387 VariableElement fieldElement = analyzedElement; | 366 VariableElement fieldElement = analyzedElement; |
388 initializer = fieldElement.initializer; | 367 initializer = fieldElement.initializer; |
389 if (initializer == null) { | 368 if (initializer == null) { |
390 // Eagerly bailout, because computing the closure data only | 369 // Eagerly bailout, because computing the closure data only |
391 // works for functions and field assignments. | 370 // works for functions and field assignments. |
392 return types.nullType; | 371 return types.nullType; |
393 } | 372 } |
394 } | 373 } |
395 // Update the locals that are boxed in [locals]. These locals will | 374 // Update the locals that are boxed in [locals]. These locals will |
396 // be handled specially, in that we are computing their LUB at | 375 // be handled specially, in that we are computing their LUB at |
397 // each update, and reading them yields the type that was found in a | 376 // each update, and reading them yields the type that was found in a |
398 // previous analysis of [outermostElement]. | 377 // previous analysis of [outermostElement]. |
399 ClosureClassMap closureData = | 378 ClosureClassMap closureData = compiler.closureToClassMapper |
400 compiler.closureToClassMapper.computeClosureToClassMapping( | 379 .computeClosureToClassMapping(analyzedElement, node, elements); |
401 analyzedElement, node, elements); | |
402 closureData.forEachCapturedVariable((variable, field) { | 380 closureData.forEachCapturedVariable((variable, field) { |
403 locals.setCaptured(variable, field); | 381 locals.setCaptured(variable, field); |
404 }); | 382 }); |
405 closureData.forEachBoxedVariable((variable, field) { | 383 closureData.forEachBoxedVariable((variable, field) { |
406 locals.setCapturedAndBoxed(variable, field); | 384 locals.setCapturedAndBoxed(variable, field); |
407 }); | 385 }); |
408 if (analyzedElement.isField) { | 386 if (analyzedElement.isField) { |
409 return visit(initializer); | 387 return visit(initializer); |
410 } | 388 } |
411 | 389 |
(...skipping 26 matching lines...) Expand all Loading... |
438 return types.dynamicType; | 416 return types.dynamicType; |
439 } | 417 } |
440 | 418 |
441 if (analyzedElement.isGenerativeConstructor) { | 419 if (analyzedElement.isGenerativeConstructor) { |
442 isThisExposed = false; | 420 isThisExposed = false; |
443 signature.forEachParameter((ParameterElement element) { | 421 signature.forEachParameter((ParameterElement element) { |
444 T parameterType = inferrer.typeOfElement(element); | 422 T parameterType = inferrer.typeOfElement(element); |
445 if (element.isInitializingFormal) { | 423 if (element.isInitializingFormal) { |
446 InitializingFormalElement initializingFormal = element; | 424 InitializingFormalElement initializingFormal = element; |
447 if (initializingFormal.fieldElement.isFinal) { | 425 if (initializingFormal.fieldElement.isFinal) { |
448 inferrer.recordTypeOfFinalField( | 426 inferrer.recordTypeOfFinalField(node, analyzedElement, |
449 node, | 427 initializingFormal.fieldElement, parameterType); |
450 analyzedElement, | |
451 initializingFormal.fieldElement, | |
452 parameterType); | |
453 } else { | 428 } else { |
454 locals.updateField(initializingFormal.fieldElement, parameterType); | 429 locals.updateField(initializingFormal.fieldElement, parameterType); |
455 inferrer.recordTypeOfNonFinalField( | 430 inferrer.recordTypeOfNonFinalField(initializingFormal.node, |
456 initializingFormal.node, | 431 initializingFormal.fieldElement, parameterType); |
457 initializingFormal.fieldElement, | |
458 parameterType); | |
459 } | 432 } |
460 } | 433 } |
461 locals.update(element, parameterType, node); | 434 locals.update(element, parameterType, node); |
462 }); | 435 }); |
463 ClassElement cls = analyzedElement.enclosingClass; | 436 ClassElement cls = analyzedElement.enclosingClass; |
464 Spannable spannable = node; | 437 Spannable spannable = node; |
465 if (analyzedElement.isSynthesized) { | 438 if (analyzedElement.isSynthesized) { |
466 spannable = analyzedElement; | 439 spannable = analyzedElement; |
467 ConstructorElement constructor = analyzedElement; | 440 ConstructorElement constructor = analyzedElement; |
468 synthesizeForwardingCall(spannable, constructor.definingConstructor); | 441 synthesizeForwardingCall(spannable, constructor.definingConstructor); |
469 } else { | 442 } else { |
470 visitingInitializers = true; | 443 visitingInitializers = true; |
471 if (node.initializers != null) { | 444 if (node.initializers != null) { |
472 for (ast.Node initializer in node.initializers) { | 445 for (ast.Node initializer in node.initializers) { |
473 ast.SendSet fieldInitializer = initializer.asSendSet(); | 446 ast.SendSet fieldInitializer = initializer.asSendSet(); |
474 if (fieldInitializer != null) { | 447 if (fieldInitializer != null) { |
475 handleSendSet(fieldInitializer); | 448 handleSendSet(fieldInitializer); |
476 } else { | 449 } else { |
477 Element element = elements[initializer]; | 450 Element element = elements[initializer]; |
478 handleConstructorSend(initializer, element); | 451 handleConstructorSend(initializer, element); |
479 } | 452 } |
480 } | 453 } |
481 } | 454 } |
482 visitingInitializers = false; | 455 visitingInitializers = false; |
483 // For a generative constructor like: `Foo();`, we synthesize | 456 // For a generative constructor like: `Foo();`, we synthesize |
484 // a call to the default super constructor (the one that takes | 457 // a call to the default super constructor (the one that takes |
485 // no argument). Resolution ensures that such a constructor | 458 // no argument). Resolution ensures that such a constructor |
486 // exists. | 459 // exists. |
487 if (!isConstructorRedirect | 460 if (!isConstructorRedirect && |
488 && !seenSuperConstructorCall | 461 !seenSuperConstructorCall && |
489 && !cls.isObject) { | 462 !cls.isObject) { |
490 FunctionElement target = cls.superclass.lookupDefaultConstructor(); | 463 FunctionElement target = cls.superclass.lookupDefaultConstructor(); |
491 ArgumentsTypes arguments = new ArgumentsTypes([], {}); | 464 ArgumentsTypes arguments = new ArgumentsTypes([], {}); |
492 analyzeSuperConstructorCall(target, arguments); | 465 analyzeSuperConstructorCall(target, arguments); |
493 inferrer.registerCalledElement(node, | 466 inferrer.registerCalledElement(node, null, null, outermostElement, |
494 null, | 467 target.implementation, arguments, sideEffects, inLoop); |
495 null, | |
496 outermostElement, | |
497 target.implementation, | |
498 arguments, | |
499 sideEffects, | |
500 inLoop); | |
501 } | 468 } |
502 visit(node.body); | 469 visit(node.body); |
503 inferrer.recordExposesThis(analyzedElement, isThisExposed); | 470 inferrer.recordExposesThis(analyzedElement, isThisExposed); |
504 } | 471 } |
505 if (!isConstructorRedirect) { | 472 if (!isConstructorRedirect) { |
506 // Iterate over all instance fields, and give a null type to | 473 // Iterate over all instance fields, and give a null type to |
507 // fields that we haven't initialized for sure. | 474 // fields that we haven't initialized for sure. |
508 cls.forEachInstanceField((_, FieldElement field) { | 475 cls.forEachInstanceField((_, FieldElement field) { |
509 if (field.isFinal) return; | 476 if (field.isFinal) return; |
510 T type = locals.fieldScope.readField(field); | 477 T type = locals.fieldScope.readField(field); |
511 if (type == null && field.initializer == null) { | 478 if (type == null && field.initializer == null) { |
512 inferrer.recordTypeOfNonFinalField( | 479 inferrer.recordTypeOfNonFinalField( |
513 spannable, field, types.nullType); | 480 spannable, field, types.nullType); |
514 } | 481 } |
515 }); | 482 }); |
516 } | 483 } |
517 if (analyzedElement.isGenerativeConstructor && cls.isAbstract) { | 484 if (analyzedElement.isGenerativeConstructor && cls.isAbstract) { |
518 if (compiler.world.isDirectlyInstantiated(cls)) { | 485 if (compiler.world.isDirectlyInstantiated(cls)) { |
519 returnType = types.nonNullExact(cls); | 486 returnType = types.nonNullExact(cls); |
520 } else if (compiler.world.isIndirectlyInstantiated(cls)) { | 487 } else if (compiler.world.isIndirectlyInstantiated(cls)) { |
521 returnType = types.nonNullSubclass(cls); | 488 returnType = types.nonNullSubclass(cls); |
522 } else { | 489 } else { |
523 // TODO(johnniwinther): Avoid analyzing [analyzedElement] in this | 490 // TODO(johnniwinther): Avoid analyzing [analyzedElement] in this |
524 // case; it's never called. | 491 // case; it's never called. |
525 returnType = types.nonNullEmpty(); | 492 returnType = types.nonNullEmpty(); |
526 } | 493 } |
527 } else { | 494 } else { |
528 returnType = types.nonNullExact(cls); | 495 returnType = types.nonNullExact(cls); |
529 } | 496 } |
530 } else { | 497 } else { |
531 signature.forEachParameter((LocalParameterElement element) { | 498 signature.forEachParameter((LocalParameterElement element) { |
532 locals.update(element, inferrer.typeOfElement(element), node); | 499 locals.update(element, inferrer.typeOfElement(element), node); |
533 }); | 500 }); |
534 visit(node.body); | 501 visit(node.body); |
535 switch (function.asyncMarker) { | 502 switch (function.asyncMarker) { |
536 case AsyncMarker.SYNC: | 503 case AsyncMarker.SYNC: |
537 if (returnType == null) { | 504 if (returnType == null) { |
538 // No return in the body. | 505 // No return in the body. |
539 returnType = locals.seenReturnOrThrow | 506 returnType = locals.seenReturnOrThrow |
540 ? types.nonNullEmpty() // Body always throws. | 507 ? types.nonNullEmpty() // Body always throws. |
541 : types.nullType; | 508 : types.nullType; |
542 } else if (!locals.seenReturnOrThrow) { | 509 } else if (!locals.seenReturnOrThrow) { |
543 // We haven't seen returns on all branches. So the method may | 510 // We haven't seen returns on all branches. So the method may |
544 // also return null. | 511 // also return null. |
545 returnType = inferrer.addReturnTypeFor( | 512 returnType = inferrer.addReturnTypeFor( |
546 analyzedElement, returnType, types.nullType); | 513 analyzedElement, returnType, types.nullType); |
547 } | 514 } |
548 break; | 515 break; |
549 | 516 |
550 case AsyncMarker.SYNC_STAR: | 517 case AsyncMarker.SYNC_STAR: |
551 // TODO(asgerf): Maybe make a ContainerTypeMask for these? The type | 518 // TODO(asgerf): Maybe make a ContainerTypeMask for these? The type |
552 // contained is the method body's return type. | 519 // contained is the method body's return type. |
553 returnType = inferrer.addReturnTypeFor( | 520 returnType = inferrer.addReturnTypeFor( |
554 analyzedElement, returnType, types.syncStarIterableType); | 521 analyzedElement, returnType, types.syncStarIterableType); |
555 break; | 522 break; |
556 | 523 |
557 case AsyncMarker.ASYNC: | 524 case AsyncMarker.ASYNC: |
558 returnType = inferrer.addReturnTypeFor( | 525 returnType = inferrer.addReturnTypeFor( |
559 analyzedElement, returnType, types.asyncFutureType); | 526 analyzedElement, returnType, types.asyncFutureType); |
560 break; | 527 break; |
561 | 528 |
562 case AsyncMarker.ASYNC_STAR: | 529 case AsyncMarker.ASYNC_STAR: |
563 returnType = inferrer.addReturnTypeFor( | 530 returnType = inferrer.addReturnTypeFor( |
564 analyzedElement, returnType, types.asyncStarStreamType); | 531 analyzedElement, returnType, types.asyncStarStreamType); |
565 break; | 532 break; |
566 } | 533 } |
567 } | 534 } |
568 | 535 |
569 compiler.world.registerSideEffects(analyzedElement, sideEffects); | 536 compiler.world.registerSideEffects(analyzedElement, sideEffects); |
570 assert(breaksFor.isEmpty); | 537 assert(breaksFor.isEmpty); |
571 assert(continuesFor.isEmpty); | 538 assert(continuesFor.isEmpty); |
572 return returnType; | 539 return returnType; |
573 } | 540 } |
574 | 541 |
575 T visitFunctionExpression(ast.FunctionExpression node) { | 542 T visitFunctionExpression(ast.FunctionExpression node) { |
576 // We loose track of [this] in closures (see issue 20840). To be on | 543 // We loose track of [this] in closures (see issue 20840). To be on |
577 // the safe side, we mark [this] as exposed here. We could do better by | 544 // the safe side, we mark [this] as exposed here. We could do better by |
578 // analyzing the closure. | 545 // analyzing the closure. |
579 // TODO(herhut): Analyze whether closure exposes this. | 546 // TODO(herhut): Analyze whether closure exposes this. |
580 isThisExposed = true; | 547 isThisExposed = true; |
581 LocalFunctionElement element = elements.getFunctionDefinition(node); | 548 LocalFunctionElement element = elements.getFunctionDefinition(node); |
582 // We don't put the closure in the work queue of the | 549 // We don't put the closure in the work queue of the |
583 // inferrer, because it will share information with its enclosing | 550 // inferrer, because it will share information with its enclosing |
584 // method, like for example the types of local variables. | 551 // method, like for example the types of local variables. |
585 LocalsHandler closureLocals = new LocalsHandler<T>.from( | 552 LocalsHandler closureLocals = |
586 locals, node, useOtherTryBlock: false); | 553 new LocalsHandler<T>.from(locals, node, useOtherTryBlock: false); |
587 SimpleTypeInferrerVisitor visitor = new SimpleTypeInferrerVisitor<T>( | 554 SimpleTypeInferrerVisitor visitor = new SimpleTypeInferrerVisitor<T>( |
588 element, compiler, inferrer, closureLocals); | 555 element, compiler, inferrer, closureLocals); |
589 visitor.run(); | 556 visitor.run(); |
590 inferrer.recordReturnType(element, visitor.returnType); | 557 inferrer.recordReturnType(element, visitor.returnType); |
591 | 558 |
592 // Record the types of captured non-boxed variables. Types of | 559 // Record the types of captured non-boxed variables. Types of |
593 // these variables may already be there, because of an analysis of | 560 // these variables may already be there, because of an analysis of |
594 // a previous closure. | 561 // a previous closure. |
595 ClosureClassMap nestedClosureData = | 562 ClosureClassMap nestedClosureData = |
596 compiler.closureToClassMapper.getMappingForNestedFunction(node); | 563 compiler.closureToClassMapper.getMappingForNestedFunction(node); |
597 nestedClosureData.forEachCapturedVariable((variable, field) { | 564 nestedClosureData.forEachCapturedVariable((variable, field) { |
598 if (!nestedClosureData.isVariableBoxed(variable)) { | 565 if (!nestedClosureData.isVariableBoxed(variable)) { |
599 if (variable == nestedClosureData.thisLocal) { | 566 if (variable == nestedClosureData.thisLocal) { |
600 inferrer.recordType(field, thisType); | 567 inferrer.recordType(field, thisType); |
601 } | 568 } |
602 // The type is null for type parameters. | 569 // The type is null for type parameters. |
603 if (locals.locals[variable] == null) return; | 570 if (locals.locals[variable] == null) return; |
604 inferrer.recordType(field, locals.locals[variable]); | 571 inferrer.recordType(field, locals.locals[variable]); |
605 } | 572 } |
606 capturedVariables.add(variable); | 573 capturedVariables.add(variable); |
607 }); | 574 }); |
608 | 575 |
609 return inferrer.concreteTypes.putIfAbsent(node, () { | 576 return inferrer.concreteTypes.putIfAbsent(node, () { |
610 return types.allocateClosure(node, element); | 577 return types.allocateClosure(node, element); |
611 }); | 578 }); |
612 } | 579 } |
613 | 580 |
614 T visitFunctionDeclaration(ast.FunctionDeclaration node) { | 581 T visitFunctionDeclaration(ast.FunctionDeclaration node) { |
615 LocalFunctionElement element = elements.getFunctionDefinition(node.function)
; | 582 LocalFunctionElement element = |
| 583 elements.getFunctionDefinition(node.function); |
616 T type = inferrer.concreteTypes.putIfAbsent(node.function, () { | 584 T type = inferrer.concreteTypes.putIfAbsent(node.function, () { |
617 return types.allocateClosure(node.function, element); | 585 return types.allocateClosure(node.function, element); |
618 }); | 586 }); |
619 locals.update(element, type, node); | 587 locals.update(element, type, node); |
620 visit(node.function); | 588 visit(node.function); |
621 return type; | 589 return type; |
622 } | 590 } |
623 | 591 |
624 T visitStringInterpolation(ast.StringInterpolation node) { | 592 T visitStringInterpolation(ast.StringInterpolation node) { |
625 // Interpolation could have any effects since it could call any toString() | 593 // Interpolation could have any effects since it could call any toString() |
(...skipping 17 matching lines...) Expand all Loading... |
643 for (ast.Node element in node.elements.nodes) { | 611 for (ast.Node element in node.elements.nodes) { |
644 T type = visit(element); | 612 T type = visit(element); |
645 elementType = elementType == null | 613 elementType = elementType == null |
646 ? types.allocatePhi(null, null, type) | 614 ? types.allocatePhi(null, null, type) |
647 : types.addPhiInput(null, elementType, type); | 615 : types.addPhiInput(null, elementType, type); |
648 length++; | 616 length++; |
649 } | 617 } |
650 elementType = elementType == null | 618 elementType = elementType == null |
651 ? types.nonNullEmpty() | 619 ? types.nonNullEmpty() |
652 : types.simplifyPhi(null, null, elementType); | 620 : types.simplifyPhi(null, null, elementType); |
653 T containerType = node.isConst | 621 T containerType = |
654 ? types.constListType | 622 node.isConst ? types.constListType : types.growableListType; |
655 : types.growableListType; | |
656 return types.allocateList( | 623 return types.allocateList( |
657 containerType, | 624 containerType, node, outermostElement, elementType, length); |
658 node, | |
659 outermostElement, | |
660 elementType, | |
661 length); | |
662 }); | 625 }); |
663 } | 626 } |
664 | 627 |
665 T visitLiteralMap(ast.LiteralMap node) { | 628 T visitLiteralMap(ast.LiteralMap node) { |
666 return inferrer.concreteTypes.putIfAbsent(node, () { | 629 return inferrer.concreteTypes.putIfAbsent(node, () { |
667 ast.NodeList entries = node.entries; | 630 ast.NodeList entries = node.entries; |
668 List<T> keyTypes = []; | 631 List<T> keyTypes = []; |
669 List<T> valueTypes = []; | 632 List<T> valueTypes = []; |
670 | 633 |
671 for (ast.LiteralMapEntry entry in entries) { | 634 for (ast.LiteralMapEntry entry in entries) { |
672 keyTypes.add(visit(entry.key)); | 635 keyTypes.add(visit(entry.key)); |
673 valueTypes.add(visit(entry.value)); | 636 valueTypes.add(visit(entry.value)); |
674 } | 637 } |
675 | 638 |
676 T type = node.isConst ? types.constMapType : types.mapType; | 639 T type = node.isConst ? types.constMapType : types.mapType; |
677 return types.allocateMap(type, | 640 return types.allocateMap( |
678 node, | 641 type, node, outermostElement, keyTypes, valueTypes); |
679 outermostElement, | |
680 keyTypes, | |
681 valueTypes); | |
682 }); | 642 }); |
683 } | 643 } |
684 | 644 |
685 bool isThisOrSuper(ast.Node node) => node.isThis() || node.isSuper(); | 645 bool isThisOrSuper(ast.Node node) => node.isThis() || node.isSuper(); |
686 | 646 |
687 bool isInClassOrSubclass(Element element) { | 647 bool isInClassOrSubclass(Element element) { |
688 ClassElement cls = outermostElement.enclosingClass.declaration; | 648 ClassElement cls = outermostElement.enclosingClass.declaration; |
689 ClassElement enclosing = element.enclosingClass.declaration; | 649 ClassElement enclosing = element.enclosingClass.declaration; |
690 return compiler.world.isSubclassOf(enclosing, cls); | 650 return compiler.world.isSubclassOf(enclosing, cls); |
691 } | 651 } |
692 | 652 |
693 void checkIfExposesThis(Selector selector, TypeMask mask) { | 653 void checkIfExposesThis(Selector selector, TypeMask mask) { |
694 if (isThisExposed) return; | 654 if (isThisExposed) return; |
695 inferrer.forEachElementMatching(selector, mask, (element) { | 655 inferrer.forEachElementMatching(selector, mask, (element) { |
696 if (element.isField) { | 656 if (element.isField) { |
697 if (!selector.isSetter | 657 if (!selector.isSetter && |
698 && isInClassOrSubclass(element) | 658 isInClassOrSubclass(element) && |
699 && !element.modifiers.isFinal | 659 !element.modifiers.isFinal && |
700 && locals.fieldScope.readField(element) == null | 660 locals.fieldScope.readField(element) == null && |
701 && element.initializer == null) { | 661 element.initializer == null) { |
702 // If the field is being used before this constructor | 662 // If the field is being used before this constructor |
703 // actually had a chance to initialize it, say it can be | 663 // actually had a chance to initialize it, say it can be |
704 // null. | 664 // null. |
705 inferrer.recordTypeOfNonFinalField( | 665 inferrer.recordTypeOfNonFinalField( |
706 analyzedElement.node, element, | 666 analyzedElement.node, element, types.nullType); |
707 types.nullType); | |
708 } | 667 } |
709 // Accessing a field does not expose [:this:]. | 668 // Accessing a field does not expose [:this:]. |
710 return true; | 669 return true; |
711 } | 670 } |
712 // TODO(ngeoffray): We could do better here if we knew what we | 671 // TODO(ngeoffray): We could do better here if we knew what we |
713 // are calling does not expose this. | 672 // are calling does not expose this. |
714 isThisExposed = true; | 673 isThisExposed = true; |
715 return false; | 674 return false; |
716 }); | 675 }); |
717 } | 676 } |
718 | 677 |
719 bool get inInstanceContext { | 678 bool get inInstanceContext { |
720 return (outermostElement.isInstanceMember && !outermostElement.isField) | 679 return (outermostElement.isInstanceMember && !outermostElement.isField) || |
721 || outermostElement.isGenerativeConstructor; | 680 outermostElement.isGenerativeConstructor; |
722 } | 681 } |
723 | 682 |
724 bool treatAsInstanceMember(Element element) { | 683 bool treatAsInstanceMember(Element element) { |
725 return (Elements.isUnresolved(element) && inInstanceContext) | 684 return (Elements.isUnresolved(element) && inInstanceContext) || |
726 || (element != null && element.isInstanceMember); | 685 (element != null && element.isInstanceMember); |
727 } | 686 } |
728 | 687 |
729 @override | 688 @override |
730 T handleSendSet(ast.SendSet node) { | 689 T handleSendSet(ast.SendSet node) { |
731 Element element = elements[node]; | 690 Element element = elements[node]; |
732 if (!Elements.isUnresolved(element) && element.impliesType) { | 691 if (!Elements.isUnresolved(element) && element.impliesType) { |
733 node.visitChildren(this); | 692 node.visitChildren(this); |
734 return types.dynamicType; | 693 return types.dynamicType; |
735 } | 694 } |
736 | 695 |
737 Selector getterSelector = | 696 Selector getterSelector = elements.getGetterSelectorInComplexSendSet(node); |
738 elements.getGetterSelectorInComplexSendSet(node); | 697 TypeMask getterMask = elements.getGetterTypeMaskInComplexSendSet(node); |
739 TypeMask getterMask = | 698 TypeMask operatorMask = elements.getOperatorTypeMaskInComplexSendSet(node); |
740 elements.getGetterTypeMaskInComplexSendSet(node); | |
741 TypeMask operatorMask = | |
742 elements.getOperatorTypeMaskInComplexSendSet(node); | |
743 Selector setterSelector = elements.getSelector(node); | 699 Selector setterSelector = elements.getSelector(node); |
744 TypeMask setterMask = elements.getTypeMask(node); | 700 TypeMask setterMask = elements.getTypeMask(node); |
745 | 701 |
746 String op = node.assignmentOperator.source; | 702 String op = node.assignmentOperator.source; |
747 bool isIncrementOrDecrement = op == '++' || op == '--'; | 703 bool isIncrementOrDecrement = op == '++' || op == '--'; |
748 | 704 |
749 T receiverType; | 705 T receiverType; |
750 bool isCallOnThis = false; | 706 bool isCallOnThis = false; |
751 if (node.receiver == null) { | 707 if (node.receiver == null) { |
752 if (treatAsInstanceMember(element)) { | 708 if (treatAsInstanceMember(element)) { |
(...skipping 25 matching lines...) Expand all Loading... |
778 | 734 |
779 if (!visitingInitializers && !isThisExposed) { | 735 if (!visitingInitializers && !isThisExposed) { |
780 for (ast.Node node in node.arguments) { | 736 for (ast.Node node in node.arguments) { |
781 if (isThisOrSuper(node)) { | 737 if (isThisOrSuper(node)) { |
782 isThisExposed = true; | 738 isThisExposed = true; |
783 break; | 739 break; |
784 } | 740 } |
785 } | 741 } |
786 if (!isThisExposed && isCallOnThis) { | 742 if (!isThisExposed && isCallOnThis) { |
787 checkIfExposesThis( | 743 checkIfExposesThis( |
788 setterSelector, | 744 setterSelector, types.newTypedSelector(receiverType, setterMask)); |
789 types.newTypedSelector(receiverType, setterMask)); | |
790 if (getterSelector != null) { | 745 if (getterSelector != null) { |
791 checkIfExposesThis( | 746 checkIfExposesThis( |
792 getterSelector, | 747 getterSelector, types.newTypedSelector(receiverType, getterMask)); |
793 types.newTypedSelector(receiverType, getterMask)); | |
794 } | 748 } |
795 } | 749 } |
796 } | 750 } |
797 | 751 |
798 if (node.isIndex) { | 752 if (node.isIndex) { |
799 return internalError(node, "Unexpected index operation"); | 753 return internalError(node, "Unexpected index operation"); |
800 } else if (op == '=') { | 754 } else if (op == '=') { |
801 return handlePlainAssignment( | 755 return handlePlainAssignment(node, element, setterSelector, setterMask, |
802 node, element, setterSelector, setterMask, receiverType, rhsType, | 756 receiverType, rhsType, node.arguments.head); |
803 node.arguments.head); | |
804 } else { | 757 } else { |
805 // [foo ??= bar], [: foo++ :] or [: foo += 1 :]. | 758 // [foo ??= bar], [: foo++ :] or [: foo += 1 :]. |
806 T getterType; | 759 T getterType; |
807 T newType; | 760 T newType; |
808 | 761 |
809 if (Elements.isMalformed(element)) return types.dynamicType; | 762 if (Elements.isMalformed(element)) return types.dynamicType; |
810 | 763 |
811 if (Elements.isStaticOrTopLevelField(element)) { | 764 if (Elements.isStaticOrTopLevelField(element)) { |
812 Element getterElement = elements[node.selector]; | 765 Element getterElement = elements[node.selector]; |
813 getterType = handleStaticSend( | 766 getterType = handleStaticSend( |
814 node, getterSelector, getterMask, getterElement, null); | 767 node, getterSelector, getterMask, getterElement, null); |
815 } else if (Elements.isUnresolved(element) | 768 } else if (Elements.isUnresolved(element) || |
816 || element.isSetter | 769 element.isSetter || |
817 || element.isField) { | 770 element.isField) { |
818 getterType = handleDynamicSend( | 771 getterType = handleDynamicSend( |
819 node, getterSelector, getterMask, receiverType, null); | 772 node, getterSelector, getterMask, receiverType, null); |
820 } else if (element.isLocal) { | 773 } else if (element.isLocal) { |
821 LocalElement local = element; | 774 LocalElement local = element; |
822 getterType = locals.use(local); | 775 getterType = locals.use(local); |
823 } else { | 776 } else { |
824 // Bogus SendSet, for example [: myMethod += 42 :]. | 777 // Bogus SendSet, for example [: myMethod += 42 :]. |
825 getterType = types.dynamicType; | 778 getterType = types.dynamicType; |
826 } | 779 } |
827 | 780 |
828 if (op == '??=') { | 781 if (op == '??=') { |
829 newType = types.allocateDiamondPhi(getterType, rhsType); | 782 newType = types.allocateDiamondPhi(getterType, rhsType); |
830 } else { | 783 } else { |
831 Selector operatorSelector = | 784 Selector operatorSelector = |
832 elements.getOperatorSelectorInComplexSendSet(node); | 785 elements.getOperatorSelectorInComplexSendSet(node); |
833 newType = handleDynamicSend( | 786 newType = handleDynamicSend(node, operatorSelector, operatorMask, |
834 node, operatorSelector, operatorMask, | |
835 getterType, new ArgumentsTypes<T>([rhsType], null)); | 787 getterType, new ArgumentsTypes<T>([rhsType], null)); |
836 } | 788 } |
837 | 789 |
838 if (Elements.isStaticOrTopLevelField(element)) { | 790 if (Elements.isStaticOrTopLevelField(element)) { |
839 handleStaticSend( | 791 handleStaticSend(node, setterSelector, setterMask, element, |
840 node, setterSelector, setterMask, element, | |
841 new ArgumentsTypes<T>([newType], null)); | 792 new ArgumentsTypes<T>([newType], null)); |
842 } else if (Elements.isUnresolved(element) | 793 } else if (Elements.isUnresolved(element) || |
843 || element.isSetter | 794 element.isSetter || |
844 || element.isField) { | 795 element.isField) { |
845 handleDynamicSend(node, setterSelector, setterMask, receiverType, | 796 handleDynamicSend(node, setterSelector, setterMask, receiverType, |
846 new ArgumentsTypes<T>([newType], null)); | 797 new ArgumentsTypes<T>([newType], null)); |
847 } else if (element.isLocal) { | 798 } else if (element.isLocal) { |
848 locals.update(element, newType, node); | 799 locals.update(element, newType, node); |
849 } | 800 } |
850 | 801 |
851 return node.isPostfix ? getterType : newType; | 802 return node.isPostfix ? getterType : newType; |
852 } | 803 } |
853 } | 804 } |
854 | 805 |
855 /// Handle compound index set, like `foo[0] += 42` or `foo[0]++`. | 806 /// Handle compound index set, like `foo[0] += 42` or `foo[0]++`. |
856 T handleCompoundIndexSet( | 807 T handleCompoundIndexSet( |
857 ast.SendSet node, | 808 ast.SendSet node, T receiverType, T indexType, T rhsType) { |
858 T receiverType, | 809 Selector getterSelector = elements.getGetterSelectorInComplexSendSet(node); |
859 T indexType, | 810 TypeMask getterMask = elements.getGetterTypeMaskInComplexSendSet(node); |
860 T rhsType) { | |
861 Selector getterSelector = | |
862 elements.getGetterSelectorInComplexSendSet(node); | |
863 TypeMask getterMask = | |
864 elements.getGetterTypeMaskInComplexSendSet(node); | |
865 Selector operatorSelector = | 811 Selector operatorSelector = |
866 elements.getOperatorSelectorInComplexSendSet(node); | 812 elements.getOperatorSelectorInComplexSendSet(node); |
867 TypeMask operatorMask = | 813 TypeMask operatorMask = elements.getOperatorTypeMaskInComplexSendSet(node); |
868 elements.getOperatorTypeMaskInComplexSendSet(node); | |
869 Selector setterSelector = elements.getSelector(node); | 814 Selector setterSelector = elements.getSelector(node); |
870 TypeMask setterMask = elements.getTypeMask(node); | 815 TypeMask setterMask = elements.getTypeMask(node); |
871 | 816 |
872 T getterType = handleDynamicSend( | 817 T getterType = handleDynamicSend(node, getterSelector, getterMask, |
873 node, | 818 receiverType, new ArgumentsTypes<T>([indexType], null)); |
874 getterSelector, | |
875 getterMask, | |
876 receiverType, | |
877 new ArgumentsTypes<T>([indexType], null)); | |
878 | 819 |
879 T returnType; | 820 T returnType; |
880 if (node.isIfNullAssignment) { | 821 if (node.isIfNullAssignment) { |
881 returnType = types.allocateDiamondPhi(getterType, rhsType); | 822 returnType = types.allocateDiamondPhi(getterType, rhsType); |
882 } else { | 823 } else { |
883 returnType = handleDynamicSend( | 824 returnType = handleDynamicSend(node, operatorSelector, operatorMask, |
884 node, | 825 getterType, new ArgumentsTypes<T>([rhsType], null)); |
885 operatorSelector, | |
886 operatorMask, | |
887 getterType, | |
888 new ArgumentsTypes<T>([rhsType], null)); | |
889 } | 826 } |
890 handleDynamicSend( | 827 handleDynamicSend(node, setterSelector, setterMask, receiverType, |
891 node, | |
892 setterSelector, | |
893 setterMask, | |
894 receiverType, | |
895 new ArgumentsTypes<T>([indexType, returnType], null)); | 828 new ArgumentsTypes<T>([indexType, returnType], null)); |
896 | 829 |
897 if (node.isPostfix) { | 830 if (node.isPostfix) { |
898 return getterType; | 831 return getterType; |
899 } else { | 832 } else { |
900 return returnType; | 833 return returnType; |
901 } | 834 } |
902 } | 835 } |
903 | 836 |
904 /// Handle compound prefix/postfix operations, like `a[0]++`. | 837 /// Handle compound prefix/postfix operations, like `a[0]++`. |
905 T handleCompoundPrefixPostfix( | 838 T handleCompoundPrefixPostfix(ast.Send node, T receiverType, T indexType) { |
906 ast.Send node, | |
907 T receiverType, | |
908 T indexType) { | |
909 return handleCompoundIndexSet( | 839 return handleCompoundIndexSet( |
910 node, receiverType, indexType, types.uint31Type); | 840 node, receiverType, indexType, types.uint31Type); |
911 } | 841 } |
912 | 842 |
913 @override | 843 @override |
914 T visitIndexPostfix( | 844 T visitIndexPostfix(ast.Send node, ast.Node receiver, ast.Node index, |
915 ast.Send node, | 845 op.IncDecOperator operator, _) { |
916 ast.Node receiver, | |
917 ast.Node index, | |
918 op.IncDecOperator operator, | |
919 _) { | |
920 T receiverType = visit(receiver); | 846 T receiverType = visit(receiver); |
921 T indexType = visit(index); | 847 T indexType = visit(index); |
922 return handleCompoundPrefixPostfix(node, receiverType, indexType); | 848 return handleCompoundPrefixPostfix(node, receiverType, indexType); |
923 } | 849 } |
924 | 850 |
925 @override | 851 @override |
926 T visitIndexPrefix( | 852 T visitIndexPrefix(ast.Send node, ast.Node receiver, ast.Node index, |
927 ast.Send node, | 853 op.IncDecOperator operator, _) { |
928 ast.Node receiver, | |
929 ast.Node index, | |
930 op.IncDecOperator operator, | |
931 _) { | |
932 T receiverType = visit(receiver); | 854 T receiverType = visit(receiver); |
933 T indexType = visit(index); | 855 T indexType = visit(index); |
934 return handleCompoundPrefixPostfix(node, receiverType, indexType); | 856 return handleCompoundPrefixPostfix(node, receiverType, indexType); |
935 } | 857 } |
936 | 858 |
937 @override | 859 @override |
938 T visitCompoundIndexSet( | 860 T visitCompoundIndexSet(ast.SendSet node, ast.Node receiver, ast.Node index, |
939 ast.SendSet node, | 861 op.AssignmentOperator operator, ast.Node rhs, _) { |
940 ast.Node receiver, | |
941 ast.Node index, | |
942 op.AssignmentOperator operator, | |
943 ast.Node rhs, | |
944 _) { | |
945 T receiverType = visit(receiver); | 862 T receiverType = visit(receiver); |
946 T indexType = visit(index); | 863 T indexType = visit(index); |
947 T rhsType = visit(rhs); | 864 T rhsType = visit(rhs); |
948 return handleCompoundIndexSet(node, receiverType, indexType, rhsType); | 865 return handleCompoundIndexSet(node, receiverType, indexType, rhsType); |
949 } | 866 } |
950 | 867 |
951 @override | 868 @override |
952 T visitIndexSetIfNull( | 869 T visitIndexSetIfNull( |
953 ast.SendSet node, | 870 ast.SendSet node, ast.Node receiver, ast.Node index, ast.Node rhs, _) { |
954 ast.Node receiver, | |
955 ast.Node index, | |
956 ast.Node rhs, | |
957 _) { | |
958 T receiverType = visit(receiver); | 871 T receiverType = visit(receiver); |
959 T indexType = visit(index); | 872 T indexType = visit(index); |
960 T rhsType = visit(rhs); | 873 T rhsType = visit(rhs); |
961 return handleCompoundIndexSet(node, receiverType, indexType, rhsType); | 874 return handleCompoundIndexSet(node, receiverType, indexType, rhsType); |
962 } | 875 } |
963 | 876 |
964 @override | 877 @override |
965 T visitSuperIndexPrefix( | 878 T visitSuperIndexPrefix(ast.Send node, MethodElement getter, |
966 ast.Send node, | 879 MethodElement setter, ast.Node index, op.IncDecOperator operator, _) { |
967 MethodElement getter, | |
968 MethodElement setter, | |
969 ast.Node index, | |
970 op.IncDecOperator operator, | |
971 _) { | |
972 T indexType = visit(index); | 880 T indexType = visit(index); |
973 return handleCompoundPrefixPostfix(node, superType, indexType); | 881 return handleCompoundPrefixPostfix(node, superType, indexType); |
974 } | 882 } |
975 | 883 |
976 @override | 884 @override |
977 T visitSuperIndexPostfix( | 885 T visitSuperIndexPostfix(ast.Send node, MethodElement getter, |
978 ast.Send node, | 886 MethodElement setter, ast.Node index, op.IncDecOperator operator, _) { |
979 MethodElement getter, | |
980 MethodElement setter, | |
981 ast.Node index, | |
982 op.IncDecOperator operator, | |
983 _) { | |
984 T indexType = visit(index); | 887 T indexType = visit(index); |
985 return handleCompoundPrefixPostfix(node, superType, indexType); | 888 return handleCompoundPrefixPostfix(node, superType, indexType); |
986 } | 889 } |
987 | 890 |
988 /// Handle compound super index set, like `super[42] =+ 2`. | 891 /// Handle compound super index set, like `super[42] =+ 2`. |
989 T handleSuperCompoundIndexSet( | 892 T handleSuperCompoundIndexSet( |
990 ast.SendSet node, | 893 ast.SendSet node, ast.Node index, ast.Node rhs) { |
991 ast.Node index, | |
992 ast.Node rhs) { | |
993 T receiverType = superType; | 894 T receiverType = superType; |
994 T indexType = visit(index); | 895 T indexType = visit(index); |
995 T rhsType = visit(rhs); | 896 T rhsType = visit(rhs); |
996 return handleCompoundIndexSet(node, receiverType, indexType, rhsType); | 897 return handleCompoundIndexSet(node, receiverType, indexType, rhsType); |
997 } | 898 } |
998 | 899 |
999 @override | 900 @override |
1000 T visitSuperCompoundIndexSet( | 901 T visitSuperCompoundIndexSet( |
1001 ast.SendSet node, | 902 ast.SendSet node, |
1002 MethodElement getter, | 903 MethodElement getter, |
1003 MethodElement setter, | 904 MethodElement setter, |
1004 ast.Node index, | 905 ast.Node index, |
1005 op.AssignmentOperator operator, | 906 op.AssignmentOperator operator, |
1006 ast.Node rhs, | 907 ast.Node rhs, |
1007 _) { | 908 _) { |
1008 return handleSuperCompoundIndexSet(node, index, rhs); | 909 return handleSuperCompoundIndexSet(node, index, rhs); |
1009 } | 910 } |
1010 | 911 |
1011 @override | 912 @override |
1012 T visitSuperIndexSetIfNull( | 913 T visitSuperIndexSetIfNull(ast.SendSet node, MethodElement getter, |
1013 ast.SendSet node, | 914 MethodElement setter, ast.Node index, ast.Node rhs, _) { |
1014 MethodElement getter, | |
1015 MethodElement setter, | |
1016 ast.Node index, | |
1017 ast.Node rhs, | |
1018 _) { | |
1019 return handleSuperCompoundIndexSet(node, index, rhs); | 915 return handleSuperCompoundIndexSet(node, index, rhs); |
1020 } | 916 } |
1021 | 917 |
1022 @override | 918 @override |
1023 T visitUnresolvedSuperCompoundIndexSet( | 919 T visitUnresolvedSuperCompoundIndexSet(ast.Send node, Element element, |
1024 ast.Send node, | 920 ast.Node index, op.AssignmentOperator operator, ast.Node rhs, _) { |
1025 Element element, | |
1026 ast.Node index, | |
1027 op.AssignmentOperator operator, | |
1028 ast.Node rhs, | |
1029 _) { | |
1030 return handleSuperCompoundIndexSet(node, index, rhs); | 921 return handleSuperCompoundIndexSet(node, index, rhs); |
1031 } | 922 } |
1032 | 923 |
1033 @override | 924 @override |
1034 T visitUnresolvedSuperIndexSetIfNull( | 925 T visitUnresolvedSuperIndexSetIfNull( |
1035 ast.Send node, | 926 ast.Send node, Element element, ast.Node index, ast.Node rhs, _) { |
1036 Element element, | |
1037 ast.Node index, | |
1038 ast.Node rhs, | |
1039 _) { | |
1040 return handleSuperCompoundIndexSet(node, index, rhs); | 927 return handleSuperCompoundIndexSet(node, index, rhs); |
1041 } | 928 } |
1042 | 929 |
1043 @override | 930 @override |
1044 T visitUnresolvedSuperGetterCompoundIndexSet( | 931 T visitUnresolvedSuperGetterCompoundIndexSet( |
1045 ast.SendSet node, | 932 ast.SendSet node, |
1046 Element element, | 933 Element element, |
1047 MethodElement setter, | 934 MethodElement setter, |
1048 ast.Node index, | 935 ast.Node index, |
1049 op.AssignmentOperator operator, | 936 op.AssignmentOperator operator, |
1050 ast.Node rhs, | 937 ast.Node rhs, |
1051 _) { | 938 _) { |
1052 return handleSuperCompoundIndexSet(node, index, rhs); | 939 return handleSuperCompoundIndexSet(node, index, rhs); |
1053 } | 940 } |
1054 | 941 |
1055 @override | 942 @override |
1056 T visitUnresolvedSuperGetterIndexSetIfNull( | 943 T visitUnresolvedSuperGetterIndexSetIfNull(ast.SendSet node, Element element, |
1057 ast.SendSet node, | 944 MethodElement setter, ast.Node index, ast.Node rhs, _) { |
1058 Element element, | |
1059 MethodElement setter, | |
1060 ast.Node index, | |
1061 ast.Node rhs, | |
1062 _) { | |
1063 return handleSuperCompoundIndexSet(node, index, rhs); | 945 return handleSuperCompoundIndexSet(node, index, rhs); |
1064 } | 946 } |
1065 | 947 |
1066 @override | 948 @override |
1067 T visitUnresolvedSuperSetterCompoundIndexSet( | 949 T visitUnresolvedSuperSetterCompoundIndexSet( |
1068 ast.SendSet node, | 950 ast.SendSet node, |
1069 MethodElement getter, | 951 MethodElement getter, |
1070 Element element, | 952 Element element, |
1071 ast.Node index, | 953 ast.Node index, |
1072 op.AssignmentOperator operator, | 954 op.AssignmentOperator operator, |
1073 ast.Node rhs, | 955 ast.Node rhs, |
1074 _) { | 956 _) { |
1075 return handleSuperCompoundIndexSet(node, index, rhs); | 957 return handleSuperCompoundIndexSet(node, index, rhs); |
1076 } | 958 } |
1077 | 959 |
1078 @override | 960 @override |
1079 T visitUnresolvedSuperSetterIndexSetIfNull( | 961 T visitUnresolvedSuperSetterIndexSetIfNull(ast.SendSet node, |
1080 ast.SendSet node, | 962 MethodElement getter, Element element, ast.Node index, ast.Node rhs, _) { |
1081 MethodElement getter, | |
1082 Element element, | |
1083 ast.Node index, | |
1084 ast.Node rhs, | |
1085 _) { | |
1086 return handleSuperCompoundIndexSet(node, index, rhs); | 963 return handleSuperCompoundIndexSet(node, index, rhs); |
1087 } | 964 } |
1088 | 965 |
1089 @override | 966 @override |
1090 T visitUnresolvedSuperIndexPrefix( | 967 T visitUnresolvedSuperIndexPrefix(ast.Send node, Element element, |
1091 ast.Send node, | 968 ast.Node index, op.IncDecOperator operator, _) { |
1092 Element element, | |
1093 ast.Node index, | |
1094 op.IncDecOperator operator, | |
1095 _) { | |
1096 T indexType = visit(index); | 969 T indexType = visit(index); |
1097 return handleCompoundPrefixPostfix(node, superType, indexType); | 970 return handleCompoundPrefixPostfix(node, superType, indexType); |
1098 } | 971 } |
1099 | 972 |
1100 @override | 973 @override |
1101 T visitUnresolvedSuperGetterIndexPrefix( | 974 T visitUnresolvedSuperGetterIndexPrefix(ast.SendSet node, Element element, |
1102 ast.SendSet node, | 975 MethodElement setter, ast.Node index, op.IncDecOperator operator, _) { |
1103 Element element, | |
1104 MethodElement setter, | |
1105 ast.Node index, | |
1106 op.IncDecOperator operator, | |
1107 _) { | |
1108 T indexType = visit(index); | 976 T indexType = visit(index); |
1109 return handleCompoundPrefixPostfix(node, superType, indexType); | 977 return handleCompoundPrefixPostfix(node, superType, indexType); |
1110 } | 978 } |
1111 | 979 |
1112 @override | 980 @override |
1113 T visitUnresolvedSuperSetterIndexPrefix( | 981 T visitUnresolvedSuperSetterIndexPrefix( |
1114 ast.SendSet node, | 982 ast.SendSet node, |
1115 MethodElement getter, | 983 MethodElement getter, |
1116 Element element, | 984 Element element, |
1117 ast.Node index, | 985 ast.Node index, |
1118 op.IncDecOperator operator, | 986 op.IncDecOperator operator, |
1119 _) { | 987 _) { |
1120 T indexType = visit(index); | 988 T indexType = visit(index); |
1121 return handleCompoundPrefixPostfix(node, superType, indexType); | 989 return handleCompoundPrefixPostfix(node, superType, indexType); |
1122 } | 990 } |
1123 | 991 |
1124 @override | 992 @override |
1125 T visitUnresolvedSuperIndexPostfix( | 993 T visitUnresolvedSuperIndexPostfix(ast.Send node, Element element, |
1126 ast.Send node, | 994 ast.Node index, op.IncDecOperator operator, _) { |
1127 Element element, | |
1128 ast.Node index, | |
1129 op.IncDecOperator operator, | |
1130 _) { | |
1131 T indexType = visit(index); | 995 T indexType = visit(index); |
1132 return handleCompoundPrefixPostfix(node, superType, indexType); | 996 return handleCompoundPrefixPostfix(node, superType, indexType); |
1133 } | 997 } |
1134 | 998 |
1135 @override | 999 @override |
1136 T visitUnresolvedSuperGetterIndexPostfix( | 1000 T visitUnresolvedSuperGetterIndexPostfix(ast.SendSet node, Element element, |
1137 ast.SendSet node, | 1001 MethodElement setter, ast.Node index, op.IncDecOperator operator, _) { |
1138 Element element, | |
1139 MethodElement setter, | |
1140 ast.Node index, | |
1141 op.IncDecOperator operator, | |
1142 _) { | |
1143 T indexType = visit(index); | 1002 T indexType = visit(index); |
1144 return handleCompoundPrefixPostfix(node, superType, indexType); | 1003 return handleCompoundPrefixPostfix(node, superType, indexType); |
1145 } | 1004 } |
1146 | 1005 |
1147 @override | 1006 @override |
1148 T visitUnresolvedSuperSetterIndexPostfix( | 1007 T visitUnresolvedSuperSetterIndexPostfix( |
1149 ast.SendSet node, | 1008 ast.SendSet node, |
1150 MethodElement getter, | 1009 MethodElement getter, |
1151 Element element, | 1010 Element element, |
1152 ast.Node index, | 1011 ast.Node index, |
1153 op.IncDecOperator operator, | 1012 op.IncDecOperator operator, |
1154 _) { | 1013 _) { |
1155 T indexType = visit(index); | 1014 T indexType = visit(index); |
1156 return handleCompoundPrefixPostfix(node, superType, indexType); | 1015 return handleCompoundPrefixPostfix(node, superType, indexType); |
1157 } | 1016 } |
1158 | 1017 |
1159 /// Handle index set, like `foo[0] = 42`. | 1018 /// Handle index set, like `foo[0] = 42`. |
1160 T handleIndexSet(ast.SendSet node, T receiverType, T indexType, T rhsType) { | 1019 T handleIndexSet(ast.SendSet node, T receiverType, T indexType, T rhsType) { |
1161 Selector setterSelector = elements.getSelector(node); | 1020 Selector setterSelector = elements.getSelector(node); |
1162 TypeMask setterMask = elements.getTypeMask(node); | 1021 TypeMask setterMask = elements.getTypeMask(node); |
1163 handleDynamicSend( | 1022 handleDynamicSend(node, setterSelector, setterMask, receiverType, |
1164 node, | |
1165 setterSelector, | |
1166 setterMask, | |
1167 receiverType, | |
1168 new ArgumentsTypes<T>([indexType, rhsType], null)); | 1023 new ArgumentsTypes<T>([indexType, rhsType], null)); |
1169 return rhsType; | 1024 return rhsType; |
1170 } | 1025 } |
1171 | 1026 |
1172 @override | 1027 @override |
1173 T visitIndexSet( | 1028 T visitIndexSet( |
1174 ast.SendSet node, | 1029 ast.SendSet node, ast.Node receiver, ast.Node index, ast.Node rhs, _) { |
1175 ast.Node receiver, | |
1176 ast.Node index, | |
1177 ast.Node rhs, | |
1178 _) { | |
1179 T receiverType = visit(receiver); | 1030 T receiverType = visit(receiver); |
1180 T indexType = visit(index); | 1031 T indexType = visit(index); |
1181 T rhsType = visit(rhs); | 1032 T rhsType = visit(rhs); |
1182 return handleIndexSet(node, receiverType, indexType, rhsType); | 1033 return handleIndexSet(node, receiverType, indexType, rhsType); |
1183 } | 1034 } |
1184 | 1035 |
1185 /// Handle super index set, like `super[42] = true`. | 1036 /// Handle super index set, like `super[42] = true`. |
1186 T handleSuperIndexSet( | 1037 T handleSuperIndexSet(ast.SendSet node, ast.Node index, ast.Node rhs) { |
1187 ast.SendSet node, | |
1188 ast.Node index, | |
1189 ast.Node rhs) { | |
1190 T receiverType = superType; | 1038 T receiverType = superType; |
1191 T indexType = visit(index); | 1039 T indexType = visit(index); |
1192 T rhsType = visit(rhs); | 1040 T rhsType = visit(rhs); |
1193 return handleIndexSet(node, receiverType, indexType, rhsType); | 1041 return handleIndexSet(node, receiverType, indexType, rhsType); |
1194 } | 1042 } |
1195 | 1043 |
1196 @override | 1044 @override |
1197 T visitSuperIndexSet( | 1045 T visitSuperIndexSet(ast.SendSet node, FunctionElement function, |
1198 ast.SendSet node, | 1046 ast.Node index, ast.Node rhs, _) { |
1199 FunctionElement function, | |
1200 ast.Node index, | |
1201 ast.Node rhs, | |
1202 _) { | |
1203 return handleSuperIndexSet(node, index, rhs); | 1047 return handleSuperIndexSet(node, index, rhs); |
1204 } | 1048 } |
1205 | 1049 |
1206 @override | 1050 @override |
1207 T visitUnresolvedSuperIndexSet( | 1051 T visitUnresolvedSuperIndexSet( |
1208 ast.SendSet node, | 1052 ast.SendSet node, Element element, ast.Node index, ast.Node rhs, _) { |
1209 Element element, | |
1210 ast.Node index, | |
1211 ast.Node rhs, | |
1212 _) { | |
1213 return handleSuperIndexSet(node, index, rhs); | 1053 return handleSuperIndexSet(node, index, rhs); |
1214 } | 1054 } |
1215 | 1055 |
1216 T handlePlainAssignment(ast.Node node, | 1056 T handlePlainAssignment( |
1217 Element element, | 1057 ast.Node node, |
1218 Selector setterSelector, | 1058 Element element, |
1219 TypeMask setterMask, | 1059 Selector setterSelector, |
1220 T receiverType, | 1060 TypeMask setterMask, |
1221 T rhsType, | 1061 T receiverType, |
1222 ast.Node rhs) { | 1062 T rhsType, |
| 1063 ast.Node rhs) { |
1223 ArgumentsTypes arguments = new ArgumentsTypes<T>([rhsType], null); | 1064 ArgumentsTypes arguments = new ArgumentsTypes<T>([rhsType], null); |
1224 if (Elements.isMalformed(element)) { | 1065 if (Elements.isMalformed(element)) { |
1225 // Code will always throw. | 1066 // Code will always throw. |
1226 } else if (Elements.isStaticOrTopLevelField(element)) { | 1067 } else if (Elements.isStaticOrTopLevelField(element)) { |
1227 handleStaticSend(node, setterSelector, setterMask, element, arguments); | 1068 handleStaticSend(node, setterSelector, setterMask, element, arguments); |
1228 } else if (Elements.isUnresolved(element) || element.isSetter) { | 1069 } else if (Elements.isUnresolved(element) || element.isSetter) { |
1229 if (analyzedElement.isGenerativeConstructor | 1070 if (analyzedElement.isGenerativeConstructor && |
1230 && (node.asSendSet() != null) | 1071 (node.asSendSet() != null) && |
1231 && (node.asSendSet().receiver != null) | 1072 (node.asSendSet().receiver != null) && |
1232 && node.asSendSet().receiver.isThis()) { | 1073 node.asSendSet().receiver.isThis()) { |
1233 Iterable<Element> targets = compiler.world.allFunctions.filter( | 1074 Iterable<Element> targets = compiler.world.allFunctions.filter( |
1234 setterSelector, | 1075 setterSelector, types.newTypedSelector(thisType, setterMask)); |
1235 types.newTypedSelector(thisType, setterMask)); | |
1236 // We just recognized a field initialization of the form: | 1076 // We just recognized a field initialization of the form: |
1237 // `this.foo = 42`. If there is only one target, we can update | 1077 // `this.foo = 42`. If there is only one target, we can update |
1238 // its type. | 1078 // its type. |
1239 if (targets.length == 1) { | 1079 if (targets.length == 1) { |
1240 Element single = targets.first; | 1080 Element single = targets.first; |
1241 if (single.isField) { | 1081 if (single.isField) { |
1242 locals.updateField(single, rhsType); | 1082 locals.updateField(single, rhsType); |
1243 } | 1083 } |
1244 } | 1084 } |
1245 } | 1085 } |
(...skipping 15 matching lines...) Expand all Loading... |
1261 } | 1101 } |
1262 } | 1102 } |
1263 } else if (element.isLocal) { | 1103 } else if (element.isLocal) { |
1264 locals.update(element, rhsType, node); | 1104 locals.update(element, rhsType, node); |
1265 } | 1105 } |
1266 return rhsType; | 1106 return rhsType; |
1267 } | 1107 } |
1268 | 1108 |
1269 /// Handle a super access or invocation that results in a `noSuchMethod` call. | 1109 /// Handle a super access or invocation that results in a `noSuchMethod` call. |
1270 T handleErroneousSuperSend(ast.Send node) { | 1110 T handleErroneousSuperSend(ast.Send node) { |
1271 ArgumentsTypes arguments = node.isPropertyAccess | 1111 ArgumentsTypes arguments = |
1272 ? null | 1112 node.isPropertyAccess ? null : analyzeArguments(node.arguments); |
1273 : analyzeArguments(node.arguments); | |
1274 Selector selector = elements.getSelector(node); | 1113 Selector selector = elements.getSelector(node); |
1275 TypeMask mask = elements.getTypeMask(node); | 1114 TypeMask mask = elements.getTypeMask(node); |
1276 // TODO(herhut): We could do better here if we knew what we | 1115 // TODO(herhut): We could do better here if we knew what we |
1277 // are calling does not expose this. | 1116 // are calling does not expose this. |
1278 isThisExposed = true; | 1117 isThisExposed = true; |
1279 // Ensure we create a node, to make explicit the call to the | 1118 // Ensure we create a node, to make explicit the call to the |
1280 // `noSuchMethod` handler. | 1119 // `noSuchMethod` handler. |
1281 return handleDynamicSend(node, selector, mask, superType, arguments); | 1120 return handleDynamicSend(node, selector, mask, superType, arguments); |
1282 } | 1121 } |
1283 | 1122 |
1284 /// Handle a .call invocation on the values retrieved from the super | 1123 /// Handle a .call invocation on the values retrieved from the super |
1285 /// [element]. For instance `super.foo(bar)` where `foo` is a field or getter. | 1124 /// [element]. For instance `super.foo(bar)` where `foo` is a field or getter. |
1286 T handleSuperClosureCall( | 1125 T handleSuperClosureCall( |
1287 ast.Send node, | 1126 ast.Send node, Element element, ast.NodeList arguments) { |
1288 Element element, | |
1289 ast.NodeList arguments) { | |
1290 ArgumentsTypes argumentTypes = analyzeArguments(arguments.nodes); | 1127 ArgumentsTypes argumentTypes = analyzeArguments(arguments.nodes); |
1291 Selector selector = elements.getSelector(node); | 1128 Selector selector = elements.getSelector(node); |
1292 TypeMask mask = elements.getTypeMask(node); | 1129 TypeMask mask = elements.getTypeMask(node); |
1293 // TODO(herhut): We could do better here if we knew what we | 1130 // TODO(herhut): We could do better here if we knew what we |
1294 // are calling does not expose this. | 1131 // are calling does not expose this. |
1295 isThisExposed = true; | 1132 isThisExposed = true; |
1296 return inferrer.registerCalledClosure( | 1133 return inferrer.registerCalledClosure( |
1297 node, selector, mask, inferrer.typeOfElement(element), | 1134 node, |
1298 outermostElement, argumentTypes, sideEffects, inLoop); | 1135 selector, |
| 1136 mask, |
| 1137 inferrer.typeOfElement(element), |
| 1138 outermostElement, |
| 1139 argumentTypes, |
| 1140 sideEffects, |
| 1141 inLoop); |
1299 } | 1142 } |
1300 | 1143 |
1301 /// Handle an invocation of super [method]. | 1144 /// Handle an invocation of super [method]. |
1302 T handleSuperMethodInvoke(ast.Send node, | 1145 T handleSuperMethodInvoke( |
1303 MethodElement method, | 1146 ast.Send node, MethodElement method, ArgumentsTypes arguments) { |
1304 ArgumentsTypes arguments) { | |
1305 // TODO(herhut): We could do better here if we knew what we | 1147 // TODO(herhut): We could do better here if we knew what we |
1306 // are calling does not expose this. | 1148 // are calling does not expose this. |
1307 isThisExposed = true; | 1149 isThisExposed = true; |
1308 Selector selector = elements.getSelector(node); | 1150 Selector selector = elements.getSelector(node); |
1309 TypeMask mask = elements.getTypeMask(node); | 1151 TypeMask mask = elements.getTypeMask(node); |
1310 return handleStaticSend( | 1152 return handleStaticSend(node, selector, mask, method, arguments); |
1311 node, selector, mask, method, arguments); | |
1312 } | 1153 } |
1313 | 1154 |
1314 /// Handle access to a super field or getter [element]. | 1155 /// Handle access to a super field or getter [element]. |
1315 T handleSuperGet(ast.Send node, | 1156 T handleSuperGet(ast.Send node, Element element) { |
1316 Element element) { | |
1317 // TODO(herhut): We could do better here if we knew what we | 1157 // TODO(herhut): We could do better here if we knew what we |
1318 // are calling does not expose this. | 1158 // are calling does not expose this. |
1319 isThisExposed = true; | 1159 isThisExposed = true; |
1320 Selector selector = elements.getSelector(node); | 1160 Selector selector = elements.getSelector(node); |
1321 TypeMask mask = elements.getTypeMask(node); | 1161 TypeMask mask = elements.getTypeMask(node); |
1322 return handleStaticSend( | 1162 return handleStaticSend(node, selector, mask, element, null); |
1323 node, selector, mask, element, null); | |
1324 } | 1163 } |
1325 | 1164 |
1326 @override | 1165 @override |
1327 T visitUnresolvedSuperIndex( | 1166 T visitUnresolvedSuperIndex( |
1328 ast.Send node, | 1167 ast.Send node, Element element, ast.Node index, _) { |
1329 Element element, | |
1330 ast.Node index, | |
1331 _) { | |
1332 return handleErroneousSuperSend(node); | 1168 return handleErroneousSuperSend(node); |
1333 } | 1169 } |
1334 | 1170 |
1335 @override | 1171 @override |
1336 T visitUnresolvedSuperUnary( | 1172 T visitUnresolvedSuperUnary( |
1337 ast.Send node, | 1173 ast.Send node, op.UnaryOperator operator, Element element, _) { |
1338 op.UnaryOperator operator, | |
1339 Element element, | |
1340 _) { | |
1341 return handleErroneousSuperSend(node); | 1174 return handleErroneousSuperSend(node); |
1342 } | 1175 } |
1343 | 1176 |
1344 @override | 1177 @override |
1345 T visitUnresolvedSuperBinary( | 1178 T visitUnresolvedSuperBinary(ast.Send node, Element element, |
1346 ast.Send node, | 1179 op.BinaryOperator operator, ast.Node argument, _) { |
1347 Element element, | |
1348 op.BinaryOperator operator, | |
1349 ast.Node argument, | |
1350 _) { | |
1351 return handleErroneousSuperSend(node); | 1180 return handleErroneousSuperSend(node); |
1352 } | 1181 } |
1353 | 1182 |
1354 @override | 1183 @override |
1355 T visitUnresolvedSuperGet( | 1184 T visitUnresolvedSuperGet(ast.Send node, Element element, _) { |
1356 ast.Send node, | |
1357 Element element, | |
1358 _) { | |
1359 return handleErroneousSuperSend(node); | 1185 return handleErroneousSuperSend(node); |
1360 } | 1186 } |
1361 | 1187 |
1362 @override | 1188 @override |
1363 T visitSuperSetterGet( | 1189 T visitSuperSetterGet(ast.Send node, MethodElement setter, _) { |
1364 ast.Send node, | |
1365 MethodElement setter, | |
1366 _) { | |
1367 return handleErroneousSuperSend(node); | 1190 return handleErroneousSuperSend(node); |
1368 } | 1191 } |
1369 | 1192 |
1370 @override | 1193 @override |
1371 T visitSuperGetterSet( | 1194 T visitSuperGetterSet(ast.Send node, MethodElement getter, ast.Node rhs, _) { |
1372 ast.Send node, | |
1373 MethodElement getter, | |
1374 ast.Node rhs, | |
1375 _) { | |
1376 return handleErroneousSuperSend(node); | 1195 return handleErroneousSuperSend(node); |
1377 } | 1196 } |
1378 | 1197 |
1379 @override | 1198 @override |
1380 T visitUnresolvedSuperSet( | 1199 T visitUnresolvedSuperSet(ast.Send node, Element element, ast.Node rhs, _) { |
1381 ast.Send node, | |
1382 Element element, | |
1383 ast.Node rhs, | |
1384 _) { | |
1385 return handleErroneousSuperSend(node); | 1200 return handleErroneousSuperSend(node); |
1386 } | 1201 } |
1387 | 1202 |
1388 @override | 1203 @override |
1389 T visitUnresolvedSuperInvoke( | 1204 T visitUnresolvedSuperInvoke( |
1390 ast.Send node, | 1205 ast.Send node, Element element, ast.Node argument, Selector selector, _) { |
1391 Element element, | |
1392 ast.Node argument, | |
1393 Selector selector, | |
1394 _) { | |
1395 return handleErroneousSuperSend(node); | 1206 return handleErroneousSuperSend(node); |
1396 } | 1207 } |
1397 | 1208 |
1398 @override | 1209 @override |
1399 T visitSuperFieldGet( | 1210 T visitSuperFieldGet(ast.Send node, FieldElement field, _) { |
1400 ast.Send node, | |
1401 FieldElement field, | |
1402 _) { | |
1403 return handleSuperGet(node, field); | 1211 return handleSuperGet(node, field); |
1404 } | 1212 } |
1405 | 1213 |
1406 @override | 1214 @override |
1407 T visitSuperGetterGet( | 1215 T visitSuperGetterGet(ast.Send node, MethodElement method, _) { |
1408 ast.Send node, | |
1409 MethodElement method, | |
1410 _) { | |
1411 return handleSuperGet(node, method); | 1216 return handleSuperGet(node, method); |
1412 } | 1217 } |
1413 | 1218 |
1414 @override | 1219 @override |
1415 T visitSuperMethodGet( | 1220 T visitSuperMethodGet(ast.Send node, MethodElement method, _) { |
1416 ast.Send node, | |
1417 MethodElement method, | |
1418 _) { | |
1419 return handleSuperGet(node, method); | 1221 return handleSuperGet(node, method); |
1420 } | 1222 } |
1421 | 1223 |
1422 @override | 1224 @override |
1423 T visitSuperFieldInvoke( | 1225 T visitSuperFieldInvoke(ast.Send node, FieldElement field, |
1424 ast.Send node, | 1226 ast.NodeList arguments, CallStructure callStructure, _) { |
1425 FieldElement field, | |
1426 ast.NodeList arguments, | |
1427 CallStructure callStructure, | |
1428 _) { | |
1429 return handleSuperClosureCall(node, field, arguments); | 1227 return handleSuperClosureCall(node, field, arguments); |
1430 } | 1228 } |
1431 | 1229 |
1432 @override | 1230 @override |
1433 T visitSuperGetterInvoke( | 1231 T visitSuperGetterInvoke(ast.Send node, MethodElement getter, |
1434 ast.Send node, | 1232 ast.NodeList arguments, CallStructure callStructure, _) { |
1435 MethodElement getter, | |
1436 ast.NodeList arguments, | |
1437 CallStructure callStructure, | |
1438 _) { | |
1439 return handleSuperClosureCall(node, getter, arguments); | 1233 return handleSuperClosureCall(node, getter, arguments); |
1440 } | 1234 } |
1441 | 1235 |
1442 @override | 1236 @override |
1443 T visitSuperMethodInvoke( | 1237 T visitSuperMethodInvoke(ast.Send node, MethodElement method, |
1444 ast.Send node, | 1238 ast.NodeList arguments, CallStructure callStructure, _) { |
1445 MethodElement method, | |
1446 ast.NodeList arguments, | |
1447 CallStructure callStructure, | |
1448 _) { | |
1449 return handleSuperMethodInvoke( | 1239 return handleSuperMethodInvoke( |
1450 node, method, analyzeArguments(arguments.nodes)); | 1240 node, method, analyzeArguments(arguments.nodes)); |
1451 } | 1241 } |
1452 | 1242 |
1453 @override | 1243 @override |
1454 T visitSuperSetterInvoke( | 1244 T visitSuperSetterInvoke(ast.Send node, FunctionElement setter, |
1455 ast.Send node, | 1245 ast.NodeList arguments, CallStructure callStructure, _) { |
1456 FunctionElement setter, | |
1457 ast.NodeList arguments, | |
1458 CallStructure callStructure, | |
1459 _) { | |
1460 return handleErroneousSuperSend(node); | 1246 return handleErroneousSuperSend(node); |
1461 } | 1247 } |
1462 | 1248 |
1463 @override | 1249 @override |
1464 T visitSuperIndex( | 1250 T visitSuperIndex(ast.Send node, MethodElement method, ast.Node index, _) { |
1465 ast.Send node, | |
1466 MethodElement method, | |
1467 ast.Node index, | |
1468 _) { | |
1469 return handleSuperMethodInvoke( | 1251 return handleSuperMethodInvoke( |
1470 node, method, analyzeArguments(node.arguments)); | 1252 node, method, analyzeArguments(node.arguments)); |
1471 } | 1253 } |
1472 | 1254 |
1473 @override | 1255 @override |
1474 T visitSuperEquals( | 1256 T visitSuperEquals( |
1475 ast.Send node, | 1257 ast.Send node, MethodElement method, ast.Node argument, _) { |
1476 MethodElement method, | |
1477 ast.Node argument, | |
1478 _) { | |
1479 // TODO(johnniwinther): Special case ==. | 1258 // TODO(johnniwinther): Special case ==. |
1480 return handleSuperMethodInvoke( | 1259 return handleSuperMethodInvoke( |
1481 node, method, analyzeArguments(node.arguments)); | 1260 node, method, analyzeArguments(node.arguments)); |
1482 } | 1261 } |
1483 | 1262 |
1484 @override | 1263 @override |
1485 T visitSuperNotEquals( | 1264 T visitSuperNotEquals( |
1486 ast.Send node, | 1265 ast.Send node, MethodElement method, ast.Node argument, _) { |
1487 MethodElement method, | |
1488 ast.Node argument, | |
1489 _) { | |
1490 // TODO(johnniwinther): Special case !=. | 1266 // TODO(johnniwinther): Special case !=. |
1491 return handleSuperMethodInvoke( | 1267 return handleSuperMethodInvoke( |
1492 node, method, analyzeArguments(node.arguments)); | 1268 node, method, analyzeArguments(node.arguments)); |
1493 } | 1269 } |
1494 | 1270 |
1495 @override | 1271 @override |
1496 T visitSuperBinary( | 1272 T visitSuperBinary(ast.Send node, MethodElement method, |
1497 ast.Send node, | 1273 op.BinaryOperator operator, ast.Node argument, _) { |
1498 MethodElement method, | |
1499 op.BinaryOperator operator, | |
1500 ast.Node argument, | |
1501 _) { | |
1502 return handleSuperMethodInvoke( | 1274 return handleSuperMethodInvoke( |
1503 node, method, analyzeArguments(node.arguments)); | 1275 node, method, analyzeArguments(node.arguments)); |
1504 } | 1276 } |
1505 | 1277 |
1506 @override | 1278 @override |
1507 T visitSuperUnary( | 1279 T visitSuperUnary( |
1508 ast.Send node, | 1280 ast.Send node, op.UnaryOperator operator, MethodElement method, _) { |
1509 op.UnaryOperator operator, | |
1510 MethodElement method, | |
1511 _) { | |
1512 return handleSuperMethodInvoke( | 1281 return handleSuperMethodInvoke( |
1513 node, method, analyzeArguments(node.arguments)); | 1282 node, method, analyzeArguments(node.arguments)); |
1514 } | 1283 } |
1515 | 1284 |
1516 @override | 1285 @override |
1517 T visitSuperMethodIncompatibleInvoke( | 1286 T visitSuperMethodIncompatibleInvoke(ast.Send node, MethodElement method, |
1518 ast.Send node, | 1287 ast.NodeList arguments, CallStructure callStructure, _) { |
1519 MethodElement method, | |
1520 ast.NodeList arguments, | |
1521 CallStructure callStructure, | |
1522 _) { | |
1523 return handleErroneousSuperSend(node); | 1288 return handleErroneousSuperSend(node); |
1524 } | 1289 } |
1525 | 1290 |
1526 // Try to find the length given to a fixed array constructor call. | 1291 // Try to find the length given to a fixed array constructor call. |
1527 int findLength(ast.Send node) { | 1292 int findLength(ast.Send node) { |
1528 ast.Node firstArgument = node.arguments.head; | 1293 ast.Node firstArgument = node.arguments.head; |
1529 Element element = elements[firstArgument]; | 1294 Element element = elements[firstArgument]; |
1530 ast.LiteralInt length = firstArgument.asLiteralInt(); | 1295 ast.LiteralInt length = firstArgument.asLiteralInt(); |
1531 if (length != null) { | 1296 if (length != null) { |
1532 return length.value; | 1297 return length.value; |
1533 } else if (element != null | 1298 } else if (element != null && |
1534 && element.isField | 1299 element.isField && |
1535 && Elements.isStaticOrTopLevelField(element) | 1300 Elements.isStaticOrTopLevelField(element) && |
1536 && compiler.world.fieldNeverChanges(element)) { | 1301 compiler.world.fieldNeverChanges(element)) { |
1537 ConstantValue value = | 1302 ConstantValue value = |
1538 compiler.backend.constants.getConstantValueForVariable(element); | 1303 compiler.backend.constants.getConstantValueForVariable(element); |
1539 if (value != null && value.isInt) { | 1304 if (value != null && value.isInt) { |
1540 IntConstantValue intValue = value; | 1305 IntConstantValue intValue = value; |
1541 return intValue.primitiveValue; | 1306 return intValue.primitiveValue; |
1542 } | 1307 } |
1543 } | 1308 } |
1544 return null; | 1309 return null; |
1545 } | 1310 } |
1546 | 1311 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1587 // match the function element. | 1352 // match the function element. |
1588 // TODO(polux): return nonNullEmpty and check it doesn't break anything | 1353 // TODO(polux): return nonNullEmpty and check it doesn't break anything |
1589 if (!selector.applies(target, compiler.world) || | 1354 if (!selector.applies(target, compiler.world) || |
1590 (mask != null && !mask.canHit(target, selector, compiler.world))) { | 1355 (mask != null && !mask.canHit(target, selector, compiler.world))) { |
1591 return types.dynamicType; | 1356 return types.dynamicType; |
1592 } | 1357 } |
1593 | 1358 |
1594 T returnType = handleStaticSend(node, selector, mask, target, arguments); | 1359 T returnType = handleStaticSend(node, selector, mask, target, arguments); |
1595 if (Elements.isGrowableListConstructorCall(constructor, node, compiler)) { | 1360 if (Elements.isGrowableListConstructorCall(constructor, node, compiler)) { |
1596 return inferrer.concreteTypes.putIfAbsent( | 1361 return inferrer.concreteTypes.putIfAbsent( |
1597 node, () => types.allocateList( | 1362 node, |
1598 types.growableListType, node, outermostElement, | 1363 () => types.allocateList(types.growableListType, node, |
1599 types.nonNullEmpty(), 0)); | 1364 outermostElement, types.nonNullEmpty(), 0)); |
1600 } else if (Elements.isFixedListConstructorCall(constructor, node, compiler) | 1365 } else if (Elements.isFixedListConstructorCall( |
1601 || Elements.isFilledListConstructorCall(constructor, node, compiler)) { | 1366 constructor, node, compiler) || |
1602 | 1367 Elements.isFilledListConstructorCall(constructor, node, compiler)) { |
1603 int length = findLength(node); | 1368 int length = findLength(node); |
1604 T elementType = | 1369 T elementType = |
1605 Elements.isFixedListConstructorCall(constructor, node, compiler) | 1370 Elements.isFixedListConstructorCall(constructor, node, compiler) |
1606 ? types.nullType | 1371 ? types.nullType |
1607 : arguments.positional[1]; | 1372 : arguments.positional[1]; |
1608 | 1373 |
1609 return inferrer.concreteTypes.putIfAbsent( | 1374 return inferrer.concreteTypes.putIfAbsent( |
1610 node, () => types.allocateList( | 1375 node, |
1611 types.fixedListType, node, outermostElement, | 1376 () => types.allocateList(types.fixedListType, node, outermostElement, |
1612 elementType, length)); | 1377 elementType, length)); |
1613 } else if ( | 1378 } else if (Elements.isConstructorOfTypedArraySubclass( |
1614 Elements.isConstructorOfTypedArraySubclass(constructor, compiler)) { | 1379 constructor, compiler)) { |
1615 int length = findLength(node); | 1380 int length = findLength(node); |
1616 T elementType = inferrer.returnTypeOfElement( | 1381 T elementType = inferrer |
1617 target.enclosingClass.lookupMember('[]')); | 1382 .returnTypeOfElement(target.enclosingClass.lookupMember('[]')); |
1618 return inferrer.concreteTypes.putIfAbsent( | 1383 return inferrer.concreteTypes.putIfAbsent( |
1619 node, () => types.allocateList( | 1384 node, |
1620 types.nonNullExact(target.enclosingClass), node, | 1385 () => types.allocateList(types.nonNullExact(target.enclosingClass), |
1621 outermostElement, elementType, length)); | 1386 node, outermostElement, elementType, length)); |
1622 } else { | 1387 } else { |
1623 return returnType; | 1388 return returnType; |
1624 } | 1389 } |
1625 } | 1390 } |
1626 | 1391 |
1627 @override | 1392 @override |
1628 T bulkHandleNew(ast.NewExpression node, _) { | 1393 T bulkHandleNew(ast.NewExpression node, _) { |
1629 Element element = elements[node.send]; | 1394 Element element = elements[node.send]; |
1630 return handleConstructorSend(node.send, element); | 1395 return handleConstructorSend(node.send, element); |
1631 } | 1396 } |
1632 | 1397 |
1633 @override | 1398 @override |
1634 T errorNonConstantConstructorInvoke( | 1399 T errorNonConstantConstructorInvoke(ast.NewExpression node, Element element, |
1635 ast.NewExpression node, | 1400 DartType type, ast.NodeList arguments, CallStructure callStructure, _) { |
1636 Element element, | |
1637 DartType type, | |
1638 ast.NodeList arguments, | |
1639 CallStructure callStructure, | |
1640 _) { | |
1641 return bulkHandleNew(node, _); | 1401 return bulkHandleNew(node, _); |
1642 } | 1402 } |
1643 | 1403 |
1644 /// Handle invocation of a top level or static field or getter [element]. | 1404 /// Handle invocation of a top level or static field or getter [element]. |
1645 T handleStaticFieldOrGetterInvoke(ast.Send node, Element element) { | 1405 T handleStaticFieldOrGetterInvoke(ast.Send node, Element element) { |
1646 ArgumentsTypes arguments = analyzeArguments(node.arguments); | 1406 ArgumentsTypes arguments = analyzeArguments(node.arguments); |
1647 Selector selector = elements.getSelector(node); | 1407 Selector selector = elements.getSelector(node); |
1648 TypeMask mask = elements.getTypeMask(node); | 1408 TypeMask mask = elements.getTypeMask(node); |
1649 handleStaticSend(node, selector, mask, element, arguments); | 1409 handleStaticSend(node, selector, mask, element, arguments); |
1650 return inferrer.registerCalledClosure( | 1410 return inferrer.registerCalledClosure( |
1651 node, selector, mask, inferrer.typeOfElement(element), | 1411 node, |
1652 outermostElement, arguments, sideEffects, inLoop); | 1412 selector, |
| 1413 mask, |
| 1414 inferrer.typeOfElement(element), |
| 1415 outermostElement, |
| 1416 arguments, |
| 1417 sideEffects, |
| 1418 inLoop); |
1653 } | 1419 } |
1654 | 1420 |
1655 /// Handle invocation of a top level or static [function]. | 1421 /// Handle invocation of a top level or static [function]. |
1656 T handleStaticFunctionInvoke(ast.Send node, MethodElement function) { | 1422 T handleStaticFunctionInvoke(ast.Send node, MethodElement function) { |
1657 if (compiler.backend.isForeign(function)) { | 1423 if (compiler.backend.isForeign(function)) { |
1658 return handleForeignSend(node, function); | 1424 return handleForeignSend(node, function); |
1659 } | 1425 } |
1660 ArgumentsTypes arguments = analyzeArguments(node.arguments); | 1426 ArgumentsTypes arguments = analyzeArguments(node.arguments); |
1661 Selector selector = elements.getSelector(node); | 1427 Selector selector = elements.getSelector(node); |
1662 TypeMask mask = elements.getTypeMask(node); | 1428 TypeMask mask = elements.getTypeMask(node); |
1663 return handleStaticSend(node, selector, mask, function, arguments); | 1429 return handleStaticSend(node, selector, mask, function, arguments); |
1664 } | 1430 } |
1665 | 1431 |
1666 /// Handle an static invocation of an unresolved target or with incompatible | 1432 /// Handle an static invocation of an unresolved target or with incompatible |
1667 /// arguments to a resolved target. | 1433 /// arguments to a resolved target. |
1668 T handleInvalidStaticInvoke(ast.Send node) { | 1434 T handleInvalidStaticInvoke(ast.Send node) { |
1669 analyzeArguments(node.arguments); | 1435 analyzeArguments(node.arguments); |
1670 return types.dynamicType; | 1436 return types.dynamicType; |
1671 } | 1437 } |
1672 | 1438 |
1673 @override | 1439 @override |
1674 T visitStaticFieldInvoke( | 1440 T visitStaticFieldInvoke(ast.Send node, FieldElement field, |
1675 ast.Send node, | 1441 ast.NodeList arguments, CallStructure callStructure, _) { |
1676 FieldElement field, | |
1677 ast.NodeList arguments, | |
1678 CallStructure callStructure, | |
1679 _) { | |
1680 return handleStaticFieldOrGetterInvoke(node, field); | 1442 return handleStaticFieldOrGetterInvoke(node, field); |
1681 } | 1443 } |
1682 | 1444 |
1683 @override | 1445 @override |
1684 T visitStaticFunctionInvoke( | 1446 T visitStaticFunctionInvoke(ast.Send node, MethodElement function, |
1685 ast.Send node, | 1447 ast.NodeList arguments, CallStructure callStructure, _) { |
1686 MethodElement function, | |
1687 ast.NodeList arguments, | |
1688 CallStructure callStructure, | |
1689 _) { | |
1690 return handleStaticFunctionInvoke(node, function); | 1448 return handleStaticFunctionInvoke(node, function); |
1691 } | 1449 } |
1692 | 1450 |
1693 @override | 1451 @override |
1694 T visitStaticFunctionIncompatibleInvoke( | 1452 T visitStaticFunctionIncompatibleInvoke(ast.Send node, MethodElement function, |
1695 ast.Send node, | 1453 ast.NodeList arguments, CallStructure callStructure, _) { |
1696 MethodElement function, | |
1697 ast.NodeList arguments, | |
1698 CallStructure callStructure, | |
1699 _) { | |
1700 return handleInvalidStaticInvoke(node); | 1454 return handleInvalidStaticInvoke(node); |
1701 } | 1455 } |
1702 | 1456 |
1703 @override | 1457 @override |
1704 T visitStaticGetterInvoke( | 1458 T visitStaticGetterInvoke(ast.Send node, FunctionElement getter, |
1705 ast.Send node, | 1459 ast.NodeList arguments, CallStructure callStructure, _) { |
1706 FunctionElement getter, | |
1707 ast.NodeList arguments, | |
1708 CallStructure callStructure, | |
1709 _) { | |
1710 return handleStaticFieldOrGetterInvoke(node, getter); | 1460 return handleStaticFieldOrGetterInvoke(node, getter); |
1711 } | 1461 } |
1712 | 1462 |
1713 @override | 1463 @override |
1714 T visitTopLevelFieldInvoke( | 1464 T visitTopLevelFieldInvoke(ast.Send node, FieldElement field, |
1715 ast.Send node, | 1465 ast.NodeList arguments, CallStructure callStructure, _) { |
1716 FieldElement field, | |
1717 ast.NodeList arguments, | |
1718 CallStructure callStructure, | |
1719 _) { | |
1720 return handleStaticFieldOrGetterInvoke(node, field); | 1466 return handleStaticFieldOrGetterInvoke(node, field); |
1721 } | 1467 } |
1722 | 1468 |
1723 @override | 1469 @override |
1724 T visitTopLevelFunctionInvoke( | 1470 T visitTopLevelFunctionInvoke(ast.Send node, MethodElement function, |
1725 ast.Send node, | 1471 ast.NodeList arguments, CallStructure callStructure, _) { |
1726 MethodElement function, | |
1727 ast.NodeList arguments, | |
1728 CallStructure callStructure, | |
1729 _) { | |
1730 return handleStaticFunctionInvoke(node, function); | 1472 return handleStaticFunctionInvoke(node, function); |
1731 } | 1473 } |
1732 | 1474 |
1733 @override | 1475 @override |
1734 T visitTopLevelFunctionIncompatibleInvoke( | 1476 T visitTopLevelFunctionIncompatibleInvoke( |
1735 ast.Send node, | 1477 ast.Send node, |
1736 MethodElement function, | 1478 MethodElement function, |
1737 ast.NodeList arguments, | 1479 ast.NodeList arguments, |
1738 CallStructure callStructure, | 1480 CallStructure callStructure, |
1739 _) { | 1481 _) { |
1740 return handleInvalidStaticInvoke(node); | 1482 return handleInvalidStaticInvoke(node); |
1741 } | 1483 } |
1742 | 1484 |
1743 @override | 1485 @override |
1744 T visitTopLevelGetterInvoke( | 1486 T visitTopLevelGetterInvoke(ast.Send node, FunctionElement getter, |
1745 ast.Send node, | 1487 ast.NodeList arguments, CallStructure callStructure, _) { |
1746 FunctionElement getter, | |
1747 ast.NodeList arguments, | |
1748 CallStructure callStructure, | |
1749 _) { | |
1750 return handleStaticFieldOrGetterInvoke(node, getter); | 1488 return handleStaticFieldOrGetterInvoke(node, getter); |
1751 } | 1489 } |
1752 | 1490 |
1753 @override | 1491 @override |
1754 T visitStaticSetterInvoke( | 1492 T visitStaticSetterInvoke(ast.Send node, MethodElement setter, |
1755 ast.Send node, | 1493 ast.NodeList arguments, CallStructure callStructure, _) { |
1756 MethodElement setter, | |
1757 ast.NodeList arguments, | |
1758 CallStructure callStructure, | |
1759 _) { | |
1760 return handleInvalidStaticInvoke(node); | 1494 return handleInvalidStaticInvoke(node); |
1761 } | 1495 } |
1762 | 1496 |
1763 @override | 1497 @override |
1764 T visitTopLevelSetterInvoke( | 1498 T visitTopLevelSetterInvoke(ast.Send node, MethodElement setter, |
1765 ast.Send node, | 1499 ast.NodeList arguments, CallStructure callStructure, _) { |
1766 MethodElement setter, | |
1767 ast.NodeList arguments, | |
1768 CallStructure callStructure, | |
1769 _) { | |
1770 return handleInvalidStaticInvoke(node); | 1500 return handleInvalidStaticInvoke(node); |
1771 } | 1501 } |
1772 | 1502 |
1773 @override | 1503 @override |
1774 T visitUnresolvedInvoke( | 1504 T visitUnresolvedInvoke(ast.Send node, Element element, |
1775 ast.Send node, | 1505 ast.NodeList arguments, Selector selector, _) { |
1776 Element element, | |
1777 ast.NodeList arguments, | |
1778 Selector selector, | |
1779 _) { | |
1780 return handleInvalidStaticInvoke(node); | 1506 return handleInvalidStaticInvoke(node); |
1781 } | 1507 } |
1782 | 1508 |
1783 T handleForeignSend(ast.Send node, Element element) { | 1509 T handleForeignSend(ast.Send node, Element element) { |
1784 ArgumentsTypes arguments = analyzeArguments(node.arguments); | 1510 ArgumentsTypes arguments = analyzeArguments(node.arguments); |
1785 Selector selector = elements.getSelector(node); | 1511 Selector selector = elements.getSelector(node); |
1786 TypeMask mask = elements.getTypeMask(node); | 1512 TypeMask mask = elements.getTypeMask(node); |
1787 String name = element.name; | 1513 String name = element.name; |
1788 handleStaticSend(node, selector, mask, element, arguments); | 1514 handleStaticSend(node, selector, mask, element, arguments); |
1789 if (name == 'JS' || name == 'JS_EMBEDDED_GLOBAL' || name == 'JS_BUILTIN') { | 1515 if (name == 'JS' || name == 'JS_EMBEDDED_GLOBAL' || name == 'JS_BUILTIN') { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1839 } | 1565 } |
1840 | 1566 |
1841 /// Closurize a static or top level function. | 1567 /// Closurize a static or top level function. |
1842 T handleStaticFunctionGet(ast.Send node, MethodElement function) { | 1568 T handleStaticFunctionGet(ast.Send node, MethodElement function) { |
1843 Selector selector = elements.getSelector(node); | 1569 Selector selector = elements.getSelector(node); |
1844 TypeMask mask = elements.getTypeMask(node); | 1570 TypeMask mask = elements.getTypeMask(node); |
1845 return handleStaticSend(node, selector, mask, function, null); | 1571 return handleStaticSend(node, selector, mask, function, null); |
1846 } | 1572 } |
1847 | 1573 |
1848 @override | 1574 @override |
1849 T visitDynamicPropertyGet( | 1575 T visitDynamicPropertyGet(ast.Send node, ast.Node receiver, Name name, _) { |
1850 ast.Send node, | |
1851 ast.Node receiver, | |
1852 Name name, | |
1853 _) { | |
1854 return handleDynamicGet(node); | 1576 return handleDynamicGet(node); |
1855 } | 1577 } |
1856 | 1578 |
1857 @override | 1579 @override |
1858 T visitIfNotNullDynamicPropertyGet( | 1580 T visitIfNotNullDynamicPropertyGet( |
1859 ast.Send node, | 1581 ast.Send node, ast.Node receiver, Name name, _) { |
1860 ast.Node receiver, | |
1861 Name name, | |
1862 _) { | |
1863 return handleDynamicGet(node); | 1582 return handleDynamicGet(node); |
1864 } | 1583 } |
1865 | 1584 |
1866 @override | 1585 @override |
1867 T visitLocalVariableGet( | 1586 T visitLocalVariableGet(ast.Send node, LocalVariableElement variable, _) { |
1868 ast.Send node, | |
1869 LocalVariableElement variable, | |
1870 _) { | |
1871 return handleLocalGet(node, variable); | 1587 return handleLocalGet(node, variable); |
1872 } | 1588 } |
1873 | 1589 |
1874 @override | 1590 @override |
1875 T visitParameterGet( | 1591 T visitParameterGet(ast.Send node, ParameterElement parameter, _) { |
1876 ast.Send node, | |
1877 ParameterElement parameter, | |
1878 _) { | |
1879 return handleLocalGet(node, parameter); | 1592 return handleLocalGet(node, parameter); |
1880 } | 1593 } |
1881 | 1594 |
1882 @override | 1595 @override |
1883 T visitLocalFunctionGet( | 1596 T visitLocalFunctionGet(ast.Send node, LocalFunctionElement function, _) { |
1884 ast.Send node, | |
1885 LocalFunctionElement function, | |
1886 _) { | |
1887 return handleLocalGet(node, function); | 1597 return handleLocalGet(node, function); |
1888 } | 1598 } |
1889 | 1599 |
1890 @override | 1600 @override |
1891 T visitStaticFieldGet( | 1601 T visitStaticFieldGet(ast.Send node, FieldElement field, _) { |
1892 ast.Send node, | |
1893 FieldElement field, | |
1894 _) { | |
1895 return handleStaticFieldGet(node, field); | 1602 return handleStaticFieldGet(node, field); |
1896 } | 1603 } |
1897 | 1604 |
1898 @override | 1605 @override |
1899 T visitStaticFunctionGet( | 1606 T visitStaticFunctionGet(ast.Send node, MethodElement function, _) { |
1900 ast.Send node, | |
1901 MethodElement function, | |
1902 _) { | |
1903 return handleStaticFunctionGet(node, function); | 1607 return handleStaticFunctionGet(node, function); |
1904 } | 1608 } |
1905 | 1609 |
1906 @override | 1610 @override |
1907 T visitStaticGetterGet( | 1611 T visitStaticGetterGet(ast.Send node, FunctionElement getter, _) { |
1908 ast.Send node, | |
1909 FunctionElement getter, | |
1910 _) { | |
1911 return handleStaticGetterGet(node, getter); | 1612 return handleStaticGetterGet(node, getter); |
1912 } | 1613 } |
1913 | 1614 |
1914 @override | 1615 @override |
1915 T visitThisPropertyGet( | 1616 T visitThisPropertyGet(ast.Send node, Name name, _) { |
1916 ast.Send node, | |
1917 Name name, | |
1918 _) { | |
1919 return handleDynamicGet(node); | 1617 return handleDynamicGet(node); |
1920 } | 1618 } |
1921 | 1619 |
1922 @override | 1620 @override |
1923 T visitTopLevelFieldGet( | 1621 T visitTopLevelFieldGet(ast.Send node, FieldElement field, _) { |
1924 ast.Send node, | |
1925 FieldElement field, | |
1926 _) { | |
1927 return handleStaticFieldGet(node, field); | 1622 return handleStaticFieldGet(node, field); |
1928 } | 1623 } |
1929 | 1624 |
1930 @override | 1625 @override |
1931 T visitTopLevelFunctionGet( | 1626 T visitTopLevelFunctionGet(ast.Send node, MethodElement function, _) { |
1932 ast.Send node, | |
1933 MethodElement function, | |
1934 _) { | |
1935 return handleStaticFunctionGet(node, function); | 1627 return handleStaticFunctionGet(node, function); |
1936 } | 1628 } |
1937 | 1629 |
1938 @override | 1630 @override |
1939 T visitTopLevelGetterGet( | 1631 T visitTopLevelGetterGet(ast.Send node, FunctionElement getter, _) { |
1940 ast.Send node, | |
1941 FunctionElement getter, | |
1942 _) { | |
1943 return handleStaticGetterGet(node, getter); | 1632 return handleStaticGetterGet(node, getter); |
1944 } | 1633 } |
1945 | 1634 |
1946 @override | 1635 @override |
1947 T visitStaticSetterGet( | 1636 T visitStaticSetterGet(ast.Send node, MethodElement setter, _) { |
1948 ast.Send node, | |
1949 MethodElement setter, | |
1950 _) { | |
1951 return types.dynamicType; | 1637 return types.dynamicType; |
1952 } | 1638 } |
1953 | 1639 |
1954 @override | 1640 @override |
1955 T visitTopLevelSetterGet( | 1641 T visitTopLevelSetterGet(ast.Send node, MethodElement setter, _) { |
1956 ast.Send node, | |
1957 MethodElement setter, | |
1958 _) { | |
1959 return types.dynamicType; | 1642 return types.dynamicType; |
1960 } | 1643 } |
1961 | 1644 |
1962 @override | 1645 @override |
1963 T visitUnresolvedGet( | 1646 T visitUnresolvedGet(ast.Send node, Element element, _) { |
1964 ast.Send node, | |
1965 Element element, | |
1966 _) { | |
1967 return types.dynamicType; | 1647 return types.dynamicType; |
1968 } | 1648 } |
1969 | 1649 |
1970 /// Handle .call invocation on [closure]. | 1650 /// Handle .call invocation on [closure]. |
1971 T handleCallInvoke(ast.Send node, T closure) { | 1651 T handleCallInvoke(ast.Send node, T closure) { |
1972 ArgumentsTypes arguments = analyzeArguments(node.arguments); | 1652 ArgumentsTypes arguments = analyzeArguments(node.arguments); |
1973 Selector selector = elements.getSelector(node); | 1653 Selector selector = elements.getSelector(node); |
1974 TypeMask mask = elements.getTypeMask(node); | 1654 TypeMask mask = elements.getTypeMask(node); |
1975 return inferrer.registerCalledClosure( | 1655 return inferrer.registerCalledClosure(node, selector, mask, closure, |
1976 node, selector, mask, closure, outermostElement, arguments, | 1656 outermostElement, arguments, sideEffects, inLoop); |
1977 sideEffects, inLoop); | |
1978 } | 1657 } |
1979 | 1658 |
1980 @override | 1659 @override |
1981 T visitExpressionInvoke( | 1660 T visitExpressionInvoke(ast.Send node, ast.Node expression, |
1982 ast.Send node, | 1661 ast.NodeList arguments, CallStructure callStructure, _) { |
1983 ast.Node expression, | |
1984 ast.NodeList arguments, | |
1985 CallStructure callStructure, | |
1986 _) { | |
1987 return handleCallInvoke(node, expression.accept(this)); | 1662 return handleCallInvoke(node, expression.accept(this)); |
1988 } | 1663 } |
1989 | 1664 |
1990 @override | 1665 @override |
1991 T visitThisInvoke( | 1666 T visitThisInvoke( |
1992 ast.Send node, | 1667 ast.Send node, ast.NodeList arguments, CallStructure callStructure, _) { |
1993 ast.NodeList arguments, | |
1994 CallStructure callStructure, | |
1995 _) { | |
1996 return handleCallInvoke(node, thisType); | 1668 return handleCallInvoke(node, thisType); |
1997 } | 1669 } |
1998 | 1670 |
1999 @override | 1671 @override |
2000 T visitParameterInvoke( | 1672 T visitParameterInvoke(ast.Send node, ParameterElement parameter, |
2001 ast.Send node, | 1673 ast.NodeList arguments, CallStructure callStructure, _) { |
2002 ParameterElement parameter, | |
2003 ast.NodeList arguments, | |
2004 CallStructure callStructure, | |
2005 _) { | |
2006 return handleCallInvoke(node, locals.use(parameter)); | 1674 return handleCallInvoke(node, locals.use(parameter)); |
2007 } | 1675 } |
2008 | 1676 |
2009 @override | 1677 @override |
2010 T visitLocalVariableInvoke( | 1678 T visitLocalVariableInvoke(ast.Send node, LocalVariableElement variable, |
2011 ast.Send node, | 1679 ast.NodeList arguments, CallStructure callStructure, _) { |
2012 LocalVariableElement variable, | |
2013 ast.NodeList arguments, | |
2014 CallStructure callStructure, | |
2015 _) { | |
2016 return handleCallInvoke(node, locals.use(variable)); | 1680 return handleCallInvoke(node, locals.use(variable)); |
2017 } | 1681 } |
2018 | 1682 |
2019 @override | 1683 @override |
2020 T visitLocalFunctionInvoke( | 1684 T visitLocalFunctionInvoke(ast.Send node, LocalFunctionElement function, |
2021 ast.Send node, | 1685 ast.NodeList arguments, CallStructure callStructure, _) { |
2022 LocalFunctionElement function, | |
2023 ast.NodeList arguments, | |
2024 CallStructure callStructure, | |
2025 _) { | |
2026 ArgumentsTypes argumentTypes = analyzeArguments(node.arguments); | 1686 ArgumentsTypes argumentTypes = analyzeArguments(node.arguments); |
2027 Selector selector = elements.getSelector(node); | 1687 Selector selector = elements.getSelector(node); |
2028 TypeMask mask = elements.getTypeMask(node); | 1688 TypeMask mask = elements.getTypeMask(node); |
2029 // This only works for function statements. We need a | 1689 // This only works for function statements. We need a |
2030 // more sophisticated type system with function types to support | 1690 // more sophisticated type system with function types to support |
2031 // more. | 1691 // more. |
2032 return inferrer.registerCalledElement( | 1692 return inferrer.registerCalledElement(node, selector, mask, |
2033 node, selector, mask, outermostElement, function, argumentTypes, | 1693 outermostElement, function, argumentTypes, sideEffects, inLoop); |
2034 sideEffects, inLoop); | |
2035 } | 1694 } |
2036 | 1695 |
2037 @override | 1696 @override |
2038 T visitLocalFunctionIncompatibleInvoke( | 1697 T visitLocalFunctionIncompatibleInvoke( |
2039 ast.Send node, | 1698 ast.Send node, |
2040 LocalFunctionElement function, | 1699 LocalFunctionElement function, |
2041 ast.NodeList arguments, | 1700 ast.NodeList arguments, |
2042 CallStructure callStructure, | 1701 CallStructure callStructure, |
2043 _) { | 1702 _) { |
2044 analyzeArguments(node.arguments); | 1703 analyzeArguments(node.arguments); |
2045 return types.dynamicType; | 1704 return types.dynamicType; |
2046 } | 1705 } |
2047 | 1706 |
2048 T handleStaticSend(ast.Node node, | 1707 T handleStaticSend(ast.Node node, Selector selector, TypeMask mask, |
2049 Selector selector, | 1708 Element element, ArgumentsTypes arguments) { |
2050 TypeMask mask, | |
2051 Element element, | |
2052 ArgumentsTypes arguments) { | |
2053 assert(!element.isFactoryConstructor || | 1709 assert(!element.isFactoryConstructor || |
2054 !(element as ConstructorElement).isRedirectingFactory); | 1710 !(element as ConstructorElement).isRedirectingFactory); |
2055 // Erroneous elements may be unresolved, for example missing getters. | 1711 // Erroneous elements may be unresolved, for example missing getters. |
2056 if (Elements.isUnresolved(element)) return types.dynamicType; | 1712 if (Elements.isUnresolved(element)) return types.dynamicType; |
2057 // TODO(herhut): should we follow redirecting constructors here? We would | 1713 // TODO(herhut): should we follow redirecting constructors here? We would |
2058 // need to pay attention if the constructor is pointing to an erroneous | 1714 // need to pay attention if the constructor is pointing to an erroneous |
2059 // element. | 1715 // element. |
2060 return inferrer.registerCalledElement( | 1716 return inferrer.registerCalledElement(node, selector, mask, |
2061 node, selector, mask, outermostElement, element, arguments, | 1717 outermostElement, element, arguments, sideEffects, inLoop); |
2062 sideEffects, inLoop); | |
2063 } | 1718 } |
2064 | 1719 |
2065 T handleDynamicSend(ast.Node node, | 1720 T handleDynamicSend(ast.Node node, Selector selector, TypeMask mask, |
2066 Selector selector, | 1721 T receiverType, ArgumentsTypes arguments) { |
2067 TypeMask mask, | |
2068 T receiverType, | |
2069 ArgumentsTypes arguments) { | |
2070 assert(receiverType != null); | 1722 assert(receiverType != null); |
2071 if (types.selectorNeedsUpdate(receiverType, mask)) { | 1723 if (types.selectorNeedsUpdate(receiverType, mask)) { |
2072 mask = receiverType == types.dynamicType | 1724 mask = receiverType == types.dynamicType |
2073 ? null | 1725 ? null |
2074 : types.newTypedSelector(receiverType, mask); | 1726 : types.newTypedSelector(receiverType, mask); |
2075 inferrer.updateSelectorInTree(analyzedElement, node, selector, mask); | 1727 inferrer.updateSelectorInTree(analyzedElement, node, selector, mask); |
2076 } | 1728 } |
2077 | 1729 |
2078 // If the receiver of the call is a local, we may know more about | 1730 // If the receiver of the call is a local, we may know more about |
2079 // its type by refining it with the potential targets of the | 1731 // its type by refining it with the potential targets of the |
2080 // calls. | 1732 // calls. |
2081 ast.Send send = node.asSend(); | 1733 ast.Send send = node.asSend(); |
2082 if (send != null) { | 1734 if (send != null) { |
2083 ast.Node receiver = send.receiver; | 1735 ast.Node receiver = send.receiver; |
2084 if (receiver != null) { | 1736 if (receiver != null) { |
2085 Element element = elements[receiver]; | 1737 Element element = elements[receiver]; |
2086 if (Elements.isLocal(element) && !capturedVariables.contains(element)) { | 1738 if (Elements.isLocal(element) && !capturedVariables.contains(element)) { |
2087 T refinedType = types.refineReceiver( | 1739 T refinedType = types.refineReceiver( |
2088 selector, mask, receiverType, send.isConditional); | 1740 selector, mask, receiverType, send.isConditional); |
2089 locals.update(element, refinedType, node); | 1741 locals.update(element, refinedType, node); |
2090 } | 1742 } |
2091 } | 1743 } |
2092 } | 1744 } |
2093 | 1745 |
2094 return inferrer.registerCalledSelector( | 1746 return inferrer.registerCalledSelector(node, selector, mask, receiverType, |
2095 node, selector, mask, receiverType, outermostElement, arguments, | 1747 outermostElement, arguments, sideEffects, inLoop); |
2096 sideEffects, inLoop); | |
2097 } | 1748 } |
2098 | 1749 |
2099 T handleDynamicInvoke(ast.Send node) { | 1750 T handleDynamicInvoke(ast.Send node) { |
2100 return _handleDynamicSend(node); | 1751 return _handleDynamicSend(node); |
2101 } | 1752 } |
2102 | 1753 |
2103 T handleDynamicGet(ast.Send node) { | 1754 T handleDynamicGet(ast.Send node) { |
2104 return _handleDynamicSend(node); | 1755 return _handleDynamicSend(node); |
2105 } | 1756 } |
2106 | 1757 |
(...skipping 11 matching lines...) Expand all Loading... |
2118 isCallOnThis = isThisOrSuper(receiver); | 1769 isCallOnThis = isThisOrSuper(receiver); |
2119 receiverType = visit(receiver); | 1770 receiverType = visit(receiver); |
2120 } | 1771 } |
2121 | 1772 |
2122 Selector selector = elements.getSelector(node); | 1773 Selector selector = elements.getSelector(node); |
2123 TypeMask mask = elements.getTypeMask(node); | 1774 TypeMask mask = elements.getTypeMask(node); |
2124 if (!isThisExposed && isCallOnThis) { | 1775 if (!isThisExposed && isCallOnThis) { |
2125 checkIfExposesThis(selector, types.newTypedSelector(receiverType, mask)); | 1776 checkIfExposesThis(selector, types.newTypedSelector(receiverType, mask)); |
2126 } | 1777 } |
2127 | 1778 |
2128 ArgumentsTypes arguments = node.isPropertyAccess | 1779 ArgumentsTypes arguments = |
2129 ? null | 1780 node.isPropertyAccess ? null : analyzeArguments(node.arguments); |
2130 : analyzeArguments(node.arguments); | 1781 if (selector.name == '==' || selector.name == '!=') { |
2131 if (selector.name == '==' || | |
2132 selector.name == '!=') { | |
2133 if (types.isNull(receiverType)) { | 1782 if (types.isNull(receiverType)) { |
2134 potentiallyAddNullCheck(node, node.arguments.head); | 1783 potentiallyAddNullCheck(node, node.arguments.head); |
2135 return types.boolType; | 1784 return types.boolType; |
2136 } else if (types.isNull(arguments.positional[0])) { | 1785 } else if (types.isNull(arguments.positional[0])) { |
2137 potentiallyAddNullCheck(node, node.receiver); | 1786 potentiallyAddNullCheck(node, node.receiver); |
2138 return types.boolType; | 1787 return types.boolType; |
2139 } | 1788 } |
2140 } | 1789 } |
2141 return handleDynamicSend(node, selector, mask, receiverType, arguments); | 1790 return handleDynamicSend(node, selector, mask, receiverType, arguments); |
2142 } | 1791 } |
(...skipping 23 matching lines...) Expand all Loading... |
2166 signature.forEachOptionalParameter((ParameterElement element) { | 1815 signature.forEachOptionalParameter((ParameterElement element) { |
2167 named[element.name] = locals.use(element); | 1816 named[element.name] = locals.use(element); |
2168 }); | 1817 }); |
2169 } else { | 1818 } else { |
2170 signature.forEachOptionalParameter((ParameterElement element) { | 1819 signature.forEachOptionalParameter((ParameterElement element) { |
2171 unnamed.add(locals.use(element)); | 1820 unnamed.add(locals.use(element)); |
2172 }); | 1821 }); |
2173 } | 1822 } |
2174 | 1823 |
2175 ArgumentsTypes arguments = new ArgumentsTypes<T>(unnamed, named); | 1824 ArgumentsTypes arguments = new ArgumentsTypes<T>(unnamed, named); |
2176 return inferrer.registerCalledElement(node, | 1825 return inferrer.registerCalledElement(node, null, null, outermostElement, |
2177 null, | 1826 element, arguments, sideEffects, inLoop); |
2178 null, | |
2179 outermostElement, | |
2180 element, | |
2181 arguments, | |
2182 sideEffects, | |
2183 inLoop); | |
2184 } | 1827 } |
2185 | 1828 |
2186 T visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { | 1829 T visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { |
2187 Element element = elements.getRedirectingTargetConstructor(node); | 1830 Element element = elements.getRedirectingTargetConstructor(node); |
2188 if (Elements.isMalformed(element)) { | 1831 if (Elements.isMalformed(element)) { |
2189 recordReturnType(types.dynamicType); | 1832 recordReturnType(types.dynamicType); |
2190 } else { | 1833 } else { |
2191 // We don't create a selector for redirecting factories, and | 1834 // We don't create a selector for redirecting factories, and |
2192 // the send is just a property access. Therefore we must | 1835 // the send is just a property access. Therefore we must |
2193 // manually create the [ArgumentsTypes] of the call, and | 1836 // manually create the [ArgumentsTypes] of the call, and |
2194 // manually register [analyzedElement] as a caller of [element]. | 1837 // manually register [analyzedElement] as a caller of [element]. |
2195 T mask = synthesizeForwardingCall(node.constructorReference, element); | 1838 T mask = synthesizeForwardingCall(node.constructorReference, element); |
2196 recordReturnType(mask); | 1839 recordReturnType(mask); |
2197 } | 1840 } |
2198 locals.seenReturnOrThrow = true; | 1841 locals.seenReturnOrThrow = true; |
2199 return null; | 1842 return null; |
2200 } | 1843 } |
2201 | 1844 |
2202 T visitReturn(ast.Return node) { | 1845 T visitReturn(ast.Return node) { |
2203 ast.Node expression = node.expression; | 1846 ast.Node expression = node.expression; |
2204 recordReturnType(expression == null | 1847 recordReturnType( |
2205 ? types.nullType | 1848 expression == null ? types.nullType : expression.accept(this)); |
2206 : expression.accept(this)); | |
2207 locals.seenReturnOrThrow = true; | 1849 locals.seenReturnOrThrow = true; |
2208 return null; | 1850 return null; |
2209 } | 1851 } |
2210 | 1852 |
2211 T handleForInLoop(ast.ForIn node, | 1853 T handleForInLoop(ast.ForIn node, T iteratorType, Selector currentSelector, |
2212 T iteratorType, | 1854 TypeMask currentMask, Selector moveNextSelector, TypeMask moveNextMask) { |
2213 Selector currentSelector, | 1855 handleDynamicSend(node, moveNextSelector, moveNextMask, iteratorType, |
2214 TypeMask currentMask, | |
2215 Selector moveNextSelector, | |
2216 TypeMask moveNextMask) { | |
2217 handleDynamicSend( | |
2218 node, moveNextSelector, moveNextMask, iteratorType, | |
2219 new ArgumentsTypes<T>.empty()); | 1856 new ArgumentsTypes<T>.empty()); |
2220 T currentType = handleDynamicSend( | 1857 T currentType = handleDynamicSend(node, currentSelector, currentMask, |
2221 node, currentSelector, currentMask, iteratorType, | 1858 iteratorType, new ArgumentsTypes<T>.empty()); |
2222 new ArgumentsTypes<T>.empty()); | |
2223 | 1859 |
2224 if (node.expression.isThis()) { | 1860 if (node.expression.isThis()) { |
2225 // Any reasonable implementation of an iterator would expose | 1861 // Any reasonable implementation of an iterator would expose |
2226 // this, so we play it safe and assume it will. | 1862 // this, so we play it safe and assume it will. |
2227 isThisExposed = true; | 1863 isThisExposed = true; |
2228 } | 1864 } |
2229 | 1865 |
2230 ast.Node identifier = node.declaredIdentifier; | 1866 ast.Node identifier = node.declaredIdentifier; |
2231 Element element = elements.getForInVariable(node); | 1867 Element element = elements.getForInVariable(node); |
2232 Selector selector = elements.getSelector(identifier); | 1868 Selector selector = elements.getSelector(identifier); |
2233 TypeMask mask = elements.getTypeMask(identifier); | 1869 TypeMask mask = elements.getTypeMask(identifier); |
2234 | 1870 |
2235 T receiverType; | 1871 T receiverType; |
2236 if (element != null && element.isInstanceMember) { | 1872 if (element != null && element.isInstanceMember) { |
2237 receiverType = thisType; | 1873 receiverType = thisType; |
2238 } else { | 1874 } else { |
2239 receiverType = types.dynamicType; | 1875 receiverType = types.dynamicType; |
2240 } | 1876 } |
2241 | 1877 |
2242 handlePlainAssignment(identifier, element, selector, mask, | 1878 handlePlainAssignment(identifier, element, selector, mask, receiverType, |
2243 receiverType, currentType, | 1879 currentType, node.expression); |
2244 node.expression); | |
2245 return handleLoop(node, () { | 1880 return handleLoop(node, () { |
2246 visit(node.body); | 1881 visit(node.body); |
2247 }); | 1882 }); |
2248 } | 1883 } |
2249 | 1884 |
2250 T visitAsyncForIn(ast.AsyncForIn node) { | 1885 T visitAsyncForIn(ast.AsyncForIn node) { |
2251 T expressionType = visit(node.expression); | 1886 T expressionType = visit(node.expression); |
2252 | 1887 |
2253 Selector currentSelector = Selectors.current; | 1888 Selector currentSelector = Selectors.current; |
2254 TypeMask currentMask = elements.getCurrentTypeMask(node); | 1889 TypeMask currentMask = elements.getCurrentTypeMask(node); |
2255 Selector moveNextSelector = Selectors.moveNext; | 1890 Selector moveNextSelector = Selectors.moveNext; |
2256 TypeMask moveNextMask = elements.getMoveNextTypeMask(node); | 1891 TypeMask moveNextMask = elements.getMoveNextTypeMask(node); |
2257 | 1892 |
2258 js.JavaScriptBackend backend = compiler.backend; | 1893 js.JavaScriptBackend backend = compiler.backend; |
2259 Element ctor = backend.helpers.streamIteratorConstructor; | 1894 Element ctor = backend.helpers.streamIteratorConstructor; |
2260 | 1895 |
2261 /// Synthesize a call to the [StreamIterator] constructor. | 1896 /// Synthesize a call to the [StreamIterator] constructor. |
2262 T iteratorType = handleStaticSend(node, null, null, ctor, | 1897 T iteratorType = handleStaticSend( |
2263 new ArgumentsTypes<T>([expressionType], | 1898 node, null, null, ctor, new ArgumentsTypes<T>([expressionType], null)); |
2264 null)); | |
2265 | 1899 |
2266 return handleForInLoop(node, iteratorType, currentSelector, currentMask, | 1900 return handleForInLoop(node, iteratorType, currentSelector, currentMask, |
2267 moveNextSelector, moveNextMask); | 1901 moveNextSelector, moveNextMask); |
2268 } | 1902 } |
2269 | 1903 |
2270 T visitSyncForIn(ast.SyncForIn node) { | 1904 T visitSyncForIn(ast.SyncForIn node) { |
2271 T expressionType = visit(node.expression); | 1905 T expressionType = visit(node.expression); |
2272 Selector iteratorSelector = Selectors.iterator; | 1906 Selector iteratorSelector = Selectors.iterator; |
2273 TypeMask iteratorMask = elements.getIteratorTypeMask(node); | 1907 TypeMask iteratorMask = elements.getIteratorTypeMask(node); |
2274 Selector currentSelector = Selectors.current; | 1908 Selector currentSelector = Selectors.current; |
2275 TypeMask currentMask = elements.getCurrentTypeMask(node); | 1909 TypeMask currentMask = elements.getCurrentTypeMask(node); |
2276 Selector moveNextSelector = Selectors.moveNext; | 1910 Selector moveNextSelector = Selectors.moveNext; |
2277 TypeMask moveNextMask = elements.getMoveNextTypeMask(node); | 1911 TypeMask moveNextMask = elements.getMoveNextTypeMask(node); |
2278 | 1912 |
2279 T iteratorType = handleDynamicSend( | 1913 T iteratorType = handleDynamicSend(node, iteratorSelector, iteratorMask, |
2280 node, iteratorSelector, iteratorMask, expressionType, | 1914 expressionType, new ArgumentsTypes<T>.empty()); |
2281 new ArgumentsTypes<T>.empty()); | |
2282 | 1915 |
2283 return handleForInLoop(node, iteratorType, currentSelector, currentMask, | 1916 return handleForInLoop(node, iteratorType, currentSelector, currentMask, |
2284 moveNextSelector, moveNextMask); | 1917 moveNextSelector, moveNextMask); |
2285 } | 1918 } |
2286 } | 1919 } |
OLD | NEW |