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 compiler.src.inferrer.type_graph_nodes; | 5 library compiler.src.inferrer.type_graph_nodes; |
6 | 6 |
7 import 'dart:collection' show IterableBase; | 7 import 'dart:collection' show IterableBase; |
8 | 8 |
9 import '../common.dart'; | 9 import '../common.dart'; |
10 import '../common/names.dart' show Identifiers; | 10 import '../common/names.dart' show Identifiers; |
11 import '../compiler.dart' show Compiler; | 11 import '../compiler.dart' show Compiler; |
12 import '../constants/values.dart'; | 12 import '../constants/values.dart'; |
13 import '../elements/elements.dart'; | 13 import '../elements/elements.dart'; |
14 import '../elements/entities.dart'; | 14 import '../elements/entities.dart'; |
15 import '../elements/resolution_types.dart' | 15 import '../elements/resolution_types.dart' |
16 show | 16 show ResolutionDartType, ResolutionInterfaceType; |
17 ResolutionDartType, | 17 import '../elements/types.dart'; |
18 ResolutionFunctionType, | |
19 ResolutionInterfaceType, | |
20 ResolutionTypeKind; | |
21 import '../tree/tree.dart' as ast show Node, Send; | 18 import '../tree/tree.dart' as ast show Node, Send; |
22 import '../types/masks.dart' | 19 import '../types/masks.dart' |
23 show | 20 show |
24 CommonMasks, | 21 CommonMasks, |
25 ContainerTypeMask, | 22 ContainerTypeMask, |
26 DictionaryTypeMask, | 23 DictionaryTypeMask, |
27 MapTypeMask, | 24 MapTypeMask, |
28 TypeMask, | 25 TypeMask, |
29 ValueTypeMask; | 26 ValueTypeMask; |
30 import '../universe/selector.dart' show Selector; | 27 import '../universe/selector.dart' show Selector; |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 * A node representing members in the broadest sense: | 360 * A node representing members in the broadest sense: |
364 * | 361 * |
365 * - Functions | 362 * - Functions |
366 * - Constructors | 363 * - Constructors |
367 * - Fields (also synthetic ones due to closures) | 364 * - Fields (also synthetic ones due to closures) |
368 * - Local functions (closures) | 365 * - Local functions (closures) |
369 * | 366 * |
370 * These should never be created directly but instead are constructed by | 367 * These should never be created directly but instead are constructed by |
371 * the [ElementTypeInformation] factory. | 368 * the [ElementTypeInformation] factory. |
372 */ | 369 */ |
373 class MemberTypeInformation extends ElementTypeInformation | 370 abstract class MemberTypeInformation extends ElementTypeInformation |
374 with ApplyableTypeInformation { | 371 with ApplyableTypeInformation { |
375 MemberElement get _member => super._element; | 372 MemberElement get _member => super._element; |
376 | 373 |
377 /** | 374 /** |
378 * If [element] is a function, [closurizedCount] is the number of | 375 * If [element] is a function, [closurizedCount] is the number of |
379 * times it is closurized. The value gets updated while inferring. | 376 * times it is closurized. The value gets updated while inferring. |
380 */ | 377 */ |
381 int closurizedCount = 0; | 378 int closurizedCount = 0; |
382 | 379 |
383 // Strict `bool` value is computed in cleanup(). Also used as a flag to see if | 380 // Strict `bool` value is computed in cleanup(). Also used as a flag to see if |
384 // cleanup has been called. | 381 // cleanup has been called. |
385 bool _isCalledOnce = null; | 382 bool _isCalledOnce = null; |
386 | 383 |
387 /** | 384 /** |
388 * This map contains the callers of [element]. It stores all unique call sites | 385 * This map contains the callers of [element]. It stores all unique call sites |
389 * to enable counting the global number of call sites of [element]. | 386 * to enable counting the global number of call sites of [element]. |
390 * | 387 * |
391 * A call site is either an AST [ast.Node], an [Element] (see uses of | 388 * A call site is either an AST [ast.Node], an [Element] (see uses of |
392 * [synthesizeForwardingCall] in [SimpleTypeInferrerVisitor]). | 389 * [synthesizeForwardingCall] in [SimpleTypeInferrerVisitor]). |
393 * | 390 * |
394 * The global information is summarized in [cleanup], after which [_callers] | 391 * The global information is summarized in [cleanup], after which [_callers] |
395 * is set to `null`. | 392 * is set to `null`. |
396 */ | 393 */ |
397 Map<MemberElement, Setlet<Spannable>> _callers; | 394 Map<MemberElement, Setlet<Spannable>> _callers; |
398 | 395 |
399 MemberTypeInformation(MemberElement element) : super._internal(null, element); | 396 MemberTypeInformation._internal(MemberElement element) |
| 397 : super._internal(null, element); |
400 | 398 |
401 MemberElement get member => _element; | 399 MemberElement get member => _element; |
402 | 400 |
403 String get debugName => '$member'; | 401 String get debugName => '$member'; |
404 | 402 |
405 void addCall(MemberElement caller, Spannable node) { | 403 void addCall(MemberElement caller, Spannable node) { |
406 assert(node is ast.Node || node is Element); | 404 assert(node is ast.Node || node is Element); |
407 _callers ??= <MemberElement, Setlet<Spannable>>{}; | 405 _callers ??= <MemberElement, Setlet<Spannable>>{}; |
408 _callers.putIfAbsent(caller, () => new Setlet()).add(node); | 406 _callers.putIfAbsent(caller, () => new Setlet()).add(node); |
409 } | 407 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 } | 446 } |
449 | 447 |
450 bool get isClosurized => closurizedCount > 0; | 448 bool get isClosurized => closurizedCount > 0; |
451 | 449 |
452 // Closurized methods never become stable to ensure that the information in | 450 // Closurized methods never become stable to ensure that the information in |
453 // [users] is accurate. The inference stops tracking users for stable types. | 451 // [users] is accurate. The inference stops tracking users for stable types. |
454 // Note that we only override the getter, the setter will still modify the | 452 // Note that we only override the getter, the setter will still modify the |
455 // state of the [isStable] field inherited from [TypeInformation]. | 453 // state of the [isStable] field inherited from [TypeInformation]. |
456 bool get isStable => super.isStable && !isClosurized; | 454 bool get isStable => super.isStable && !isClosurized; |
457 | 455 |
458 TypeMask handleSpecialCases(InferrerEngine inferrer) { | 456 TypeMask handleSpecialCases(InferrerEngine inferrer); |
459 if (_member.isField && | |
460 (!inferrer.backend.canFieldBeUsedForGlobalOptimizations( | |
461 _member, inferrer.closedWorld) || | |
462 inferrer.assumeDynamic(_member))) { | |
463 // Do not infer types for fields that have a corresponding annotation or | |
464 // are assigned by synthesized calls | |
465 | 457 |
466 giveUp(inferrer); | 458 TypeMask _handleFunctionCase( |
467 return safeType(inferrer); | 459 FunctionEntity function, InferrerEngine inferrer) { |
468 } | 460 if (inferrer.closedWorld.nativeData.isNativeMember(function)) { |
469 if (inferrer.closedWorld.nativeData.isNativeMember(_member)) { | |
470 // Use the type annotation as the type for native elements. We | 461 // Use the type annotation as the type for native elements. We |
471 // also give up on inferring to make sure this element never | 462 // also give up on inferring to make sure this element never |
472 // goes in the work queue. | 463 // goes in the work queue. |
473 giveUp(inferrer); | 464 giveUp(inferrer); |
474 if (_member.isField) { | 465 return inferrer |
475 FieldElement field = _member; | 466 .typeOfNativeBehavior( |
476 return inferrer | 467 inferrer.closedWorld.nativeData.getNativeMethodBehavior(function)) |
477 .typeOfNativeBehavior(inferrer.closedWorld.nativeData | 468 .type; |
478 .getNativeFieldLoadBehavior(field)) | |
479 .type; | |
480 } else { | |
481 assert(_member.isFunction || | |
482 _member.isGetter || | |
483 _member.isSetter || | |
484 _member.isConstructor); | |
485 MethodElement methodElement = _member; | |
486 var elementType = methodElement.type; | |
487 if (elementType.kind != ResolutionTypeKind.FUNCTION) { | |
488 return safeType(inferrer); | |
489 } else { | |
490 return inferrer | |
491 .typeOfNativeBehavior(inferrer.closedWorld.nativeData | |
492 .getNativeMethodBehavior(methodElement)) | |
493 .type; | |
494 } | |
495 } | |
496 } | |
497 | |
498 CommonMasks commonMasks = inferrer.commonMasks; | |
499 if (_member.isConstructor) { | |
500 ConstructorElement constructor = _member; | |
501 if (constructor.isIntFromEnvironmentConstructor) { | |
502 giveUp(inferrer); | |
503 return commonMasks.intType.nullable(); | |
504 } else if (constructor.isBoolFromEnvironmentConstructor) { | |
505 giveUp(inferrer); | |
506 return commonMasks.boolType.nullable(); | |
507 } else if (constructor.isStringFromEnvironmentConstructor) { | |
508 giveUp(inferrer); | |
509 return commonMasks.stringType.nullable(); | |
510 } | |
511 } | 469 } |
512 return null; | 470 return null; |
513 } | 471 } |
514 | 472 |
515 TypeMask potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) { | 473 TypeMask potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) { |
516 Compiler compiler = inferrer.compiler; | 474 Compiler compiler = inferrer.compiler; |
517 if (!compiler.options.trustTypeAnnotations && | 475 if (!compiler.options.trustTypeAnnotations && |
518 !compiler.options.enableTypeAssertions && | 476 !compiler.options.enableTypeAssertions && |
519 !inferrer.trustTypeAnnotations(_member)) { | 477 !inferrer.trustTypeAnnotations(_member)) { |
520 return mask; | 478 return mask; |
521 } | 479 } |
522 if (_member.isGenerativeConstructor || _member.isSetter) { | 480 return _potentiallyNarrowType(mask, inferrer); |
523 return mask; | 481 } |
524 } | |
525 if (_member.isField) { | |
526 return _narrowType(inferrer.closedWorld, mask, _member.type); | |
527 } | |
528 assert( | |
529 _member.isFunction || _member.isGetter || _member.isFactoryConstructor); | |
530 | 482 |
531 ResolutionFunctionType type = _member.type; | 483 TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer); |
532 return _narrowType(inferrer.closedWorld, mask, type.returnType); | |
533 } | |
534 | 484 |
535 TypeMask computeType(InferrerEngine inferrer) { | 485 TypeMask computeType(InferrerEngine inferrer) { |
536 TypeMask special = handleSpecialCases(inferrer); | 486 TypeMask special = handleSpecialCases(inferrer); |
537 if (special != null) return potentiallyNarrowType(special, inferrer); | 487 if (special != null) return potentiallyNarrowType(special, inferrer); |
538 return potentiallyNarrowType( | 488 return potentiallyNarrowType( |
539 inferrer.types.computeTypeMask(assignments), inferrer); | 489 inferrer.types.computeTypeMask(assignments), inferrer); |
540 } | 490 } |
541 | 491 |
542 TypeMask safeType(InferrerEngine inferrer) { | 492 TypeMask safeType(InferrerEngine inferrer) { |
543 return potentiallyNarrowType(super.safeType(inferrer), inferrer); | 493 return potentiallyNarrowType(super.safeType(inferrer), inferrer); |
544 } | 494 } |
545 | 495 |
546 String toString() => 'MemberElement $_member $type'; | 496 String toString() => 'MemberElement $_member $type'; |
547 | 497 |
548 accept(TypeInformationVisitor visitor) { | 498 accept(TypeInformationVisitor visitor) { |
549 return visitor.visitMemberTypeInformation(this); | 499 return visitor.visitMemberTypeInformation(this); |
550 } | 500 } |
551 | 501 |
552 bool hasStableType(InferrerEngine inferrer) { | |
553 // The number of assignments of non-final fields is | |
554 // not stable. Therefore such a field cannot be stable. | |
555 if (_member.isField && !(_member.isConst || _member.isFinal)) { | |
556 return false; | |
557 } | |
558 | |
559 if (_member.isFunction) return false; | |
560 | |
561 return super.hasStableType(inferrer); | |
562 } | |
563 | |
564 void cleanup() { | 502 void cleanup() { |
565 // This node is on multiple lists so cleanup() can be called twice. | 503 // This node is on multiple lists so cleanup() can be called twice. |
566 if (_isCalledOnce != null) return; | 504 if (_isCalledOnce != null) return; |
567 _isCalledOnce = _computeIsCalledOnce(); | 505 _isCalledOnce = _computeIsCalledOnce(); |
568 _callers = null; | 506 _callers = null; |
569 super.cleanup(); | 507 super.cleanup(); |
570 } | 508 } |
571 | 509 |
572 @override | 510 @override |
573 String getInferredSignature(TypeSystem types) { | 511 String getInferredSignature(TypeSystem types) { |
574 return types.getInferredSignatureOfMethod(_member); | 512 return types.getInferredSignatureOfMethod(_member); |
575 } | 513 } |
576 } | 514 } |
577 | 515 |
| 516 class FieldTypeInformation extends MemberTypeInformation { |
| 517 FieldElement get _field => _member; |
| 518 |
| 519 FieldTypeInformation(FieldElement element) : super._internal(element); |
| 520 |
| 521 TypeMask handleSpecialCases(InferrerEngine inferrer) { |
| 522 if (!inferrer.backend.canFieldBeUsedForGlobalOptimizations( |
| 523 _field, inferrer.closedWorld) || |
| 524 inferrer.assumeDynamic(_field)) { |
| 525 // Do not infer types for fields that have a corresponding annotation or |
| 526 // are assigned by synthesized calls |
| 527 |
| 528 giveUp(inferrer); |
| 529 return safeType(inferrer); |
| 530 } |
| 531 if (inferrer.closedWorld.nativeData.isNativeMember(_field)) { |
| 532 // Use the type annotation as the type for native elements. We |
| 533 // also give up on inferring to make sure this element never |
| 534 // goes in the work queue. |
| 535 giveUp(inferrer); |
| 536 return inferrer |
| 537 .typeOfNativeBehavior(inferrer.closedWorld.nativeData |
| 538 .getNativeFieldLoadBehavior(_field)) |
| 539 .type; |
| 540 } |
| 541 return null; |
| 542 } |
| 543 |
| 544 TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) { |
| 545 return _narrowType(inferrer.closedWorld, mask, _field.type); |
| 546 } |
| 547 |
| 548 bool hasStableType(InferrerEngine inferrer) { |
| 549 // The number of assignments of non-final fields is |
| 550 // not stable. Therefore such a field cannot be stable. |
| 551 if (!(_field.isConst || _field.isFinal)) { |
| 552 return false; |
| 553 } |
| 554 return super.hasStableType(inferrer); |
| 555 } |
| 556 } |
| 557 |
| 558 class GetterTypeInformation extends MemberTypeInformation { |
| 559 GetterElement get _getter => _member; |
| 560 |
| 561 GetterTypeInformation(GetterElement element) : super._internal(element); |
| 562 |
| 563 TypeMask handleSpecialCases(InferrerEngine inferrer) { |
| 564 return _handleFunctionCase(_getter, inferrer); |
| 565 } |
| 566 |
| 567 TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) { |
| 568 FunctionType type = _getter.type; |
| 569 return _narrowType(inferrer.closedWorld, mask, type.returnType); |
| 570 } |
| 571 } |
| 572 |
| 573 class SetterTypeInformation extends MemberTypeInformation { |
| 574 SetterElement get _setter => _member; |
| 575 |
| 576 SetterTypeInformation(SetterElement element) : super._internal(element); |
| 577 |
| 578 TypeMask handleSpecialCases(InferrerEngine inferrer) { |
| 579 return _handleFunctionCase(_setter, inferrer); |
| 580 } |
| 581 |
| 582 TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) { |
| 583 return mask; |
| 584 } |
| 585 } |
| 586 |
| 587 class MethodTypeInformation extends MemberTypeInformation { |
| 588 MethodElement get _method => _member; |
| 589 |
| 590 MethodTypeInformation(MethodElement element) : super._internal(element); |
| 591 |
| 592 TypeMask handleSpecialCases(InferrerEngine inferrer) { |
| 593 return _handleFunctionCase(_method, inferrer); |
| 594 } |
| 595 |
| 596 TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) { |
| 597 FunctionType type = _method.type; |
| 598 return _narrowType(inferrer.closedWorld, mask, type.returnType); |
| 599 } |
| 600 |
| 601 bool hasStableType(InferrerEngine inferrer) => false; |
| 602 } |
| 603 |
| 604 class FactoryConstructorTypeInformation extends MemberTypeInformation { |
| 605 ConstructorElement get _constructor => _member; |
| 606 |
| 607 FactoryConstructorTypeInformation(ConstructorElement element) |
| 608 : super._internal(element); |
| 609 |
| 610 TypeMask handleSpecialCases(InferrerEngine inferrer) { |
| 611 CommonMasks commonMasks = inferrer.commonMasks; |
| 612 if (_constructor.isIntFromEnvironmentConstructor) { |
| 613 giveUp(inferrer); |
| 614 return commonMasks.intType.nullable(); |
| 615 } else if (_constructor.isBoolFromEnvironmentConstructor) { |
| 616 giveUp(inferrer); |
| 617 return commonMasks.boolType.nullable(); |
| 618 } else if (_constructor.isStringFromEnvironmentConstructor) { |
| 619 giveUp(inferrer); |
| 620 return commonMasks.stringType.nullable(); |
| 621 } |
| 622 return _handleFunctionCase(_constructor, inferrer); |
| 623 } |
| 624 |
| 625 TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) { |
| 626 FunctionType type = _constructor.type; |
| 627 return _narrowType(inferrer.closedWorld, mask, type.returnType); |
| 628 } |
| 629 |
| 630 bool hasStableType(InferrerEngine inferrer) { |
| 631 return super.hasStableType(inferrer); |
| 632 } |
| 633 } |
| 634 |
| 635 class GenerativeConstructorTypeInformation extends MemberTypeInformation { |
| 636 ConstructorElement get _constructor => _member; |
| 637 |
| 638 GenerativeConstructorTypeInformation(ConstructorElement element) |
| 639 : super._internal(element); |
| 640 |
| 641 TypeMask handleSpecialCases(InferrerEngine inferrer) { |
| 642 return _handleFunctionCase(_constructor, inferrer); |
| 643 } |
| 644 |
| 645 TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) { |
| 646 return mask; |
| 647 } |
| 648 |
| 649 bool hasStableType(InferrerEngine inferrer) { |
| 650 return super.hasStableType(inferrer); |
| 651 } |
| 652 } |
| 653 |
578 /** | 654 /** |
579 * A node representing parameters: | 655 * A node representing parameters: |
580 * | 656 * |
581 * - Parameters | 657 * - Parameters |
582 * - Initializing formals | 658 * - Initializing formals |
583 * | 659 * |
584 * These should never be created directly but instead are constructed by | 660 * These should never be created directly but instead are constructed by |
585 * the [ElementTypeInformation] factory. | 661 * the [ElementTypeInformation] factory. |
586 */ | 662 */ |
587 class ParameterTypeInformation extends ElementTypeInformation { | 663 class ParameterTypeInformation extends ElementTypeInformation { |
588 ParameterElement get _parameter => super._element; | 664 ParameterElement get _parameter => super._element; |
589 final MethodElement _method; | 665 final MethodElement _method; |
590 bool _isInstanceMemberParameter; | 666 bool _isInstanceMemberParameter; |
591 bool _isClosureParameter; | 667 bool _isClosureParameter; |
592 bool _isTearOffClosureParameter = false; | 668 bool _isTearOffClosureParameter = false; |
593 | 669 |
594 ParameterTypeInformation.localFunction(MemberTypeInformation context, | 670 ParameterTypeInformation.localFunction( |
595 ParameterElement parameter, this._method) | 671 MemberTypeInformation context, ParameterElement parameter, this._method) |
596 : _isInstanceMemberParameter = false, | 672 : _isInstanceMemberParameter = false, |
597 _isClosureParameter = true, | 673 _isClosureParameter = true, |
598 super._internal(context, parameter); | 674 super._internal(context, parameter); |
599 | 675 |
600 ParameterTypeInformation.static( | 676 ParameterTypeInformation.static( |
601 MemberTypeInformation context, ParameterElement parameter, this._method) | 677 MemberTypeInformation context, ParameterElement parameter, this._method) |
602 : _isInstanceMemberParameter = false, | 678 : _isInstanceMemberParameter = false, |
603 _isClosureParameter = false, | 679 _isClosureParameter = false, |
604 super._internal(context, parameter); | 680 super._internal(context, parameter); |
605 | 681 |
(...skipping 1195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1801 // TODO(ngeoffray): Narrow to bound. | 1877 // TODO(ngeoffray): Narrow to bound. |
1802 return type; | 1878 return type; |
1803 } else { | 1879 } else { |
1804 ResolutionInterfaceType interfaceType = annotation; | 1880 ResolutionInterfaceType interfaceType = annotation; |
1805 otherType = new TypeMask.nonNullSubtype(interfaceType.element, closedWorld); | 1881 otherType = new TypeMask.nonNullSubtype(interfaceType.element, closedWorld); |
1806 } | 1882 } |
1807 if (isNullable) otherType = otherType.nullable(); | 1883 if (isNullable) otherType = otherType.nullable(); |
1808 if (type == null) return otherType; | 1884 if (type == null) return otherType; |
1809 return type.intersection(otherType, closedWorld); | 1885 return type.intersection(otherType, closedWorld); |
1810 } | 1886 } |
OLD | NEW |