| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 dart2js.world; | 5 library dart2js.world; |
| 6 | 6 |
| 7 import 'closure.dart' show ClosureClassElement, SynthesizedCallMethodElementX; | 7 import 'closure.dart' show ClosureClassElement, SynthesizedCallMethodElementX; |
| 8 import 'common/backend_api.dart' show BackendClasses; | 8 import 'common/backend_api.dart' show BackendClasses; |
| 9 import 'common.dart'; | 9 import 'common.dart'; |
| 10 import 'constants/constant_system.dart'; | 10 import 'constants/constant_system.dart'; |
| 11 import 'core_types.dart' show CoreTypes, CoreClasses, CommonElements; | 11 import 'core_types.dart' show CommonElements; |
| 12 import 'dart_types.dart'; | 12 import 'dart_types.dart'; |
| 13 import 'elements/elements.dart' | 13 import 'elements/elements.dart' |
| 14 show | 14 show |
| 15 ClassElement, | 15 ClassElement, |
| 16 Element, | 16 Element, |
| 17 FunctionElement, | 17 FunctionElement, |
| 18 MixinApplicationElement, | 18 MixinApplicationElement, |
| 19 TypedefElement, | 19 TypedefElement, |
| 20 FieldElement; | 20 FieldElement; |
| 21 import 'js_backend/backend.dart' show JavaScriptBackend; | 21 import 'js_backend/backend.dart' show JavaScriptBackend; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 36 /// | 36 /// |
| 37 /// Given the entrypoint of an application, we can track what's reachable from | 37 /// Given the entrypoint of an application, we can track what's reachable from |
| 38 /// it, what functions are called, what classes are allocated, which native | 38 /// it, what functions are called, what classes are allocated, which native |
| 39 /// JavaScript types are touched, what language features are used, and so on. | 39 /// JavaScript types are touched, what language features are used, and so on. |
| 40 /// This precise knowledge about what's live in the program is later used in | 40 /// This precise knowledge about what's live in the program is later used in |
| 41 /// optimizations and other compiler decisions during code generation. | 41 /// optimizations and other compiler decisions during code generation. |
| 42 abstract class ClosedWorld implements World { | 42 abstract class ClosedWorld implements World { |
| 43 /// Access to core classes used by the backend. | 43 /// Access to core classes used by the backend. |
| 44 BackendClasses get backendClasses; | 44 BackendClasses get backendClasses; |
| 45 | 45 |
| 46 /// Access to core classes used in the Dart language. | |
| 47 CoreClasses get coreClasses; | |
| 48 | |
| 49 CoreTypes get coreTypes; | |
| 50 | |
| 51 CommonElements get commonElements; | 46 CommonElements get commonElements; |
| 52 | 47 |
| 53 CommonMasks get commonMasks; | 48 CommonMasks get commonMasks; |
| 54 | 49 |
| 55 ConstantSystem get constantSystem; | 50 ConstantSystem get constantSystem; |
| 56 | 51 |
| 57 /// Returns `true` if [cls] is either directly or indirectly instantiated. | 52 /// Returns `true` if [cls] is either directly or indirectly instantiated. |
| 58 bool isInstantiated(ClassElement cls); | 53 bool isInstantiated(ClassElement cls); |
| 59 | 54 |
| 60 /// Returns `true` if [cls] is directly instantiated. This means that at | 55 /// Returns `true` if [cls] is directly instantiated. This means that at |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 | 383 |
| 389 final Set<Element> elementsThatCannotThrow = new Set<Element>(); | 384 final Set<Element> elementsThatCannotThrow = new Set<Element>(); |
| 390 | 385 |
| 391 final Set<Element> functionsThatMightBePassedToApply = | 386 final Set<Element> functionsThatMightBePassedToApply = |
| 392 new Set<FunctionElement>(); | 387 new Set<FunctionElement>(); |
| 393 | 388 |
| 394 CommonMasks _commonMasks; | 389 CommonMasks _commonMasks; |
| 395 | 390 |
| 396 final CommonElements commonElements; | 391 final CommonElements commonElements; |
| 397 | 392 |
| 398 final CoreTypes coreTypes; | |
| 399 | |
| 400 final ResolutionWorldBuilder _resolverWorld; | 393 final ResolutionWorldBuilder _resolverWorld; |
| 401 | 394 |
| 402 bool get isClosed => true; | 395 bool get isClosed => true; |
| 403 | 396 |
| 404 ClosedWorldImpl( | 397 ClosedWorldImpl( |
| 405 {JavaScriptBackend backend, | 398 {JavaScriptBackend backend, |
| 406 this.commonElements, | 399 this.commonElements, |
| 407 this.coreTypes, | |
| 408 ResolutionWorldBuilder resolverWorld, | 400 ResolutionWorldBuilder resolverWorld, |
| 409 FunctionSetBuilder functionSetBuilder, | 401 FunctionSetBuilder functionSetBuilder, |
| 410 Iterable<TypedefElement> allTypedefs, | 402 Iterable<TypedefElement> allTypedefs, |
| 411 Map<ClassElement, Set<MixinApplicationElement>> mixinUses, | 403 Map<ClassElement, Set<MixinApplicationElement>> mixinUses, |
| 412 Map<ClassElement, Set<ClassElement>> typesImplementedBySubclasses, | 404 Map<ClassElement, Set<ClassElement>> typesImplementedBySubclasses, |
| 413 Map<ClassElement, ClassHierarchyNode> classHierarchyNodes, | 405 Map<ClassElement, ClassHierarchyNode> classHierarchyNodes, |
| 414 Map<ClassElement, ClassSet> classSets}) | 406 Map<ClassElement, ClassSet> classSets}) |
| 415 : this._backend = backend, | 407 : this._backend = backend, |
| 416 this._resolverWorld = resolverWorld, | 408 this._resolverWorld = resolverWorld, |
| 417 this._allTypedefs = allTypedefs, | 409 this._allTypedefs = allTypedefs, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 428 final List<Map<ClassElement, TypeMask>> _canonicalizedTypeMasks = | 420 final List<Map<ClassElement, TypeMask>> _canonicalizedTypeMasks = |
| 429 new List<Map<ClassElement, TypeMask>>.filled(8, null); | 421 new List<Map<ClassElement, TypeMask>>.filled(8, null); |
| 430 | 422 |
| 431 FunctionSet get allFunctions => _allFunctions; | 423 FunctionSet get allFunctions => _allFunctions; |
| 432 | 424 |
| 433 CommonMasks get commonMasks { | 425 CommonMasks get commonMasks { |
| 434 assert(isClosed); | 426 assert(isClosed); |
| 435 return _commonMasks; | 427 return _commonMasks; |
| 436 } | 428 } |
| 437 | 429 |
| 438 CoreClasses get coreClasses => commonElements; | |
| 439 | |
| 440 ConstantSystem get constantSystem => _backend.constantSystem; | 430 ConstantSystem get constantSystem => _backend.constantSystem; |
| 441 | 431 |
| 442 TypeMask getCachedMask(ClassElement base, int flags, TypeMask createMask()) { | 432 TypeMask getCachedMask(ClassElement base, int flags, TypeMask createMask()) { |
| 443 Map<ClassElement, TypeMask> cachedMasks = | 433 Map<ClassElement, TypeMask> cachedMasks = |
| 444 _canonicalizedTypeMasks[flags] ??= <ClassElement, TypeMask>{}; | 434 _canonicalizedTypeMasks[flags] ??= <ClassElement, TypeMask>{}; |
| 445 return cachedMasks.putIfAbsent(base, createMask); | 435 return cachedMasks.putIfAbsent(base, createMask); |
| 446 } | 436 } |
| 447 | 437 |
| 448 bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { | 438 bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { |
| 449 return invariant(cls, cls.isDeclaration, | 439 return invariant(cls, cls.isDeclaration, |
| 450 message: '$cls must be the declaration.') && | 440 message: '$cls must be the declaration.') && |
| 451 invariant(cls, cls.isResolved, | 441 invariant(cls, cls.isResolved, |
| 452 message: | 442 message: |
| 453 '$cls must be resolved.') /* && | 443 '$cls must be resolved.') /* && |
| 454 // TODO(johnniwinther): Reinsert this or similar invariant. | 444 // TODO(johnniwinther): Reinsert this or similar invariant. |
| 455 (!mustBeInstantiated || | 445 (!mustBeInstantiated || |
| 456 invariant(cls, isInstantiated(cls), | 446 invariant(cls, isInstantiated(cls), |
| 457 message: '$cls is not instantiated.'))*/ | 447 message: '$cls is not instantiated.'))*/ |
| 458 ; | 448 ; |
| 459 } | 449 } |
| 460 | 450 |
| 461 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an | 451 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an |
| 462 /// instance of [y]. | 452 /// instance of [y]. |
| 463 bool isSubtypeOf(ClassElement x, ClassElement y) { | 453 bool isSubtypeOf(ClassElement x, ClassElement y) { |
| 464 assert(isClosed); | 454 assert(isClosed); |
| 465 assert(checkInvariants(x)); | 455 assert(checkInvariants(x)); |
| 466 assert(checkInvariants(y, mustBeInstantiated: false)); | 456 assert(checkInvariants(y, mustBeInstantiated: false)); |
| 467 | 457 |
| 468 if (y == coreClasses.objectClass) return true; | 458 if (y == commonElements.objectClass) return true; |
| 469 if (x == coreClasses.objectClass) return false; | 459 if (x == commonElements.objectClass) return false; |
| 470 if (x.asInstanceOf(y) != null) return true; | 460 if (x.asInstanceOf(y) != null) return true; |
| 471 if (y != coreClasses.functionClass) return false; | 461 if (y != commonElements.functionClass) return false; |
| 472 return x.callType != null; | 462 return x.callType != null; |
| 473 } | 463 } |
| 474 | 464 |
| 475 /// Return `true` if [x] is a (non-strict) subclass of [y]. | 465 /// Return `true` if [x] is a (non-strict) subclass of [y]. |
| 476 bool isSubclassOf(ClassElement x, ClassElement y) { | 466 bool isSubclassOf(ClassElement x, ClassElement y) { |
| 477 assert(isClosed); | 467 assert(isClosed); |
| 478 assert(checkInvariants(x)); | 468 assert(checkInvariants(x)); |
| 479 assert(checkInvariants(y)); | 469 assert(checkInvariants(y)); |
| 480 | 470 |
| 481 if (y == coreClasses.objectClass) return true; | 471 if (y == commonElements.objectClass) return true; |
| 482 if (x == coreClasses.objectClass) return false; | 472 if (x == commonElements.objectClass) return false; |
| 483 while (x != null && x.hierarchyDepth >= y.hierarchyDepth) { | 473 while (x != null && x.hierarchyDepth >= y.hierarchyDepth) { |
| 484 if (x == y) return true; | 474 if (x == y) return true; |
| 485 x = x.superclass; | 475 x = x.superclass; |
| 486 } | 476 } |
| 487 return false; | 477 return false; |
| 488 } | 478 } |
| 489 | 479 |
| 490 @override | 480 @override |
| 491 bool isInstantiated(ClassElement cls) { | 481 bool isInstantiated(ClassElement cls) { |
| 492 assert(isClosed); | 482 assert(isClosed); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 /// implements [cls]. | 659 /// implements [cls]. |
| 670 bool hasAnyStrictSubtype(ClassElement cls) { | 660 bool hasAnyStrictSubtype(ClassElement cls) { |
| 671 return strictSubtypeCount(cls) > 0; | 661 return strictSubtypeCount(cls) > 0; |
| 672 } | 662 } |
| 673 | 663 |
| 674 /// Returns `true` if all directly instantiated classes that implement [cls] | 664 /// Returns `true` if all directly instantiated classes that implement [cls] |
| 675 /// extend it. | 665 /// extend it. |
| 676 bool hasOnlySubclasses(ClassElement cls) { | 666 bool hasOnlySubclasses(ClassElement cls) { |
| 677 assert(isClosed); | 667 assert(isClosed); |
| 678 // TODO(johnniwinther): move this to ClassSet? | 668 // TODO(johnniwinther): move this to ClassSet? |
| 679 if (cls == coreClasses.objectClass) return true; | 669 if (cls == commonElements.objectClass) return true; |
| 680 ClassSet classSet = _classSets[cls.declaration]; | 670 ClassSet classSet = _classSets[cls.declaration]; |
| 681 if (classSet == null) { | 671 if (classSet == null) { |
| 682 // Vacuously true. | 672 // Vacuously true. |
| 683 return true; | 673 return true; |
| 684 } | 674 } |
| 685 return classSet.hasOnlyInstantiatedSubclasses; | 675 return classSet.hasOnlyInstantiatedSubclasses; |
| 686 } | 676 } |
| 687 | 677 |
| 688 @override | 678 @override |
| 689 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { | 679 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 OrderedTypeSet otherTypeSet = otherClass.allSupertypesAndSelf; | 716 OrderedTypeSet otherTypeSet = otherClass.allSupertypesAndSelf; |
| 727 otherTypeSets = otherTypeSets.prepend(otherTypeSet); | 717 otherTypeSets = otherTypeSets.prepend(otherTypeSet); |
| 728 if (otherTypeSet.maxDepth < depth) { | 718 if (otherTypeSet.maxDepth < depth) { |
| 729 depth = otherTypeSet.maxDepth; | 719 depth = otherTypeSet.maxDepth; |
| 730 } | 720 } |
| 731 } while (iterator.moveNext()); | 721 } while (iterator.moveNext()); |
| 732 | 722 |
| 733 List<ClassElement> commonSupertypes = <ClassElement>[]; | 723 List<ClassElement> commonSupertypes = <ClassElement>[]; |
| 734 OUTER: | 724 OUTER: |
| 735 for (Link<DartType> link = typeSet[depth]; | 725 for (Link<DartType> link = typeSet[depth]; |
| 736 link.head.element != coreClasses.objectClass; | 726 link.head.element != commonElements.objectClass; |
| 737 link = link.tail) { | 727 link = link.tail) { |
| 738 ClassElement cls = link.head.element; | 728 ClassElement cls = link.head.element; |
| 739 for (Link<OrderedTypeSet> link = otherTypeSets; | 729 for (Link<OrderedTypeSet> link = otherTypeSets; |
| 740 !link.isEmpty; | 730 !link.isEmpty; |
| 741 link = link.tail) { | 731 link = link.tail) { |
| 742 if (link.head.asInstanceOf(cls) == null) { | 732 if (link.head.asInstanceOf(cls) == null) { |
| 743 continue OUTER; | 733 continue OUTER; |
| 744 } | 734 } |
| 745 } | 735 } |
| 746 commonSupertypes.add(cls); | 736 commonSupertypes.add(cls); |
| 747 } | 737 } |
| 748 commonSupertypes.add(coreClasses.objectClass); | 738 commonSupertypes.add(commonElements.objectClass); |
| 749 return commonSupertypes; | 739 return commonSupertypes; |
| 750 } | 740 } |
| 751 | 741 |
| 752 /// Returns an iterable over the live mixin applications that mixin [cls]. | 742 /// Returns an iterable over the live mixin applications that mixin [cls]. |
| 753 Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls) { | 743 Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls) { |
| 754 assert(isClosed); | 744 assert(isClosed); |
| 755 if (_liveMixinUses == null) { | 745 if (_liveMixinUses == null) { |
| 756 _liveMixinUses = new Map<ClassElement, List<MixinApplicationElement>>(); | 746 _liveMixinUses = new Map<ClassElement, List<MixinApplicationElement>>(); |
| 757 for (ClassElement mixin in _mixinUses.keys) { | 747 for (ClassElement mixin in _mixinUses.keys) { |
| 758 List<MixinApplicationElement> uses = <MixinApplicationElement>[]; | 748 List<MixinApplicationElement> uses = <MixinApplicationElement>[]; |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 971 Iterable<TypedefElement> get allTypedefs => _allTypedefs; | 961 Iterable<TypedefElement> get allTypedefs => _allTypedefs; |
| 972 | 962 |
| 973 @override | 963 @override |
| 974 String dump([ClassElement cls]) { | 964 String dump([ClassElement cls]) { |
| 975 StringBuffer sb = new StringBuffer(); | 965 StringBuffer sb = new StringBuffer(); |
| 976 if (cls != null) { | 966 if (cls != null) { |
| 977 sb.write("Classes in the closed world related to $cls:\n"); | 967 sb.write("Classes in the closed world related to $cls:\n"); |
| 978 } else { | 968 } else { |
| 979 sb.write("Instantiated classes in the closed world:\n"); | 969 sb.write("Instantiated classes in the closed world:\n"); |
| 980 } | 970 } |
| 981 getClassHierarchyNode(coreClasses.objectClass) | 971 getClassHierarchyNode(commonElements.objectClass) |
| 982 .printOn(sb, ' ', instantiatedOnly: cls == null, withRespectTo: cls); | 972 .printOn(sb, ' ', instantiatedOnly: cls == null, withRespectTo: cls); |
| 983 return sb.toString(); | 973 return sb.toString(); |
| 984 } | 974 } |
| 985 | 975 |
| 986 bool hasAnyUserDefinedGetter(Selector selector, TypeMask mask) { | 976 bool hasAnyUserDefinedGetter(Selector selector, TypeMask mask) { |
| 987 return allFunctions.filter(selector, mask).any((each) => each.isGetter); | 977 return allFunctions.filter(selector, mask).any((each) => each.isGetter); |
| 988 } | 978 } |
| 989 | 979 |
| 990 FieldElement locateSingleField(Selector selector, TypeMask mask) { | 980 FieldElement locateSingleField(Selector selector, TypeMask mask) { |
| 991 Element result = locateSingleElement(selector, mask); | 981 Element result = locateSingleElement(selector, mask); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 return getMightBePassedToApply(element.expression); | 1102 return getMightBePassedToApply(element.expression); |
| 1113 } | 1103 } |
| 1114 return functionsThatMightBePassedToApply.contains(element); | 1104 return functionsThatMightBePassedToApply.contains(element); |
| 1115 } | 1105 } |
| 1116 | 1106 |
| 1117 @override | 1107 @override |
| 1118 bool getCurrentlyKnownMightBePassedToApply(Element element) { | 1108 bool getCurrentlyKnownMightBePassedToApply(Element element) { |
| 1119 return getMightBePassedToApply(element); | 1109 return getMightBePassedToApply(element); |
| 1120 } | 1110 } |
| 1121 } | 1111 } |
| OLD | NEW |