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

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

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 inferrer_visitor; 5 library inferrer_visitor;
6 6
7 import 'dart:collection' show 7 import 'dart:collection' show IterableMixin;
8 IterableMixin;
9 8
10 import '../common.dart'; 9 import '../common.dart';
11 import '../compiler.dart' show 10 import '../compiler.dart' show Compiler;
12 Compiler;
13 import '../constants/constant_system.dart'; 11 import '../constants/constant_system.dart';
14 import '../constants/expressions.dart'; 12 import '../constants/expressions.dart';
15 import '../dart_types.dart'; 13 import '../dart_types.dart';
16 import '../elements/elements.dart'; 14 import '../elements/elements.dart';
17 import '../resolution/operators.dart'; 15 import '../resolution/operators.dart';
18 import '../resolution/semantic_visitor.dart'; 16 import '../resolution/semantic_visitor.dart';
19 import '../resolution/tree_elements.dart' show 17 import '../resolution/tree_elements.dart' show TreeElements;
20 TreeElements;
21 import '../tree/tree.dart'; 18 import '../tree/tree.dart';
22 import '../types/types.dart' show 19 import '../types/types.dart' show TypeMask;
23 TypeMask; 20 import '../types/constants.dart' show computeTypeMask;
24 import '../types/constants.dart' show 21 import '../universe/call_structure.dart' show CallStructure;
25 computeTypeMask; 22 import '../universe/selector.dart' show Selector;
26 import '../universe/call_structure.dart' show
27 CallStructure;
28 import '../universe/selector.dart' show
29 Selector;
30 import '../util/util.dart'; 23 import '../util/util.dart';
31 import '../world.dart' show 24 import '../world.dart' show ClassWorld;
32 ClassWorld;
33 25
34 /** 26 /**
35 * The interface [InferrerVisitor] will use when working on types. 27 * The interface [InferrerVisitor] will use when working on types.
36 */ 28 */
37 abstract class TypeSystem<T> { 29 abstract class TypeSystem<T> {
38 T get dynamicType; 30 T get dynamicType;
39 T get nullType; 31 T get nullType;
40 T get intType; 32 T get intType;
41 T get uint31Type; 33 T get uint31Type;
42 T get uint32Type; 34 T get uint32Type;
(...skipping 17 matching lines...) Expand all
60 T stringLiteralType(DartString value); 52 T stringLiteralType(DartString value);
61 T boolLiteralType(LiteralBool value); 53 T boolLiteralType(LiteralBool value);
62 54
63 T nonNullSubtype(ClassElement type); 55 T nonNullSubtype(ClassElement type);
64 T nonNullSubclass(ClassElement type); 56 T nonNullSubclass(ClassElement type);
65 T nonNullExact(ClassElement type); 57 T nonNullExact(ClassElement type);
66 T nonNullEmpty(); 58 T nonNullEmpty();
67 bool isNull(T type); 59 bool isNull(T type);
68 TypeMask newTypedSelector(T receiver, TypeMask mask); 60 TypeMask newTypedSelector(T receiver, TypeMask mask);
69 61
70 T allocateList(T type, 62 T allocateList(T type, Node node, Element enclosing,
71 Node node, 63 [T elementType, int length]);
72 Element enclosing,
73 [T elementType, int length]);
74 64
75 T allocateMap(T type, Node node, Element element, [List<T> keyType, 65 T allocateMap(T type, Node node, Element element,
76 List<T> valueType]); 66 [List<T> keyType, List<T> valueType]);
77 67
78 T allocateClosure(Node node, Element element); 68 T allocateClosure(Node node, Element element);
79 69
80 /** 70 /**
81 * Returns the least upper bound between [firstType] and 71 * Returns the least upper bound between [firstType] and
82 * [secondType]. 72 * [secondType].
83 */ 73 */
84 T computeLUB(T firstType, T secondType); 74 T computeLUB(T firstType, T secondType);
85 75
86 /** 76 /**
(...skipping 12 matching lines...) Expand all
99 * Returns a new type that unions [firstInput] and [secondInput]. 89 * Returns a new type that unions [firstInput] and [secondInput].
100 */ 90 */
101 T allocateDiamondPhi(T firstInput, T secondInput); 91 T allocateDiamondPhi(T firstInput, T secondInput);
102 92
103 /** 93 /**
104 * Returns a new type for holding the potential types of [element]. 94 * Returns a new type for holding the potential types of [element].
105 * [inputType] is the first incoming type of the phi. 95 * [inputType] is the first incoming type of the phi.
106 */ 96 */
107 T allocatePhi(Node node, Local variable, T inputType); 97 T allocatePhi(Node node, Local variable, T inputType);
108 98
109
110 /** 99 /**
111 * Returns a new type for holding the potential types of [element]. 100 * Returns a new type for holding the potential types of [element].
112 * [inputType] is the first incoming type of the phi. [allocateLoopPhi] 101 * [inputType] is the first incoming type of the phi. [allocateLoopPhi]
113 * only differs from [allocatePhi] in that it allows the underlying 102 * only differs from [allocatePhi] in that it allows the underlying
114 * implementation of [TypeSystem] to differentiate Phi nodes due to loops 103 * implementation of [TypeSystem] to differentiate Phi nodes due to loops
115 * from other merging uses. 104 * from other merging uses.
116 */ 105 */
117 T allocateLoopPhi(Node node, Local variable, T inputType); 106 T allocateLoopPhi(Node node, Local variable, T inputType);
118 107
119 /** 108 /**
(...skipping 16 matching lines...) Expand all
136 bool selectorNeedsUpdate(T receiverType, TypeMask mask); 125 bool selectorNeedsUpdate(T receiverType, TypeMask mask);
137 126
138 /** 127 /**
139 * Returns a new receiver type for this [selector] applied to 128 * Returns a new receiver type for this [selector] applied to
140 * [receiverType]. 129 * [receiverType].
141 * 130 *
142 * The option [isConditional] is true when [selector] was seen in a 131 * The option [isConditional] is true when [selector] was seen in a
143 * conditional send (e.g. `a?.selector`), in which case the returned type may 132 * conditional send (e.g. `a?.selector`), in which case the returned type may
144 * be null. 133 * be null.
145 */ 134 */
146 T refineReceiver(Selector selector, 135 T refineReceiver(
147 TypeMask mask, 136 Selector selector, TypeMask mask, T receiverType, bool isConditional);
148 T receiverType,
149 bool isConditional);
150 137
151 /** 138 /**
152 * Returns the internal inferrer representation for [mask]. 139 * Returns the internal inferrer representation for [mask].
153 */ 140 */
154 T getConcreteTypeFor(TypeMask mask); 141 T getConcreteTypeFor(TypeMask mask);
155 } 142 }
156 143
157 /** 144 /**
158 * A variable scope holds types for variables. It has a link to a 145 * A variable scope holds types for variables. It has a link to a
159 * parent scope, but never changes the types in that parent. Instead, 146 * parent scope, but never changes the types in that parent. Instead,
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 variables = new Map<Local, T>(); 191 variables = new Map<Local, T>();
205 } 192 }
206 variables[variable] = mask; 193 variables[variable] = mask;
207 } 194 }
208 195
209 void forEachOwnLocal(void f(Local variable, T type)) { 196 void forEachOwnLocal(void f(Local variable, T type)) {
210 if (variables == null) return; 197 if (variables == null) return;
211 variables.forEach(f); 198 variables.forEach(f);
212 } 199 }
213 200
214 void forEachLocalUntilNode(Node node, 201 void forEachLocalUntilNode(Node node, void f(Local variable, T type),
215 void f(Local variable, T type), 202 [Setlet<Local> seenLocals]) {
216 [Setlet<Local> seenLocals]) {
217 if (seenLocals == null) seenLocals = new Setlet<Local>(); 203 if (seenLocals == null) seenLocals = new Setlet<Local>();
218 if (variables != null) { 204 if (variables != null) {
219 variables.forEach((variable, type) { 205 variables.forEach((variable, type) {
220 if (seenLocals.contains(variable)) return; 206 if (seenLocals.contains(variable)) return;
221 seenLocals.add(variable); 207 seenLocals.add(variable);
222 f(variable, type); 208 f(variable, type);
223 }); 209 });
224 } 210 }
225 if (block == node) return; 211 if (block == node) return;
226 if (parent != null) parent.forEachLocalUntilNode(node, f, seenLocals); 212 if (parent != null) parent.forEachLocalUntilNode(node, f, seenLocals);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 T readField(Element field) { 252 T readField(Element field) {
267 return fields == null ? null : fields[field]; 253 return fields == null ? null : fields[field];
268 } 254 }
269 255
270 void forEach(void f(Element element, T type)) { 256 void forEach(void f(Element element, T type)) {
271 if (fields == null) return; 257 if (fields == null) return;
272 fields.forEach(f); 258 fields.forEach(f);
273 } 259 }
274 260
275 void mergeDiamondFlow(FieldInitializationScope<T> thenScope, 261 void mergeDiamondFlow(FieldInitializationScope<T> thenScope,
276 FieldInitializationScope<T> elseScope) { 262 FieldInitializationScope<T> elseScope) {
277 // Quick bailout check. If [isThisExposed] is true, we know the 263 // Quick bailout check. If [isThisExposed] is true, we know the
278 // code following won't do anything. 264 // code following won't do anything.
279 if (isThisExposed) return; 265 if (isThisExposed) return;
280 if (elseScope == null || elseScope.fields == null) { 266 if (elseScope == null || elseScope.fields == null) {
281 elseScope = this; 267 elseScope = this;
282 } 268 }
283 269
284 thenScope.forEach((Element field, T type) { 270 thenScope.forEach((Element field, T type) {
285 T otherType = elseScope.readField(field); 271 T otherType = elseScope.readField(field);
286 if (otherType == null) return; 272 if (otherType == null) return;
287 updateField(field, types.allocateDiamondPhi(type, otherType)); 273 updateField(field, types.allocateDiamondPhi(type, otherType));
288 }); 274 });
289 isThisExposed = thenScope.isThisExposed || elseScope.isThisExposed; 275 isThisExposed = thenScope.isThisExposed || elseScope.isThisExposed;
290 } 276 }
291 } 277 }
292 278
293 /** 279 /**
294 * Placeholder for inferred arguments types on sends. 280 * Placeholder for inferred arguments types on sends.
295 */ 281 */
296 class ArgumentsTypes<T> extends IterableMixin<T> { 282 class ArgumentsTypes<T> extends IterableMixin<T> {
297 final List<T> positional; 283 final List<T> positional;
298 final Map<String, T> named; 284 final Map<String, T> named;
299 ArgumentsTypes(this.positional, named) 285 ArgumentsTypes(this.positional, named)
300 : this.named = (named == null || named.isEmpty) ? const {} : named { 286 : this.named = (named == null || named.isEmpty) ? const {} : named {
301 assert(this.positional.every((T type) => type != null)); 287 assert(this.positional.every((T type) => type != null));
302 assert(this.named.values.every((T type) => type != null)); 288 assert(this.named.values.every((T type) => type != null));
303 } 289 }
304 290
305 ArgumentsTypes.empty() : positional = const [], named = const {}; 291 ArgumentsTypes.empty()
292 : positional = const [],
293 named = const {};
306 294
307 int get length => positional.length + named.length; 295 int get length => positional.length + named.length;
308 296
309 Iterator<T> get iterator => new ArgumentsTypesIterator(this); 297 Iterator<T> get iterator => new ArgumentsTypesIterator(this);
310 298
311 String toString() => "{ positional = $positional, named = $named }"; 299 String toString() => "{ positional = $positional, named = $named }";
312 300
313 bool operator==(other) { 301 bool operator ==(other) {
314 if (positional.length != other.positional.length) return false; 302 if (positional.length != other.positional.length) return false;
315 if (named.length != other.named.length) return false; 303 if (named.length != other.named.length) return false;
316 for (int i = 0; i < positional.length; i++) { 304 for (int i = 0; i < positional.length; i++) {
317 if (positional[i] != other.positional[i]) return false; 305 if (positional[i] != other.positional[i]) return false;
318 } 306 }
319 named.forEach((name, type) { 307 named.forEach((name, type) {
320 if (other.named[name] != type) return false; 308 if (other.named[name] != type) return false;
321 }); 309 });
322 return true; 310 return true;
323 } 311 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 347
360 bool moveNext() { 348 bool moveNext() {
361 if (_iteratePositional && positional.moveNext()) { 349 if (_iteratePositional && positional.moveNext()) {
362 return true; 350 return true;
363 } 351 }
364 _iteratePositional = false; 352 _iteratePositional = false;
365 return named.moveNext(); 353 return named.moveNext();
366 } 354 }
367 } 355 }
368 356
369
370 abstract class MinimalInferrerEngine<T> { 357 abstract class MinimalInferrerEngine<T> {
371 /** 358 /**
372 * Returns the type of [element]. 359 * Returns the type of [element].
373 */ 360 */
374 T typeOfElement(Element element); 361 T typeOfElement(Element element);
375 362
376 /** 363 /**
377 * Records that [node] sets non-final field [element] to be of type 364 * Records that [node] sets non-final field [element] to be of type
378 * [type]. 365 * [type].
379 */ 366 */
(...skipping 21 matching lines...) Expand all
401 final Map<Local, Element> captured; 388 final Map<Local, Element> captured;
402 final Map<Local, Element> capturedAndBoxed; 389 final Map<Local, Element> capturedAndBoxed;
403 final FieldInitializationScope<T> fieldScope; 390 final FieldInitializationScope<T> fieldScope;
404 LocalsHandler<T> tryBlock; 391 LocalsHandler<T> tryBlock;
405 bool seenReturnOrThrow = false; 392 bool seenReturnOrThrow = false;
406 bool seenBreakOrContinue = false; 393 bool seenBreakOrContinue = false;
407 394
408 bool get aborts { 395 bool get aborts {
409 return seenReturnOrThrow || seenBreakOrContinue; 396 return seenReturnOrThrow || seenBreakOrContinue;
410 } 397 }
398
411 bool get inTryBlock => tryBlock != null; 399 bool get inTryBlock => tryBlock != null;
412 400
413 LocalsHandler(this.inferrer, 401 LocalsHandler(this.inferrer, this.types, this.compiler, Node block,
414 this.types, 402 [this.fieldScope])
415 this.compiler,
416 Node block,
417 [this.fieldScope])
418 : locals = new VariableScope<T>(block), 403 : locals = new VariableScope<T>(block),
419 captured = new Map<Local, Element>(), 404 captured = new Map<Local, Element>(),
420 capturedAndBoxed = new Map<Local, Element>(), 405 capturedAndBoxed = new Map<Local, Element>(),
421 tryBlock = null; 406 tryBlock = null;
422 407
423 LocalsHandler.from(LocalsHandler<T> other, 408 LocalsHandler.from(LocalsHandler<T> other, Node block,
424 Node block, 409 {bool useOtherTryBlock: true})
425 {bool useOtherTryBlock: true})
426 : locals = new VariableScope<T>(block, other.locals), 410 : locals = new VariableScope<T>(block, other.locals),
427 fieldScope = new FieldInitializationScope<T>.from(other.fieldScope), 411 fieldScope = new FieldInitializationScope<T>.from(other.fieldScope),
428 captured = other.captured, 412 captured = other.captured,
429 capturedAndBoxed = other.capturedAndBoxed, 413 capturedAndBoxed = other.capturedAndBoxed,
430 types = other.types, 414 types = other.types,
431 inferrer = other.inferrer, 415 inferrer = other.inferrer,
432 compiler = other.compiler { 416 compiler = other.compiler {
433 tryBlock = useOtherTryBlock ? other.tryBlock : this; 417 tryBlock = useOtherTryBlock ? other.tryBlock : this;
434 } 418 }
435 419
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 } 456 }
473 updateLocal() { 457 updateLocal() {
474 T currentType = locals[local]; 458 T currentType = locals[local];
475 459
476 SendSet send = node != null ? node.asSendSet() : null; 460 SendSet send = node != null ? node.asSendSet() : null;
477 if (send != null && send.isIfNullAssignment && currentType != null) { 461 if (send != null && send.isIfNullAssignment && currentType != null) {
478 // If-null assignments may return either the new or the original value 462 // If-null assignments may return either the new or the original value
479 // narrowed to non-null. 463 // narrowed to non-null.
480 type = types.addPhiInput( 464 type = types.addPhiInput(
481 local, 465 local,
482 types.allocatePhi(locals.block, local, 466 types.allocatePhi(
483 types.narrowNotNull(currentType)), 467 locals.block, local, types.narrowNotNull(currentType)),
484 type); 468 type);
485 } 469 }
486 locals[local] = type; 470 locals[local] = type;
487 if (currentType != type) { 471 if (currentType != type) {
488 inferrer.recordLocalUpdate(local, type); 472 inferrer.recordLocalUpdate(local, type);
489 } 473 }
490 } 474 }
491 if (capturedAndBoxed.containsKey(local)) { 475 if (capturedAndBoxed.containsKey(local)) {
492 inferrer.recordTypeOfNonFinalField( 476 inferrer.recordTypeOfNonFinalField(node, capturedAndBoxed[local], type);
493 node, capturedAndBoxed[local], type);
494 } else if (inTryBlock) { 477 } else if (inTryBlock) {
495 // We don't know if an assignment in a try block 478 // We don't know if an assignment in a try block
496 // will be executed, so all assigments in that block are 479 // will be executed, so all assigments in that block are
497 // potential types after we have left it. We update the parent 480 // potential types after we have left it. We update the parent
498 // of the try block so that, at exit of the try block, we get 481 // of the try block so that, at exit of the try block, we get
499 // the right phi for it. 482 // the right phi for it.
500 T existing = tryBlock.locals.parent[local]; 483 T existing = tryBlock.locals.parent[local];
501 if (existing != null) { 484 if (existing != null) {
502 T phiType = types.allocatePhi(tryBlock.locals.block, local, existing); 485 T phiType = types.allocatePhi(tryBlock.locals.block, local, existing);
503 T inputType = types.addPhiInput(local, phiType, type); 486 T inputType = types.addPhiInput(local, phiType, type);
504 tryBlock.locals.parent[local] = inputType; 487 tryBlock.locals.parent[local] = inputType;
505 } 488 }
506 // Update the current handler unconditionnally with the new 489 // Update the current handler unconditionnally with the new
507 // type. 490 // type.
508 updateLocal(); 491 updateLocal();
509 } else { 492 } else {
510 updateLocal(); 493 updateLocal();
511 } 494 }
512 } 495 }
513 496
514 void setCaptured(Local local, Element field) { 497 void setCaptured(Local local, Element field) {
515 captured[local] = field; 498 captured[local] = field;
516 } 499 }
517 500
518 void setCapturedAndBoxed(Local local, Element field) { 501 void setCapturedAndBoxed(Local local, Element field) {
519 capturedAndBoxed[local] = field; 502 capturedAndBoxed[local] = field;
520 } 503 }
521 504
522 void mergeDiamondFlow(LocalsHandler<T> thenBranch, 505 void mergeDiamondFlow(
523 LocalsHandler<T> elseBranch) { 506 LocalsHandler<T> thenBranch, LocalsHandler<T> elseBranch) {
524 if (fieldScope != null && elseBranch != null) { 507 if (fieldScope != null && elseBranch != null) {
525 fieldScope.mergeDiamondFlow(thenBranch.fieldScope, elseBranch.fieldScope); 508 fieldScope.mergeDiamondFlow(thenBranch.fieldScope, elseBranch.fieldScope);
526 } 509 }
527 seenReturnOrThrow = thenBranch.seenReturnOrThrow 510 seenReturnOrThrow = thenBranch.seenReturnOrThrow &&
528 && elseBranch != null 511 elseBranch != null &&
529 && elseBranch.seenReturnOrThrow; 512 elseBranch.seenReturnOrThrow;
530 seenBreakOrContinue = thenBranch.seenBreakOrContinue 513 seenBreakOrContinue = thenBranch.seenBreakOrContinue &&
531 && elseBranch != null 514 elseBranch != null &&
532 && elseBranch.seenBreakOrContinue; 515 elseBranch.seenBreakOrContinue;
533 if (aborts) return; 516 if (aborts) return;
534 517
535 void mergeOneBranch(LocalsHandler<T> other) { 518 void mergeOneBranch(LocalsHandler<T> other) {
536 other.locals.forEachOwnLocal((Local local, T type) { 519 other.locals.forEachOwnLocal((Local local, T type) {
537 T myType = locals[local]; 520 T myType = locals[local];
538 if (myType == null) return; // Variable is only defined in [other]. 521 if (myType == null) return; // Variable is only defined in [other].
539 if (type == myType) return; 522 if (type == myType) return;
540 locals[local] = types.allocateDiamondPhi(myType, type); 523 locals[local] = types.allocateDiamondPhi(myType, type);
541 }); 524 });
542 } 525 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 * [: L: { 588 * [: L: {
606 * if (...) break; 589 * if (...) break;
607 * ... 590 * ...
608 * } 591 * }
609 * :] 592 * :]
610 * 593 *
611 * where [:this:] is the [LocalsHandler] for the paths through the 594 * where [:this:] is the [LocalsHandler] for the paths through the
612 * labeled statement that do not break out. 595 * labeled statement that do not break out.
613 */ 596 */
614 void mergeAfterBreaks(List<LocalsHandler<T>> handlers, 597 void mergeAfterBreaks(List<LocalsHandler<T>> handlers,
615 {bool keepOwnLocals: true}) { 598 {bool keepOwnLocals: true}) {
616 Node level = locals.block; 599 Node level = locals.block;
617 // Use a separate locals handler to perform the merge in, so that Phi 600 // Use a separate locals handler to perform the merge in, so that Phi
618 // creation does not invalidate previous type knowledge while we might 601 // creation does not invalidate previous type knowledge while we might
619 // still look it up. 602 // still look it up.
620 LocalsHandler merged = new LocalsHandler.from(this, level); 603 LocalsHandler merged = new LocalsHandler.from(this, level);
621 Set<Local> seenLocals = new Setlet<Local>(); 604 Set<Local> seenLocals = new Setlet<Local>();
622 bool allBranchesAbort = true; 605 bool allBranchesAbort = true;
623 // Merge all other handlers. 606 // Merge all other handlers.
624 for (LocalsHandler handler in handlers) { 607 for (LocalsHandler handler in handlers) {
625 allBranchesAbort = allBranchesAbort && handler.seenReturnOrThrow; 608 allBranchesAbort = allBranchesAbort && handler.seenReturnOrThrow;
626 merged.mergeHandler(handler, seenLocals); 609 merged.mergeHandler(handler, seenLocals);
627 } 610 }
628 // If we want to keep own locals, we merge [seenLocals] from [this] into 611 // If we want to keep own locals, we merge [seenLocals] from [this] into
629 // [merged] to update the Phi nodes with original values. 612 // [merged] to update the Phi nodes with original values.
630 if (keepOwnLocals && !seenReturnOrThrow) { 613 if (keepOwnLocals && !seenReturnOrThrow) {
631 for (Local variable in seenLocals) { 614 for (Local variable in seenLocals) {
632 T originalType = locals[variable]; 615 T originalType = locals[variable];
633 if (originalType != null) { 616 if (originalType != null) {
634 merged.locals[variable] = types.addPhiInput(variable, 617 merged.locals[variable] = types.addPhiInput(
635 merged.locals[variable], 618 variable, merged.locals[variable], originalType);
636 originalType);
637 } 619 }
638 } 620 }
639 } 621 }
640 // Clean up Phi nodes with single input and store back result into 622 // Clean up Phi nodes with single input and store back result into
641 // actual locals handler. 623 // actual locals handler.
642 merged.locals.forEachOwnLocal((Local variable, T type) { 624 merged.locals.forEachOwnLocal((Local variable, T type) {
643 locals[variable] = types.simplifyPhi(level, variable, type); 625 locals[variable] = types.simplifyPhi(level, variable, type);
644 }); 626 });
645 seenReturnOrThrow = allBranchesAbort && 627 seenReturnOrThrow =
646 (!keepOwnLocals || seenReturnOrThrow); 628 allBranchesAbort && (!keepOwnLocals || seenReturnOrThrow);
647 } 629 }
648 630
649 /** 631 /**
650 * Merge [other] into this handler. Returns whether a local in this 632 * Merge [other] into this handler. Returns whether a local in this
651 * has changed. If [seen] is not null, we allocate new Phi nodes 633 * has changed. If [seen] is not null, we allocate new Phi nodes
652 * unless the local is already present in the set [seen]. This effectively 634 * unless the local is already present in the set [seen]. This effectively
653 * overwrites the current type knowledge in this handler. 635 * overwrites the current type knowledge in this handler.
654 */ 636 */
655 bool mergeHandler(LocalsHandler<T> other, [Set<Local> seen]) { 637 bool mergeHandler(LocalsHandler<T> other, [Set<Local> seen]) {
656 if (other.seenReturnOrThrow) return false; 638 if (other.seenReturnOrThrow) return false;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 }); 686 });
705 } 687 }
706 688
707 void updateField(Element element, T type) { 689 void updateField(Element element, T type) {
708 fieldScope.updateField(element, type); 690 fieldScope.updateField(element, type);
709 } 691 }
710 } 692 }
711 693
712 abstract class InferrerVisitor<T, E extends MinimalInferrerEngine<T>> 694 abstract class InferrerVisitor<T, E extends MinimalInferrerEngine<T>>
713 extends Visitor<T> 695 extends Visitor<T>
714 with SemanticSendResolvedMixin<T, dynamic>, 696 with
715 CompoundBulkMixin<T, dynamic>, 697 SemanticSendResolvedMixin<T, dynamic>,
716 SetIfNullBulkMixin<T, dynamic>, 698 CompoundBulkMixin<T, dynamic>,
717 PrefixBulkMixin<T, dynamic>, 699 SetIfNullBulkMixin<T, dynamic>,
718 PostfixBulkMixin<T, dynamic>, 700 PrefixBulkMixin<T, dynamic>,
719 ErrorBulkMixin<T, dynamic>, 701 PostfixBulkMixin<T, dynamic>,
720 NewBulkMixin<T, dynamic>, 702 ErrorBulkMixin<T, dynamic>,
721 SetBulkMixin<T, dynamic> 703 NewBulkMixin<T, dynamic>,
704 SetBulkMixin<T, dynamic>
722 implements SemanticSendVisitor<T, dynamic> { 705 implements SemanticSendVisitor<T, dynamic> {
723 final Compiler compiler; 706 final Compiler compiler;
724 final AstElement analyzedElement; 707 final AstElement analyzedElement;
725 final TypeSystem<T> types; 708 final TypeSystem<T> types;
726 final E inferrer; 709 final E inferrer;
727 final Map<JumpTarget, List<LocalsHandler<T>>> breaksFor = 710 final Map<JumpTarget, List<LocalsHandler<T>>> breaksFor =
728 new Map<JumpTarget, List<LocalsHandler<T>>>(); 711 new Map<JumpTarget, List<LocalsHandler<T>>>();
729 final Map<JumpTarget, List<LocalsHandler>> continuesFor = 712 final Map<JumpTarget, List<LocalsHandler>> continuesFor =
730 new Map<JumpTarget, List<LocalsHandler<T>>>(); 713 new Map<JumpTarget, List<LocalsHandler<T>>>();
731 LocalsHandler<T> locals; 714 LocalsHandler<T> locals;
732 final List<T> cascadeReceiverStack = new List<T>(); 715 final List<T> cascadeReceiverStack = new List<T>();
733 final TreeElements elements; 716 final TreeElements elements;
734 717
735 bool accumulateIsChecks = false; 718 bool accumulateIsChecks = false;
736 bool conditionIsSimple = false; 719 bool conditionIsSimple = false;
737 List<Send> isChecks; 720 List<Send> isChecks;
738 int loopLevel = 0; 721 int loopLevel = 0;
739 722
740 bool get inLoop => loopLevel > 0; 723 bool get inLoop => loopLevel > 0;
741 bool get isThisExposed { 724 bool get isThisExposed {
742 return analyzedElement.isGenerativeConstructor 725 return analyzedElement.isGenerativeConstructor
743 ? locals.fieldScope.isThisExposed 726 ? locals.fieldScope.isThisExposed
744 : true; 727 : true;
745 } 728 }
729
746 void set isThisExposed(value) { 730 void set isThisExposed(value) {
747 if (analyzedElement.isGenerativeConstructor) { 731 if (analyzedElement.isGenerativeConstructor) {
748 locals.fieldScope.isThisExposed = value; 732 locals.fieldScope.isThisExposed = value;
749 } 733 }
750 } 734 }
751 735
752 InferrerVisitor(AstElement analyzedElement, 736 InferrerVisitor(
753 this.inferrer, 737 AstElement analyzedElement, this.inferrer, this.types, this.compiler,
754 this.types, 738 [LocalsHandler<T> handler])
755 this.compiler, 739 : this.analyzedElement = analyzedElement,
756 [LocalsHandler<T> handler]) 740 this.locals = handler,
757 : this.analyzedElement = analyzedElement, 741 this.elements = analyzedElement.resolvedAst.elements {
758 this.locals = handler,
759 this.elements = analyzedElement.resolvedAst.elements {
760 if (handler != null) return; 742 if (handler != null) return;
761 Node node = analyzedElement.node; 743 Node node = analyzedElement.node;
762 FieldInitializationScope<T> fieldScope = 744 FieldInitializationScope<T> fieldScope =
763 analyzedElement.isGenerativeConstructor 745 analyzedElement.isGenerativeConstructor
764 ? new FieldInitializationScope<T>(types) 746 ? new FieldInitializationScope<T>(types)
765 : null; 747 : null;
766 locals = new LocalsHandler<T>(inferrer, types, compiler, node, fieldScope); 748 locals = new LocalsHandler<T>(inferrer, types, compiler, node, fieldScope);
767 } 749 }
768 750
769 DiagnosticReporter get reporter => compiler.reporter; 751 DiagnosticReporter get reporter => compiler.reporter;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 } 880 }
899 881
900 T handleTypeLiteralGet() { 882 T handleTypeLiteralGet() {
901 return types.typeType; 883 return types.typeType;
902 } 884 }
903 885
904 T handleTypeLiteralInvoke(NodeList arguments) { 886 T handleTypeLiteralInvoke(NodeList arguments) {
905 return types.dynamicType; 887 return types.dynamicType;
906 } 888 }
907 889
908
909 @override 890 @override
910 T bulkHandleNode(Node node, String message, _) { 891 T bulkHandleNode(Node node, String message, _) {
911 return internalError(node, message.replaceAll('#', '$node')); 892 return internalError(node, message.replaceAll('#', '$node'));
912 } 893 }
913 894
914 @override 895 @override
915 T visitConstantGet( 896 T visitConstantGet(Send node, ConstantExpression constant, _) {
916 Send node,
917 ConstantExpression constant,
918 _) {
919 return bulkHandleNode(node, "Constant read `#` unhandled.", _); 897 return bulkHandleNode(node, "Constant read `#` unhandled.", _);
920 } 898 }
921 899
922 @override 900 @override
923 T visitConstantInvoke( 901 T visitConstantInvoke(Send node, ConstantExpression constant,
924 Send node, 902 NodeList arguments, CallStructure callStructure, _) {
925 ConstantExpression constant,
926 NodeList arguments,
927 CallStructure callStructure,
928 _) {
929 return bulkHandleNode(node, "Constant invoke `#` unhandled.", _); 903 return bulkHandleNode(node, "Constant invoke `#` unhandled.", _);
930 } 904 }
931 905
932 T visitClassTypeLiteralGet( 906 T visitClassTypeLiteralGet(Send node, ConstantExpression constant, _) {
933 Send node,
934 ConstantExpression constant,
935 _) {
936 return handleTypeLiteralGet(); 907 return handleTypeLiteralGet();
937 } 908 }
938 909
939 T visitClassTypeLiteralInvoke( 910 T visitClassTypeLiteralInvoke(Send node, ConstantExpression constant,
940 Send node, 911 NodeList arguments, CallStructure callStructure, _) {
941 ConstantExpression constant,
942 NodeList arguments,
943 CallStructure callStructure,
944 _) {
945 return handleTypeLiteralInvoke(arguments); 912 return handleTypeLiteralInvoke(arguments);
946 } 913 }
947 914
948 T visitTypedefTypeLiteralGet( 915 T visitTypedefTypeLiteralGet(Send node, ConstantExpression constant, _) {
949 Send node,
950 ConstantExpression constant,
951 _) {
952 return handleTypeLiteralGet(); 916 return handleTypeLiteralGet();
953 } 917 }
954 918
955 T visitTypedefTypeLiteralInvoke( 919 T visitTypedefTypeLiteralInvoke(Send node, ConstantExpression constant,
956 Send node, 920 NodeList arguments, CallStructure callStructure, _) {
957 ConstantExpression constant,
958 NodeList arguments,
959 CallStructure callStructure,
960 _) {
961 return handleTypeLiteralInvoke(arguments); 921 return handleTypeLiteralInvoke(arguments);
962 } 922 }
963 923
964 T visitTypeVariableTypeLiteralGet( 924 T visitTypeVariableTypeLiteralGet(Send node, TypeVariableElement element, _) {
965 Send node,
966 TypeVariableElement element,
967 _) {
968 return handleTypeLiteralGet(); 925 return handleTypeLiteralGet();
969 } 926 }
970 927
971 T visitTypeVariableTypeLiteralInvoke( 928 T visitTypeVariableTypeLiteralInvoke(Send node, TypeVariableElement element,
972 Send node, 929 NodeList arguments, CallStructure callStructure, _) {
973 TypeVariableElement element,
974 NodeList arguments,
975 CallStructure callStructure,
976 _) {
977 return handleTypeLiteralInvoke(arguments); 930 return handleTypeLiteralInvoke(arguments);
978 } 931 }
979 932
980 T visitDynamicTypeLiteralGet( 933 T visitDynamicTypeLiteralGet(Send node, ConstantExpression constant, _) {
981 Send node,
982 ConstantExpression constant,
983 _) {
984 return handleTypeLiteralGet(); 934 return handleTypeLiteralGet();
985 } 935 }
986 936
987 T visitDynamicTypeLiteralInvoke( 937 T visitDynamicTypeLiteralInvoke(Send node, ConstantExpression constant,
988 Send node, 938 NodeList arguments, CallStructure callStructure, _) {
989 ConstantExpression constant,
990 NodeList arguments,
991 CallStructure callStructure,
992 _) {
993 return handleTypeLiteralInvoke(arguments); 939 return handleTypeLiteralInvoke(arguments);
994 } 940 }
995 941
996 bool isThisOrSuper(Node node) => node.isThis() || node.isSuper(); 942 bool isThisOrSuper(Node node) => node.isThis() || node.isSuper();
997 943
998 Element get outermostElement { 944 Element get outermostElement {
999 return analyzedElement.outermostEnclosingMemberOrTopLevel.implementation; 945 return analyzedElement.outermostEnclosingMemberOrTopLevel.implementation;
1000 } 946 }
1001 947
1002 T _thisType; 948 T _thisType;
1003 T get thisType { 949 T get thisType {
1004 if (_thisType != null) return _thisType; 950 if (_thisType != null) return _thisType;
1005 ClassElement cls = outermostElement.enclosingClass; 951 ClassElement cls = outermostElement.enclosingClass;
1006 ClassWorld classWorld = compiler.world; 952 ClassWorld classWorld = compiler.world;
1007 if (classWorld.isUsedAsMixin(cls)) { 953 if (classWorld.isUsedAsMixin(cls)) {
1008 return _thisType = types.nonNullSubtype(cls); 954 return _thisType = types.nonNullSubtype(cls);
1009 } else { 955 } else {
1010 return _thisType = types.nonNullSubclass(cls); 956 return _thisType = types.nonNullSubclass(cls);
1011 } 957 }
1012 } 958 }
1013 959
1014 T _superType; 960 T _superType;
1015 T get superType { 961 T get superType {
1016 if (_superType != null) return _superType; 962 if (_superType != null) return _superType;
1017 return _superType = types.nonNullExact( 963 return _superType =
1018 outermostElement.enclosingClass.superclass); 964 types.nonNullExact(outermostElement.enclosingClass.superclass);
1019 } 965 }
1020 966
1021 @override 967 @override
1022 T visitThisGet(Identifier node, _) { 968 T visitThisGet(Identifier node, _) {
1023 return thisType; 969 return thisType;
1024 } 970 }
1025 971
1026 T visitIdentifier(Identifier node) { 972 T visitIdentifier(Identifier node) {
1027 if (node.isThis()) { 973 if (node.isThis()) {
1028 return thisType; 974 return thisType;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1066 if (usePositive) continue; 1012 if (usePositive) continue;
1067 } else { 1013 } else {
1068 if (!usePositive) continue; 1014 if (!usePositive) continue;
1069 } 1015 }
1070 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); 1016 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast);
1071 narrow(elements[node.receiver], type, node); 1017 narrow(elements[node.receiver], type, node);
1072 } else { 1018 } else {
1073 Element receiverElement = elements[node.receiver]; 1019 Element receiverElement = elements[node.receiver];
1074 Element argumentElement = elements[node.arguments.first]; 1020 Element argumentElement = elements[node.arguments.first];
1075 String operator = node.selector.asOperator().source; 1021 String operator = node.selector.asOperator().source;
1076 if ((operator == '==' && usePositive) 1022 if ((operator == '==' && usePositive) ||
1077 || (operator == '!=' && !usePositive)) { 1023 (operator == '!=' && !usePositive)) {
1078 // Type the elements as null. 1024 // Type the elements as null.
1079 if (Elements.isLocal(receiverElement)) { 1025 if (Elements.isLocal(receiverElement)) {
1080 locals.update(receiverElement, types.nullType, node); 1026 locals.update(receiverElement, types.nullType, node);
1081 } 1027 }
1082 if (Elements.isLocal(argumentElement)) { 1028 if (Elements.isLocal(argumentElement)) {
1083 locals.update(argumentElement, types.nullType, node); 1029 locals.update(argumentElement, types.nullType, node);
1084 } 1030 }
1085 } else { 1031 } else {
1086 // Narrow the elements to a non-null type. 1032 // Narrow the elements to a non-null type.
1087 DartType objectType = compiler.coreTypes.objectType; 1033 DartType objectType = compiler.coreTypes.objectType;
1088 if (Elements.isLocal(receiverElement)) { 1034 if (Elements.isLocal(receiverElement)) {
1089 narrow(receiverElement, objectType, node); 1035 narrow(receiverElement, objectType, node);
1090 } 1036 }
1091 if (Elements.isLocal(argumentElement)) { 1037 if (Elements.isLocal(argumentElement)) {
1092 narrow(argumentElement, objectType, node); 1038 narrow(argumentElement, objectType, node);
1093 } 1039 }
1094 } 1040 }
1095 } 1041 }
1096 } 1042 }
1097 } 1043 }
1098 1044
1099 @override 1045 @override
1100 T visitIndex(Send node, Node receiver, Node index, _) { 1046 T visitIndex(Send node, Node receiver, Node index, _) {
1101 return handleDynamicInvoke(node); 1047 return handleDynamicInvoke(node);
1102 } 1048 }
1103 1049
1104 @override 1050 @override
1105 T visitDynamicPropertyInvoke( 1051 T visitDynamicPropertyInvoke(
1106 Send node, 1052 Send node, Node receiver, NodeList arguments, Selector selector, _) {
1107 Node receiver,
1108 NodeList arguments,
1109 Selector selector,
1110 _) {
1111 return handleDynamicInvoke(node); 1053 return handleDynamicInvoke(node);
1112 } 1054 }
1113 1055
1114 @override 1056 @override
1115 T visitIfNotNullDynamicPropertyInvoke( 1057 T visitIfNotNullDynamicPropertyInvoke(
1116 Send node, 1058 Send node, Node receiver, NodeList arguments, Selector selector, _) {
1117 Node receiver,
1118 NodeList arguments,
1119 Selector selector,
1120 _) {
1121 return handleDynamicInvoke(node); 1059 return handleDynamicInvoke(node);
1122 } 1060 }
1123 1061
1124 @override 1062 @override
1125 T visitThisPropertyInvoke( 1063 T visitThisPropertyInvoke(
1126 Send node, 1064 Send node, NodeList arguments, Selector selector, _) {
1127 NodeList arguments,
1128 Selector selector,
1129 _) {
1130 return handleDynamicInvoke(node); 1065 return handleDynamicInvoke(node);
1131 } 1066 }
1132 1067
1133 @override 1068 @override
1134 T visitIfNull(Send node, Node left, Node right, _) { 1069 T visitIfNull(Send node, Node left, Node right, _) {
1135 T firstType = visit(left); 1070 T firstType = visit(left);
1136 T secondType = visit(right); 1071 T secondType = visit(right);
1137 return types.allocateDiamondPhi(types.narrowNotNull(firstType), secondType); 1072 return types.allocateDiamondPhi(types.narrowNotNull(firstType), secondType);
1138 } 1073 }
1139 1074
(...skipping 12 matching lines...) Expand all
1152 updateIsChecks(isChecks, usePositive: true); 1087 updateIsChecks(isChecks, usePositive: true);
1153 LocalsHandler<T> narrowed; 1088 LocalsHandler<T> narrowed;
1154 if (oldAccumulateIsChecks) { 1089 if (oldAccumulateIsChecks) {
1155 narrowed = new LocalsHandler<T>.topLevelCopyOf(locals); 1090 narrowed = new LocalsHandler<T>.topLevelCopyOf(locals);
1156 } else { 1091 } else {
1157 accumulateIsChecks = false; 1092 accumulateIsChecks = false;
1158 isChecks = oldIsChecks; 1093 isChecks = oldIsChecks;
1159 } 1094 }
1160 visit(right); 1095 visit(right);
1161 if (oldAccumulateIsChecks) { 1096 if (oldAccumulateIsChecks) {
1162 1097 bool invalidatedInRightHandSide(Send test) {
1163 bool invalidatedInRightHandSide (Send test) {
1164 Element receiver = elements[test.receiver]; 1098 Element receiver = elements[test.receiver];
1165 if (receiver is LocalElement) { 1099 if (receiver is LocalElement) {
1166 return narrowed.locals[receiver] != locals.locals[receiver]; 1100 return narrowed.locals[receiver] != locals.locals[receiver];
1167 } 1101 }
1168 return false; 1102 return false;
1169 } 1103 }
1170 1104
1171 isChecks.removeWhere(invalidatedInRightHandSide); 1105 isChecks.removeWhere(invalidatedInRightHandSide);
1172 } 1106 }
1173 saved.mergeDiamondFlow(locals, null); 1107 saved.mergeDiamondFlow(locals, null);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1260 if (simpleCondition) updateIsChecks(tests, usePositive: false); 1194 if (simpleCondition) updateIsChecks(tests, usePositive: false);
1261 T secondType = visit(node.elseExpression); 1195 T secondType = visit(node.elseExpression);
1262 saved.mergeDiamondFlow(thenLocals, locals); 1196 saved.mergeDiamondFlow(thenLocals, locals);
1263 locals = saved; 1197 locals = saved;
1264 T type = types.allocateDiamondPhi(firstType, secondType); 1198 T type = types.allocateDiamondPhi(firstType, secondType);
1265 return type; 1199 return type;
1266 } 1200 }
1267 1201
1268 T visitVariableDefinitions(VariableDefinitions node) { 1202 T visitVariableDefinitions(VariableDefinitions node) {
1269 for (Link<Node> link = node.definitions.nodes; 1203 for (Link<Node> link = node.definitions.nodes;
1270 !link.isEmpty; 1204 !link.isEmpty;
1271 link = link.tail) { 1205 link = link.tail) {
1272 Node definition = link.head; 1206 Node definition = link.head;
1273 if (definition is Identifier) { 1207 if (definition is Identifier) {
1274 locals.update(elements[definition], types.nullType, node); 1208 locals.update(elements[definition], types.nullType, node);
1275 } else { 1209 } else {
1276 assert(definition.asSendSet() != null); 1210 assert(definition.asSendSet() != null);
1277 handleSendSet(definition); 1211 handleSendSet(definition);
1278 } 1212 }
1279 } 1213 }
1280 return null; 1214 return null;
1281 } 1215 }
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1346 // Setup (and clear in case of multiple iterations of the loop) 1280 // Setup (and clear in case of multiple iterations of the loop)
1347 // the lists of breaks and continues seen in the loop. 1281 // the lists of breaks and continues seen in the loop.
1348 setupBreaksAndContinues(target); 1282 setupBreaksAndContinues(target);
1349 locals = new LocalsHandler<T>.from(saved, node); 1283 locals = new LocalsHandler<T>.from(saved, node);
1350 logic(); 1284 logic();
1351 changed = saved.mergeAll(getLoopBackEdges(target)); 1285 changed = saved.mergeAll(getLoopBackEdges(target));
1352 } while (changed); 1286 } while (changed);
1353 loopLevel--; 1287 loopLevel--;
1354 saved.endLoop(node); 1288 saved.endLoop(node);
1355 bool keepOwnLocals = node.asDoWhile() == null; 1289 bool keepOwnLocals = node.asDoWhile() == null;
1356 saved.mergeAfterBreaks( 1290 saved.mergeAfterBreaks(getBreaks(target), keepOwnLocals: keepOwnLocals);
1357 getBreaks(target), keepOwnLocals: keepOwnLocals);
1358 locals = saved; 1291 locals = saved;
1359 clearBreaksAndContinues(target); 1292 clearBreaksAndContinues(target);
1360 return null; 1293 return null;
1361 } 1294 }
1362 1295
1363 T visitWhile(While node) { 1296 T visitWhile(While node) {
1364 return handleLoop(node, () { 1297 return handleLoop(node, () {
1365 List<Send> tests = <Send>[]; 1298 List<Send> tests = <Send>[];
1366 handleCondition(node.condition, tests); 1299 handleCondition(node.condition, tests);
1367 updateIsChecks(tests, usePositive: true); 1300 updateIsChecks(tests, usePositive: true);
(...skipping 16 matching lines...) Expand all
1384 List<Send> tests = <Send>[]; 1317 List<Send> tests = <Send>[];
1385 handleCondition(node.condition, tests); 1318 handleCondition(node.condition, tests);
1386 updateIsChecks(tests, usePositive: true); 1319 updateIsChecks(tests, usePositive: true);
1387 visit(node.body); 1320 visit(node.body);
1388 visit(node.update); 1321 visit(node.update);
1389 }); 1322 });
1390 } 1323 }
1391 1324
1392 T visitTryStatement(TryStatement node) { 1325 T visitTryStatement(TryStatement node) {
1393 LocalsHandler<T> saved = locals; 1326 LocalsHandler<T> saved = locals;
1394 locals = new LocalsHandler<T>.from( 1327 locals = new LocalsHandler<T>.from(locals, node, useOtherTryBlock: false);
1395 locals, node, useOtherTryBlock: false);
1396 visit(node.tryBlock); 1328 visit(node.tryBlock);
1397 saved.mergeDiamondFlow(locals, null); 1329 saved.mergeDiamondFlow(locals, null);
1398 locals = saved; 1330 locals = saved;
1399 for (Node catchBlock in node.catchBlocks) { 1331 for (Node catchBlock in node.catchBlocks) {
1400 saved = locals; 1332 saved = locals;
1401 locals = new LocalsHandler<T>.from(locals, catchBlock); 1333 locals = new LocalsHandler<T>.from(locals, catchBlock);
1402 visit(catchBlock); 1334 visit(catchBlock);
1403 saved.mergeDiamondFlow(locals, null); 1335 saved.mergeDiamondFlow(locals, null);
1404 locals = saved; 1336 locals = saved;
1405 } 1337 }
1406 visit(node.finallyBlock); 1338 visit(node.finallyBlock);
1407 return null; 1339 return null;
1408 } 1340 }
1409 1341
1410 T visitThrow(Throw node) { 1342 T visitThrow(Throw node) {
1411 node.visitChildren(this); 1343 node.visitChildren(this);
1412 locals.seenReturnOrThrow = true; 1344 locals.seenReturnOrThrow = true;
1413 return types.nonNullEmpty(); 1345 return types.nonNullEmpty();
1414 } 1346 }
1415 1347
1416 T visitCatchBlock(CatchBlock node) { 1348 T visitCatchBlock(CatchBlock node) {
1417 Node exception = node.exception; 1349 Node exception = node.exception;
1418 if (exception != null) { 1350 if (exception != null) {
1419 DartType type = elements.getType(node.type); 1351 DartType type = elements.getType(node.type);
1420 T mask = type == null || 1352 T mask = type == null || type.treatAsDynamic || type.isTypeVariable
1421 type.treatAsDynamic ||
1422 type.isTypeVariable
1423 ? types.dynamicType 1353 ? types.dynamicType
1424 : types.nonNullSubtype(type.element); 1354 : types.nonNullSubtype(type.element);
1425 locals.update(elements[exception], mask, node); 1355 locals.update(elements[exception], mask, node);
1426 } 1356 }
1427 Node trace = node.trace; 1357 Node trace = node.trace;
1428 if (trace != null) { 1358 if (trace != null) {
1429 locals.update(elements[trace], types.dynamicType, node); 1359 locals.update(elements[trace], types.dynamicType, node);
1430 } 1360 }
1431 visit(node.block); 1361 visit(node.block);
1432 return null; 1362 return null;
1433 } 1363 }
1434 1364
1435 T visitParenthesizedExpression(ParenthesizedExpression node) { 1365 T visitParenthesizedExpression(ParenthesizedExpression node) {
1436 return visit(node.expression); 1366 return visit(node.expression);
1437 } 1367 }
1438 1368
1439 T visitBlock(Block node) { 1369 T visitBlock(Block node) {
1440 if (node.statements != null) { 1370 if (node.statements != null) {
1441 for (Node statement in node.statements) { 1371 for (Node statement in node.statements) {
1442 visit(statement); 1372 visit(statement);
1443 if (locals.aborts) break; 1373 if (locals.aborts) break;
1444 } 1374 }
1445 } 1375 }
1446 return null; 1376 return null;
1447 } 1377 }
1448 1378
1449 T visitLabeledStatement(LabeledStatement node) { 1379 T visitLabeledStatement(LabeledStatement node) {
1450 Statement body = node.statement; 1380 Statement body = node.statement;
1451 if (body is Loop 1381 if (body is Loop ||
1452 || body is SwitchStatement 1382 body is SwitchStatement ||
1453 || Elements.isUnusedLabel(node, elements)) { 1383 Elements.isUnusedLabel(node, elements)) {
1454 // Loops and switches handle their own labels. 1384 // Loops and switches handle their own labels.
1455 visit(body); 1385 visit(body);
1456 } else { 1386 } else {
1457 JumpTarget targetElement = elements.getTargetDefinition(body); 1387 JumpTarget targetElement = elements.getTargetDefinition(body);
1458 setupBreaksAndContinues(targetElement); 1388 setupBreaksAndContinues(targetElement);
1459 visit(body); 1389 visit(body);
1460 locals.mergeAfterBreaks(getBreaks(targetElement)); 1390 locals.mergeAfterBreaks(getBreaks(targetElement));
1461 clearBreaksAndContinues(targetElement); 1391 clearBreaksAndContinues(targetElement);
1462 } 1392 }
1463 return null; 1393 return null;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1553 return type; 1483 return type;
1554 } 1484 }
1555 1485
1556 T visitCascade(Cascade node) { 1486 T visitCascade(Cascade node) {
1557 // Ignore the result of the cascade send and return the type of the cascade 1487 // Ignore the result of the cascade send and return the type of the cascade
1558 // receiver. 1488 // receiver.
1559 visit(node.expression); 1489 visit(node.expression);
1560 return cascadeReceiverStack.removeLast(); 1490 return cascadeReceiverStack.removeLast();
1561 } 1491 }
1562 } 1492 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/inferrer/closure_tracer.dart ('k') | pkg/compiler/lib/src/inferrer/list_tracer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698