| 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.dart'; | 8 import 'common.dart'; |
| 9 import 'constants/constant_system.dart'; | 9 import 'constants/constant_system.dart'; |
| 10 import 'common_elements.dart' show CommonElements; | 10 import 'common_elements.dart' show CommonElements; |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 } | 396 } |
| 397 | 397 |
| 398 abstract class ClosedWorldBase implements ClosedWorld, ClosedWorldRefiner { | 398 abstract class ClosedWorldBase implements ClosedWorld, ClosedWorldRefiner { |
| 399 final ConstantSystem constantSystem; | 399 final ConstantSystem constantSystem; |
| 400 final NativeData nativeData; | 400 final NativeData nativeData; |
| 401 final InterceptorData interceptorData; | 401 final InterceptorData interceptorData; |
| 402 final BackendUsage backendUsage; | 402 final BackendUsage backendUsage; |
| 403 | 403 |
| 404 final FunctionSet _allFunctions; | 404 final FunctionSet _allFunctions; |
| 405 | 405 |
| 406 final Iterable<TypedefElement> _allTypedefs; | 406 final Set<TypedefElement> _allTypedefs; |
| 407 | 407 |
| 408 final Map<ClassEntity, Set<ClassEntity>> _mixinUses; | 408 final Map<ClassEntity, Set<ClassEntity>> _mixinUses; |
| 409 Map<ClassEntity, List<ClassEntity>> _liveMixinUses; | 409 Map<ClassEntity, List<ClassEntity>> _liveMixinUses; |
| 410 | 410 |
| 411 final Map<ClassEntity, Set<ClassEntity>> _typesImplementedBySubclasses; | 411 final Map<ClassEntity, Set<ClassEntity>> _typesImplementedBySubclasses; |
| 412 | 412 |
| 413 // We keep track of subtype and subclass relationships in four | 413 // We keep track of subtype and subclass relationships in four |
| 414 // distinct sets to make class hierarchy analysis faster. | 414 // distinct sets to make class hierarchy analysis faster. |
| 415 final Map<ClassEntity, ClassHierarchyNode> _classHierarchyNodes; | 415 final Map<ClassEntity, ClassHierarchyNode> _classHierarchyNodes; |
| 416 final Map<ClassEntity, ClassSet> _classSets; | 416 final Map<ClassEntity, ClassSet> _classSets; |
| 417 | 417 |
| 418 final Map<ClassEntity, Map<ClassEntity, bool>> _subtypeCoveredByCache = | 418 final Map<ClassEntity, Map<ClassEntity, bool>> _subtypeCoveredByCache = |
| 419 <ClassEntity, Map<ClassEntity, bool>>{}; | 419 <ClassEntity, Map<ClassEntity, bool>>{}; |
| 420 | 420 |
| 421 final Set<Entity> _functionsCalledInLoop = new Set<Entity>(); | 421 final Set<Entity> _functionsCalledInLoop = new Set<Entity>(); |
| 422 final Map<Entity, SideEffects> _sideEffects = new Map<Entity, SideEffects>(); | 422 final Map<Entity, SideEffects> _sideEffects = new Map<Entity, SideEffects>(); |
| 423 | 423 |
| 424 final Set<Entity> _sideEffectsFreeElements = new Set<Entity>(); | 424 final Set<Entity> _sideEffectsFreeElements = new Set<Entity>(); |
| 425 | 425 |
| 426 final Set<Entity> _elementsThatCannotThrow = new Set<Entity>(); | 426 final Set<Entity> _elementsThatCannotThrow = new Set<Entity>(); |
| 427 | 427 |
| 428 final Set<Entity> _functionsThatMightBePassedToApply = new Set<Entity>(); | 428 final Set<Entity> _functionsThatMightBePassedToApply = new Set<Entity>(); |
| 429 | 429 |
| 430 CommonMasks _commonMasks; | 430 CommonMasks _commonMasks; |
| 431 | 431 |
| 432 final CommonElements commonElements; | 432 final CommonElements commonElements; |
| 433 | 433 |
| 434 // TODO(johnniwinther): Avoid this. |
| 434 final ResolutionWorldBuilder _resolverWorld; | 435 final ResolutionWorldBuilder _resolverWorld; |
| 435 | 436 |
| 437 // TODO(johnniwinther): Can this be derived from [ClassSet]s? |
| 438 final Set<ClassEntity> _implementedClasses; |
| 439 |
| 436 ClosedWorldBase( | 440 ClosedWorldBase( |
| 437 {this.commonElements, | 441 {this.commonElements, |
| 438 this.constantSystem, | 442 this.constantSystem, |
| 439 this.nativeData, | 443 this.nativeData, |
| 440 this.interceptorData, | 444 this.interceptorData, |
| 441 this.backendUsage, | 445 this.backendUsage, |
| 442 ResolutionWorldBuilder resolutionWorldBuilder, | 446 ResolutionWorldBuilder resolutionWorldBuilder, |
| 447 Set<ClassEntity> implementedClasses, |
| 443 FunctionSet functionSet, | 448 FunctionSet functionSet, |
| 444 Iterable<TypedefElement> allTypedefs, | 449 Set<TypedefElement> allTypedefs, |
| 445 Map<ClassEntity, Set<ClassEntity>> mixinUses, | 450 Map<ClassEntity, Set<ClassEntity>> mixinUses, |
| 446 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, | 451 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, |
| 447 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, | 452 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, |
| 448 Map<ClassEntity, ClassSet> classSets}) | 453 Map<ClassEntity, ClassSet> classSets}) |
| 449 : this._resolverWorld = resolutionWorldBuilder, | 454 : this._resolverWorld = resolutionWorldBuilder, |
| 455 this._implementedClasses = implementedClasses, |
| 450 this._allFunctions = functionSet, | 456 this._allFunctions = functionSet, |
| 451 this._allTypedefs = allTypedefs, | 457 this._allTypedefs = allTypedefs, |
| 452 this._mixinUses = mixinUses, | 458 this._mixinUses = mixinUses, |
| 453 this._typesImplementedBySubclasses = typesImplementedBySubclasses, | 459 this._typesImplementedBySubclasses = typesImplementedBySubclasses, |
| 454 this._classHierarchyNodes = classHierarchyNodes, | 460 this._classHierarchyNodes = classHierarchyNodes, |
| 455 this._classSets = classSets { | 461 this._classSets = classSets { |
| 456 _commonMasks = new CommonMasks(this); | 462 _commonMasks = new CommonMasks(this); |
| 457 } | 463 } |
| 458 | 464 |
| 459 @override | 465 @override |
| 460 ClosedWorld get closedWorld => this; | 466 ClosedWorld get closedWorld => this; |
| 461 | 467 |
| 462 /// Cache of [FlatTypeMask]s grouped by the 8 possible values of the | 468 /// Cache of [FlatTypeMask]s grouped by the 8 possible values of the |
| 463 /// `FlatTypeMask.flags` property. | 469 /// `FlatTypeMask.flags` property. |
| 464 final List<Map<ClassEntity, TypeMask>> _canonicalizedTypeMasks = | 470 final List<Map<ClassEntity, TypeMask>> _canonicalizedTypeMasks = |
| 465 new List<Map<ClassEntity, TypeMask>>.filled(8, null); | 471 new List<Map<ClassEntity, TypeMask>>.filled(8, null); |
| 466 | 472 |
| 467 CommonMasks get commonMasks { | 473 CommonMasks get commonMasks { |
| 468 return _commonMasks; | 474 return _commonMasks; |
| 469 } | 475 } |
| 470 | 476 |
| 471 TypeMask getCachedMask(ClassEntity base, int flags, TypeMask createMask()) { | 477 TypeMask getCachedMask(ClassEntity base, int flags, TypeMask createMask()) { |
| 472 Map<ClassEntity, TypeMask> cachedMasks = | 478 Map<ClassEntity, TypeMask> cachedMasks = |
| 473 _canonicalizedTypeMasks[flags] ??= <ClassEntity, TypeMask>{}; | 479 _canonicalizedTypeMasks[flags] ??= <ClassEntity, TypeMask>{}; |
| 474 return cachedMasks.putIfAbsent(base, createMask); | 480 return cachedMasks.putIfAbsent(base, createMask); |
| 475 } | 481 } |
| 476 | 482 |
| 477 bool _checkEntity(Entity element); | 483 bool checkEntity(Entity element); |
| 478 | 484 |
| 479 bool _checkClass(ClassEntity cls); | 485 bool checkClass(ClassEntity cls); |
| 480 | 486 |
| 481 bool _checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true}); | 487 bool checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true}); |
| 482 | 488 |
| 483 OrderedTypeSet _getOrderedTypeSet(ClassEntity cls); | 489 OrderedTypeSet getOrderedTypeSet(ClassEntity cls); |
| 484 | 490 |
| 485 int _getHierarchyDepth(ClassEntity cls); | 491 int getHierarchyDepth(ClassEntity cls); |
| 486 | 492 |
| 487 ClassEntity _getSuperClass(ClassEntity cls); | 493 ClassEntity getSuperClass(ClassEntity cls); |
| 488 | 494 |
| 489 Iterable<ClassEntity> _getInterfaces(ClassEntity cls); | 495 Iterable<ClassEntity> getInterfaces(ClassEntity cls); |
| 490 | 496 |
| 491 ClassEntity _getAppliedMixin(ClassEntity cls); | 497 ClassEntity getAppliedMixin(ClassEntity cls); |
| 492 | 498 |
| 493 bool _isNamedMixinApplication(ClassEntity cls); | 499 bool isNamedMixinApplication(ClassEntity cls); |
| 494 | 500 |
| 495 @override | 501 @override |
| 496 bool isInstantiated(ClassEntity cls) { | 502 bool isInstantiated(ClassEntity cls) { |
| 497 assert(_checkClass(cls)); | 503 assert(checkClass(cls)); |
| 498 ClassHierarchyNode node = _classHierarchyNodes[cls]; | 504 ClassHierarchyNode node = _classHierarchyNodes[cls]; |
| 499 return node != null && node.isInstantiated; | 505 return node != null && node.isInstantiated; |
| 500 } | 506 } |
| 501 | 507 |
| 502 @override | 508 @override |
| 503 bool isDirectlyInstantiated(ClassEntity cls) { | 509 bool isDirectlyInstantiated(ClassEntity cls) { |
| 504 assert(_checkClass(cls)); | 510 assert(checkClass(cls)); |
| 505 ClassHierarchyNode node = _classHierarchyNodes[cls]; | 511 ClassHierarchyNode node = _classHierarchyNodes[cls]; |
| 506 return node != null && node.isDirectlyInstantiated; | 512 return node != null && node.isDirectlyInstantiated; |
| 507 } | 513 } |
| 508 | 514 |
| 509 @override | 515 @override |
| 510 bool isAbstractlyInstantiated(ClassEntity cls) { | 516 bool isAbstractlyInstantiated(ClassEntity cls) { |
| 511 assert(_checkClass(cls)); | 517 assert(checkClass(cls)); |
| 512 ClassHierarchyNode node = _classHierarchyNodes[cls]; | 518 ClassHierarchyNode node = _classHierarchyNodes[cls]; |
| 513 return node != null && node.isAbstractlyInstantiated; | 519 return node != null && node.isAbstractlyInstantiated; |
| 514 } | 520 } |
| 515 | 521 |
| 516 @override | 522 @override |
| 517 bool isExplicitlyInstantiated(ClassEntity cls) { | 523 bool isExplicitlyInstantiated(ClassEntity cls) { |
| 518 assert(_checkClass(cls)); | 524 assert(checkClass(cls)); |
| 519 ClassHierarchyNode node = _classHierarchyNodes[cls]; | 525 ClassHierarchyNode node = _classHierarchyNodes[cls]; |
| 520 return node != null && node.isExplicitlyInstantiated; | 526 return node != null && node.isExplicitlyInstantiated; |
| 521 } | 527 } |
| 522 | 528 |
| 523 @override | 529 @override |
| 524 bool isIndirectlyInstantiated(ClassEntity cls) { | 530 bool isIndirectlyInstantiated(ClassEntity cls) { |
| 525 assert(_checkClass(cls)); | 531 assert(checkClass(cls)); |
| 526 ClassHierarchyNode node = _classHierarchyNodes[cls]; | 532 ClassHierarchyNode node = _classHierarchyNodes[cls]; |
| 527 return node != null && node.isIndirectlyInstantiated; | 533 return node != null && node.isIndirectlyInstantiated; |
| 528 } | 534 } |
| 529 | 535 |
| 530 @override | 536 @override |
| 531 bool isAbstract(ClassEntity cls) => cls.isAbstract; | 537 bool isAbstract(ClassEntity cls) => cls.isAbstract; |
| 532 | 538 |
| 533 /// Returns `true` if [cls] is implemented by an instantiated class. | 539 /// Returns `true` if [cls] is implemented by an instantiated class. |
| 534 bool isImplemented(ClassEntity cls) { | 540 bool isImplemented(ClassEntity cls) { |
| 535 return _resolverWorld.isImplemented(cls); | 541 return _implementedClasses.contains(cls); |
| 536 } | 542 } |
| 537 | 543 |
| 538 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an | 544 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an |
| 539 /// instance of [y]. | 545 /// instance of [y]. |
| 540 bool isSubtypeOf(ClassEntity x, ClassEntity y) { | 546 bool isSubtypeOf(ClassEntity x, ClassEntity y) { |
| 541 assert(_checkInvariants(x)); | 547 assert(checkInvariants(x)); |
| 542 assert(_checkInvariants(y, mustBeInstantiated: false)); | 548 assert(checkInvariants(y, mustBeInstantiated: false)); |
| 543 return _classSets[y].hasSubtype(_classHierarchyNodes[x]); | 549 return _classSets[y].hasSubtype(_classHierarchyNodes[x]); |
| 544 } | 550 } |
| 545 | 551 |
| 546 /// Return `true` if [x] is a (non-strict) subclass of [y]. | 552 /// Return `true` if [x] is a (non-strict) subclass of [y]. |
| 547 bool isSubclassOf(ClassEntity x, ClassEntity y) { | 553 bool isSubclassOf(ClassEntity x, ClassEntity y) { |
| 548 assert(_checkInvariants(x)); | 554 assert(checkInvariants(x)); |
| 549 assert(_checkInvariants(y)); | 555 assert(checkInvariants(y)); |
| 550 return _classHierarchyNodes[y].hasSubclass(_classHierarchyNodes[x]); | 556 return _classHierarchyNodes[y].hasSubclass(_classHierarchyNodes[x]); |
| 551 } | 557 } |
| 552 | 558 |
| 553 /// Returns an iterable over the directly instantiated classes that extend | 559 /// Returns an iterable over the directly instantiated classes that extend |
| 554 /// [cls] possibly including [cls] itself, if it is live. | 560 /// [cls] possibly including [cls] itself, if it is live. |
| 555 Iterable<ClassEntity> subclassesOf(ClassEntity cls) { | 561 Iterable<ClassEntity> subclassesOf(ClassEntity cls) { |
| 556 assert(_checkClass(cls)); | 562 assert(checkClass(cls)); |
| 557 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls]; | 563 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls]; |
| 558 if (hierarchy == null) return const <ClassEntity>[]; | 564 if (hierarchy == null) return const <ClassEntity>[]; |
| 559 return hierarchy | 565 return hierarchy |
| 560 .subclassesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED); | 566 .subclassesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED); |
| 561 } | 567 } |
| 562 | 568 |
| 563 /// Returns an iterable over the directly instantiated classes that extend | 569 /// Returns an iterable over the directly instantiated classes that extend |
| 564 /// [cls] _not_ including [cls] itself. | 570 /// [cls] _not_ including [cls] itself. |
| 565 Iterable<ClassEntity> strictSubclassesOf(ClassEntity cls) { | 571 Iterable<ClassEntity> strictSubclassesOf(ClassEntity cls) { |
| 566 assert(_checkClass(cls)); | 572 assert(checkClass(cls)); |
| 567 ClassHierarchyNode subclasses = _classHierarchyNodes[cls]; | 573 ClassHierarchyNode subclasses = _classHierarchyNodes[cls]; |
| 568 if (subclasses == null) return const <ClassEntity>[]; | 574 if (subclasses == null) return const <ClassEntity>[]; |
| 569 return subclasses.subclassesByMask( | 575 return subclasses.subclassesByMask( |
| 570 ClassHierarchyNode.EXPLICITLY_INSTANTIATED, | 576 ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
| 571 strict: true); | 577 strict: true); |
| 572 } | 578 } |
| 573 | 579 |
| 574 /// Returns the number of live classes that extend [cls] _not_ | 580 /// Returns the number of live classes that extend [cls] _not_ |
| 575 /// including [cls] itself. | 581 /// including [cls] itself. |
| 576 int strictSubclassCount(ClassEntity cls) { | 582 int strictSubclassCount(ClassEntity cls) { |
| 577 assert(_checkClass(cls)); | 583 assert(checkClass(cls)); |
| 578 ClassHierarchyNode subclasses = _classHierarchyNodes[cls]; | 584 ClassHierarchyNode subclasses = _classHierarchyNodes[cls]; |
| 579 if (subclasses == null) return 0; | 585 if (subclasses == null) return 0; |
| 580 return subclasses.instantiatedSubclassCount; | 586 return subclasses.instantiatedSubclassCount; |
| 581 } | 587 } |
| 582 | 588 |
| 583 /// Applies [f] to each live class that extend [cls] _not_ including [cls] | 589 /// Applies [f] to each live class that extend [cls] _not_ including [cls] |
| 584 /// itself. | 590 /// itself. |
| 585 void forEachStrictSubclassOf( | 591 void forEachStrictSubclassOf( |
| 586 ClassEntity cls, IterationStep f(ClassEntity cls)) { | 592 ClassEntity cls, IterationStep f(ClassEntity cls)) { |
| 587 assert(_checkClass(cls)); | 593 assert(checkClass(cls)); |
| 588 ClassHierarchyNode subclasses = _classHierarchyNodes[cls]; | 594 ClassHierarchyNode subclasses = _classHierarchyNodes[cls]; |
| 589 if (subclasses == null) return; | 595 if (subclasses == null) return; |
| 590 subclasses.forEachSubclass(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, | 596 subclasses.forEachSubclass(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
| 591 strict: true); | 597 strict: true); |
| 592 } | 598 } |
| 593 | 599 |
| 594 /// Returns `true` if [predicate] applies to any live class that extend [cls] | 600 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
| 595 /// _not_ including [cls] itself. | 601 /// _not_ including [cls] itself. |
| 596 bool anyStrictSubclassOf(ClassEntity cls, bool predicate(ClassEntity cls)) { | 602 bool anyStrictSubclassOf(ClassEntity cls, bool predicate(ClassEntity cls)) { |
| 597 assert(_checkClass(cls)); | 603 assert(checkClass(cls)); |
| 598 ClassHierarchyNode subclasses = _classHierarchyNodes[cls]; | 604 ClassHierarchyNode subclasses = _classHierarchyNodes[cls]; |
| 599 if (subclasses == null) return false; | 605 if (subclasses == null) return false; |
| 600 return subclasses.anySubclass( | 606 return subclasses.anySubclass( |
| 601 predicate, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, | 607 predicate, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
| 602 strict: true); | 608 strict: true); |
| 603 } | 609 } |
| 604 | 610 |
| 605 /// Returns an iterable over the directly instantiated that implement [cls] | 611 /// Returns an iterable over the directly instantiated that implement [cls] |
| 606 /// possibly including [cls] itself, if it is live. | 612 /// possibly including [cls] itself, if it is live. |
| 607 Iterable<ClassEntity> subtypesOf(ClassEntity cls) { | 613 Iterable<ClassEntity> subtypesOf(ClassEntity cls) { |
| 608 assert(_checkClass(cls)); | 614 assert(checkClass(cls)); |
| 609 ClassSet classSet = _classSets[cls]; | 615 ClassSet classSet = _classSets[cls]; |
| 610 if (classSet == null) { | 616 if (classSet == null) { |
| 611 return const <ClassEntity>[]; | 617 return const <ClassEntity>[]; |
| 612 } else { | 618 } else { |
| 613 return classSet | 619 return classSet |
| 614 .subtypesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED); | 620 .subtypesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED); |
| 615 } | 621 } |
| 616 } | 622 } |
| 617 | 623 |
| 618 /// Returns an iterable over the directly instantiated that implement [cls] | 624 /// Returns an iterable over the directly instantiated that implement [cls] |
| 619 /// _not_ including [cls]. | 625 /// _not_ including [cls]. |
| 620 Iterable<ClassEntity> strictSubtypesOf(ClassEntity cls) { | 626 Iterable<ClassEntity> strictSubtypesOf(ClassEntity cls) { |
| 621 assert(_checkClass(cls)); | 627 assert(checkClass(cls)); |
| 622 ClassSet classSet = _classSets[cls]; | 628 ClassSet classSet = _classSets[cls]; |
| 623 if (classSet == null) { | 629 if (classSet == null) { |
| 624 return const <ClassEntity>[]; | 630 return const <ClassEntity>[]; |
| 625 } else { | 631 } else { |
| 626 return classSet.subtypesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED, | 632 return classSet.subtypesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
| 627 strict: true); | 633 strict: true); |
| 628 } | 634 } |
| 629 } | 635 } |
| 630 | 636 |
| 631 /// Returns the number of live classes that implement [cls] _not_ | 637 /// Returns the number of live classes that implement [cls] _not_ |
| 632 /// including [cls] itself. | 638 /// including [cls] itself. |
| 633 int strictSubtypeCount(ClassEntity cls) { | 639 int strictSubtypeCount(ClassEntity cls) { |
| 634 assert(_checkClass(cls)); | 640 assert(checkClass(cls)); |
| 635 ClassSet classSet = _classSets[cls]; | 641 ClassSet classSet = _classSets[cls]; |
| 636 if (classSet == null) return 0; | 642 if (classSet == null) return 0; |
| 637 return classSet.instantiatedSubtypeCount; | 643 return classSet.instantiatedSubtypeCount; |
| 638 } | 644 } |
| 639 | 645 |
| 640 /// Applies [f] to each live class that implements [cls] _not_ including [cls] | 646 /// Applies [f] to each live class that implements [cls] _not_ including [cls] |
| 641 /// itself. | 647 /// itself. |
| 642 void forEachStrictSubtypeOf( | 648 void forEachStrictSubtypeOf( |
| 643 ClassEntity cls, IterationStep f(ClassEntity cls)) { | 649 ClassEntity cls, IterationStep f(ClassEntity cls)) { |
| 644 assert(_checkClass(cls)); | 650 assert(checkClass(cls)); |
| 645 ClassSet classSet = _classSets[cls]; | 651 ClassSet classSet = _classSets[cls]; |
| 646 if (classSet == null) return; | 652 if (classSet == null) return; |
| 647 classSet.forEachSubtype(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, | 653 classSet.forEachSubtype(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
| 648 strict: true); | 654 strict: true); |
| 649 } | 655 } |
| 650 | 656 |
| 651 /// Returns `true` if [predicate] applies to any live class that extend [cls] | 657 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
| 652 /// _not_ including [cls] itself. | 658 /// _not_ including [cls] itself. |
| 653 bool anyStrictSubtypeOf(ClassEntity cls, bool predicate(ClassEntity cls)) { | 659 bool anyStrictSubtypeOf(ClassEntity cls, bool predicate(ClassEntity cls)) { |
| 654 assert(_checkClass(cls)); | 660 assert(checkClass(cls)); |
| 655 ClassSet classSet = _classSets[cls]; | 661 ClassSet classSet = _classSets[cls]; |
| 656 if (classSet == null) return false; | 662 if (classSet == null) return false; |
| 657 return classSet.anySubtype( | 663 return classSet.anySubtype( |
| 658 predicate, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, | 664 predicate, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, |
| 659 strict: true); | 665 strict: true); |
| 660 } | 666 } |
| 661 | 667 |
| 662 /// Returns `true` if [a] and [b] have any known common subtypes. | 668 /// Returns `true` if [a] and [b] have any known common subtypes. |
| 663 bool haveAnyCommonSubtypes(ClassEntity a, ClassEntity b) { | 669 bool haveAnyCommonSubtypes(ClassEntity a, ClassEntity b) { |
| 664 assert(_checkClass(a)); | 670 assert(checkClass(a)); |
| 665 assert(_checkClass(b)); | 671 assert(checkClass(b)); |
| 666 ClassSet classSetA = _classSets[a]; | 672 ClassSet classSetA = _classSets[a]; |
| 667 ClassSet classSetB = _classSets[b]; | 673 ClassSet classSetB = _classSets[b]; |
| 668 if (classSetA == null || classSetB == null) return false; | 674 if (classSetA == null || classSetB == null) return false; |
| 669 // TODO(johnniwinther): Implement an optimized query on [ClassSet]. | 675 // TODO(johnniwinther): Implement an optimized query on [ClassSet]. |
| 670 Set<ClassEntity> subtypesOfB = classSetB.subtypes().toSet(); | 676 Set<ClassEntity> subtypesOfB = classSetB.subtypes().toSet(); |
| 671 for (ClassEntity subtypeOfA in classSetA.subtypes()) { | 677 for (ClassEntity subtypeOfA in classSetA.subtypes()) { |
| 672 if (subtypesOfB.contains(subtypeOfA)) { | 678 if (subtypesOfB.contains(subtypeOfA)) { |
| 673 return true; | 679 return true; |
| 674 } | 680 } |
| 675 } | 681 } |
| 676 return false; | 682 return false; |
| 677 } | 683 } |
| 678 | 684 |
| 679 /// Returns `true` if any directly instantiated class other than [cls] extends | 685 /// Returns `true` if any directly instantiated class other than [cls] extends |
| 680 /// [cls]. | 686 /// [cls]. |
| 681 bool hasAnyStrictSubclass(ClassEntity cls) { | 687 bool hasAnyStrictSubclass(ClassEntity cls) { |
| 682 assert(_checkClass(cls)); | 688 assert(checkClass(cls)); |
| 683 ClassHierarchyNode subclasses = _classHierarchyNodes[cls]; | 689 ClassHierarchyNode subclasses = _classHierarchyNodes[cls]; |
| 684 if (subclasses == null) return false; | 690 if (subclasses == null) return false; |
| 685 return subclasses.isIndirectlyInstantiated; | 691 return subclasses.isIndirectlyInstantiated; |
| 686 } | 692 } |
| 687 | 693 |
| 688 /// Returns `true` if any directly instantiated class other than [cls] | 694 /// Returns `true` if any directly instantiated class other than [cls] |
| 689 /// implements [cls]. | 695 /// implements [cls]. |
| 690 bool hasAnyStrictSubtype(ClassEntity cls) { | 696 bool hasAnyStrictSubtype(ClassEntity cls) { |
| 691 return strictSubtypeCount(cls) > 0; | 697 return strictSubtypeCount(cls) > 0; |
| 692 } | 698 } |
| 693 | 699 |
| 694 /// Returns `true` if all directly instantiated classes that implement [cls] | 700 /// Returns `true` if all directly instantiated classes that implement [cls] |
| 695 /// extend it. | 701 /// extend it. |
| 696 bool hasOnlySubclasses(ClassEntity cls) { | 702 bool hasOnlySubclasses(ClassEntity cls) { |
| 697 assert(_checkClass(cls)); | 703 assert(checkClass(cls)); |
| 698 // TODO(johnniwinther): move this to ClassSet? | 704 // TODO(johnniwinther): move this to ClassSet? |
| 699 if (cls == commonElements.objectClass) return true; | 705 if (cls == commonElements.objectClass) return true; |
| 700 ClassSet classSet = _classSets[cls]; | 706 ClassSet classSet = _classSets[cls]; |
| 701 if (classSet == null) { | 707 if (classSet == null) { |
| 702 // Vacuously true. | 708 // Vacuously true. |
| 703 return true; | 709 return true; |
| 704 } | 710 } |
| 705 return classSet.hasOnlyInstantiatedSubclasses; | 711 return classSet.hasOnlyInstantiatedSubclasses; |
| 706 } | 712 } |
| 707 | 713 |
| 708 @override | 714 @override |
| 709 ClassEntity getLubOfInstantiatedSubclasses(ClassEntity cls) { | 715 ClassEntity getLubOfInstantiatedSubclasses(ClassEntity cls) { |
| 710 assert(_checkClass(cls)); | 716 assert(checkClass(cls)); |
| 711 if (nativeData.isJsInteropClass(cls)) { | 717 if (nativeData.isJsInteropClass(cls)) { |
| 712 return commonElements.jsJavaScriptObjectClass; | 718 return commonElements.jsJavaScriptObjectClass; |
| 713 } | 719 } |
| 714 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls]; | 720 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls]; |
| 715 return hierarchy != null | 721 return hierarchy != null |
| 716 ? hierarchy.getLubOfInstantiatedSubclasses() | 722 ? hierarchy.getLubOfInstantiatedSubclasses() |
| 717 : null; | 723 : null; |
| 718 } | 724 } |
| 719 | 725 |
| 720 @override | 726 @override |
| 721 ClassEntity getLubOfInstantiatedSubtypes(ClassEntity cls) { | 727 ClassEntity getLubOfInstantiatedSubtypes(ClassEntity cls) { |
| 722 assert(_checkClass(cls)); | 728 assert(checkClass(cls)); |
| 723 if (nativeData.isJsInteropClass(cls)) { | 729 if (nativeData.isJsInteropClass(cls)) { |
| 724 return commonElements.jsJavaScriptObjectClass; | 730 return commonElements.jsJavaScriptObjectClass; |
| 725 } | 731 } |
| 726 ClassSet classSet = _classSets[cls]; | 732 ClassSet classSet = _classSets[cls]; |
| 727 return classSet != null ? classSet.getLubOfInstantiatedSubtypes() : null; | 733 return classSet != null ? classSet.getLubOfInstantiatedSubtypes() : null; |
| 728 } | 734 } |
| 729 | 735 |
| 730 Set<ClassEntity> _commonContainedClasses(ClassEntity cls1, ClassQuery query1, | 736 Set<ClassEntity> _commonContainedClasses(ClassEntity cls1, ClassQuery query1, |
| 731 ClassEntity cls2, ClassQuery query2) { | 737 ClassEntity cls2, ClassQuery query2) { |
| 732 Iterable<ClassEntity> xSubset = _containedSubset(cls1, query1); | 738 Iterable<ClassEntity> xSubset = _containedSubset(cls1, query1); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 756 /// Returns `true` if any live class that mixes in [cls] implements [type]. | 762 /// Returns `true` if any live class that mixes in [cls] implements [type]. |
| 757 bool hasAnySubclassOfMixinUseThatImplements( | 763 bool hasAnySubclassOfMixinUseThatImplements( |
| 758 ClassEntity cls, ClassEntity type) { | 764 ClassEntity cls, ClassEntity type) { |
| 759 return mixinUsesOf(cls) | 765 return mixinUsesOf(cls) |
| 760 .any((use) => hasAnySubclassThatImplements(use, type)); | 766 .any((use) => hasAnySubclassThatImplements(use, type)); |
| 761 } | 767 } |
| 762 | 768 |
| 763 /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass | 769 /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass |
| 764 /// of a mixin application of [y]. | 770 /// of a mixin application of [y]. |
| 765 bool everySubtypeIsSubclassOfOrMixinUseOf(ClassEntity x, ClassEntity y) { | 771 bool everySubtypeIsSubclassOfOrMixinUseOf(ClassEntity x, ClassEntity y) { |
| 766 assert(_checkClass(x)); | 772 assert(checkClass(x)); |
| 767 assert(_checkClass(y)); | 773 assert(checkClass(y)); |
| 768 Map<ClassEntity, bool> secondMap = | 774 Map<ClassEntity, bool> secondMap = |
| 769 _subtypeCoveredByCache[x] ??= <ClassEntity, bool>{}; | 775 _subtypeCoveredByCache[x] ??= <ClassEntity, bool>{}; |
| 770 return secondMap[y] ??= subtypesOf(x).every((ClassEntity cls) => | 776 return secondMap[y] ??= subtypesOf(x).every((ClassEntity cls) => |
| 771 isSubclassOf(cls, y) || isSubclassOfMixinUseOf(cls, y)); | 777 isSubclassOf(cls, y) || isSubclassOfMixinUseOf(cls, y)); |
| 772 } | 778 } |
| 773 | 779 |
| 774 /// Returns `true` if any subclass of [superclass] implements [type]. | 780 /// Returns `true` if any subclass of [superclass] implements [type]. |
| 775 bool hasAnySubclassThatImplements(ClassEntity superclass, ClassEntity type) { | 781 bool hasAnySubclassThatImplements(ClassEntity superclass, ClassEntity type) { |
| 776 assert(_checkClass(superclass)); | 782 assert(checkClass(superclass)); |
| 777 Set<ClassEntity> subclasses = _typesImplementedBySubclasses[superclass]; | 783 Set<ClassEntity> subclasses = _typesImplementedBySubclasses[superclass]; |
| 778 if (subclasses == null) return false; | 784 if (subclasses == null) return false; |
| 779 return subclasses.contains(type); | 785 return subclasses.contains(type); |
| 780 } | 786 } |
| 781 | 787 |
| 782 /// Returns whether a [selector] call on an instance of [cls] | 788 /// Returns whether a [selector] call on an instance of [cls] |
| 783 /// will hit a method at runtime, and not go through [noSuchMethod]. | 789 /// will hit a method at runtime, and not go through [noSuchMethod]. |
| 784 bool hasConcreteMatch(ClassEntity cls, Selector selector, | 790 bool hasConcreteMatch(ClassEntity cls, Selector selector, |
| 785 {ClassEntity stopAtSuperclass}); | 791 {ClassEntity stopAtSuperclass}); |
| 786 | 792 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 return false; | 837 return false; |
| 832 } | 838 } |
| 833 } | 839 } |
| 834 | 840 |
| 835 /// Returns an iterable over the common supertypes of the [classes]. | 841 /// Returns an iterable over the common supertypes of the [classes]. |
| 836 Iterable<ClassEntity> commonSupertypesOf(Iterable<ClassEntity> classes) { | 842 Iterable<ClassEntity> commonSupertypesOf(Iterable<ClassEntity> classes) { |
| 837 Iterator<ClassEntity> iterator = classes.iterator; | 843 Iterator<ClassEntity> iterator = classes.iterator; |
| 838 if (!iterator.moveNext()) return const <ClassEntity>[]; | 844 if (!iterator.moveNext()) return const <ClassEntity>[]; |
| 839 | 845 |
| 840 ClassEntity cls = iterator.current; | 846 ClassEntity cls = iterator.current; |
| 841 assert(_checkInvariants(cls)); | 847 assert(checkInvariants(cls)); |
| 842 OrderedTypeSet typeSet = _getOrderedTypeSet(cls); | 848 OrderedTypeSet typeSet = getOrderedTypeSet(cls); |
| 843 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element); | 849 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element); |
| 844 | 850 |
| 845 int depth = typeSet.maxDepth; | 851 int depth = typeSet.maxDepth; |
| 846 Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>(); | 852 Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>(); |
| 847 do { | 853 do { |
| 848 ClassEntity otherClass = iterator.current; | 854 ClassEntity otherClass = iterator.current; |
| 849 assert(_checkInvariants(otherClass)); | 855 assert(checkInvariants(otherClass)); |
| 850 OrderedTypeSet otherTypeSet = _getOrderedTypeSet(otherClass); | 856 OrderedTypeSet otherTypeSet = getOrderedTypeSet(otherClass); |
| 851 otherTypeSets = otherTypeSets.prepend(otherTypeSet); | 857 otherTypeSets = otherTypeSets.prepend(otherTypeSet); |
| 852 if (otherTypeSet.maxDepth < depth) { | 858 if (otherTypeSet.maxDepth < depth) { |
| 853 depth = otherTypeSet.maxDepth; | 859 depth = otherTypeSet.maxDepth; |
| 854 } | 860 } |
| 855 } while (iterator.moveNext()); | 861 } while (iterator.moveNext()); |
| 856 | 862 |
| 857 List<ClassEntity> commonSupertypes = <ClassEntity>[]; | 863 List<ClassEntity> commonSupertypes = <ClassEntity>[]; |
| 858 OUTER: | 864 OUTER: |
| 859 for (Link<InterfaceType> link = typeSet[depth]; | 865 for (Link<InterfaceType> link = typeSet[depth]; |
| 860 link.head.element != commonElements.objectClass; | 866 link.head.element != commonElements.objectClass; |
| 861 link = link.tail) { | 867 link = link.tail) { |
| 862 ClassEntity cls = link.head.element; | 868 ClassEntity cls = link.head.element; |
| 863 for (Link<OrderedTypeSet> link = otherTypeSets; | 869 for (Link<OrderedTypeSet> link = otherTypeSets; |
| 864 !link.isEmpty; | 870 !link.isEmpty; |
| 865 link = link.tail) { | 871 link = link.tail) { |
| 866 if (link.head.asInstanceOf(cls, _getHierarchyDepth(cls)) == null) { | 872 if (link.head.asInstanceOf(cls, getHierarchyDepth(cls)) == null) { |
| 867 continue OUTER; | 873 continue OUTER; |
| 868 } | 874 } |
| 869 } | 875 } |
| 870 commonSupertypes.add(cls); | 876 commonSupertypes.add(cls); |
| 871 } | 877 } |
| 872 commonSupertypes.add(commonElements.objectClass); | 878 commonSupertypes.add(commonElements.objectClass); |
| 873 return commonSupertypes; | 879 return commonSupertypes; |
| 874 } | 880 } |
| 875 | 881 |
| 876 Iterable<ClassEntity> commonSubclasses(ClassEntity cls1, ClassQuery query1, | 882 Iterable<ClassEntity> commonSubclasses(ClassEntity cls1, ClassQuery query1, |
| 877 ClassEntity cls2, ClassQuery query2) { | 883 ClassEntity cls2, ClassQuery query2) { |
| 878 // TODO(johnniwinther): Use [ClassSet] to compute this. | 884 // TODO(johnniwinther): Use [ClassSet] to compute this. |
| 879 // Compute the set of classes that are contained in both class subsets. | 885 // Compute the set of classes that are contained in both class subsets. |
| 880 Set<ClassEntity> common = | 886 Set<ClassEntity> common = |
| 881 _commonContainedClasses(cls1, query1, cls2, query2); | 887 _commonContainedClasses(cls1, query1, cls2, query2); |
| 882 if (common == null || common.isEmpty) return const <ClassEntity>[]; | 888 if (common == null || common.isEmpty) return const <ClassEntity>[]; |
| 883 // Narrow down the candidates by only looking at common classes | 889 // Narrow down the candidates by only looking at common classes |
| 884 // that do not have a superclass or supertype that will be a | 890 // that do not have a superclass or supertype that will be a |
| 885 // better candidate. | 891 // better candidate. |
| 886 return common.where((ClassEntity each) { | 892 return common.where((ClassEntity each) { |
| 887 bool containsSuperclass = common.contains(_getSuperClass(each)); | 893 bool containsSuperclass = common.contains(getSuperClass(each)); |
| 888 // If the superclass is also a candidate, then we don't want to | 894 // If the superclass is also a candidate, then we don't want to |
| 889 // deal with this class. If we're only looking for a subclass we | 895 // deal with this class. If we're only looking for a subclass we |
| 890 // know we don't have to look at the list of interfaces because | 896 // know we don't have to look at the list of interfaces because |
| 891 // they can never be in the common set. | 897 // they can never be in the common set. |
| 892 if (containsSuperclass || | 898 if (containsSuperclass || |
| 893 query1 == ClassQuery.SUBCLASS || | 899 query1 == ClassQuery.SUBCLASS || |
| 894 query2 == ClassQuery.SUBCLASS) { | 900 query2 == ClassQuery.SUBCLASS) { |
| 895 return !containsSuperclass; | 901 return !containsSuperclass; |
| 896 } | 902 } |
| 897 // Run through the direct supertypes of the class. If the common | 903 // Run through the direct supertypes of the class. If the common |
| 898 // set contains the direct supertype of the class, we ignore the | 904 // set contains the direct supertype of the class, we ignore the |
| 899 // the class because the supertype is a better candidate. | 905 // the class because the supertype is a better candidate. |
| 900 | 906 |
| 901 for (ClassEntity interface in _getInterfaces(each)) { | 907 for (ClassEntity interface in getInterfaces(each)) { |
| 902 if (common.contains(interface)) return false; | 908 if (common.contains(interface)) return false; |
| 903 } | 909 } |
| 904 return true; | 910 return true; |
| 905 }); | 911 }); |
| 906 } | 912 } |
| 907 | 913 |
| 908 /// Returns an iterable over the live mixin applications that mixin [cls]. | 914 /// Returns an iterable over the live mixin applications that mixin [cls]. |
| 909 Iterable<ClassEntity> mixinUsesOf(ClassEntity cls) { | 915 Iterable<ClassEntity> mixinUsesOf(ClassEntity cls) { |
| 910 if (_liveMixinUses == null) { | 916 if (_liveMixinUses == null) { |
| 911 _liveMixinUses = new Map<ClassEntity, List<ClassEntity>>(); | 917 _liveMixinUses = new Map<ClassEntity, List<ClassEntity>>(); |
| 912 for (ClassEntity mixin in _mixinUses.keys) { | 918 for (ClassEntity mixin in _mixinUses.keys) { |
| 913 List<ClassEntity> uses = <ClassEntity>[]; | 919 List<ClassEntity> uses = <ClassEntity>[]; |
| 914 | 920 |
| 915 void addLiveUse(ClassEntity mixinApplication) { | 921 void addLiveUse(ClassEntity mixinApplication) { |
| 916 if (isInstantiated(mixinApplication)) { | 922 if (isInstantiated(mixinApplication)) { |
| 917 uses.add(mixinApplication); | 923 uses.add(mixinApplication); |
| 918 } else if (_isNamedMixinApplication(mixinApplication)) { | 924 } else if (isNamedMixinApplication(mixinApplication)) { |
| 919 Set<ClassEntity> next = _mixinUses[mixinApplication]; | 925 Set<ClassEntity> next = _mixinUses[mixinApplication]; |
| 920 if (next != null) { | 926 if (next != null) { |
| 921 next.forEach(addLiveUse); | 927 next.forEach(addLiveUse); |
| 922 } | 928 } |
| 923 } | 929 } |
| 924 } | 930 } |
| 925 | 931 |
| 926 _mixinUses[mixin].forEach(addLiveUse); | 932 _mixinUses[mixin].forEach(addLiveUse); |
| 927 if (uses.isNotEmpty) { | 933 if (uses.isNotEmpty) { |
| 928 _liveMixinUses[mixin] = uses; | 934 _liveMixinUses[mixin] = uses; |
| 929 } | 935 } |
| 930 } | 936 } |
| 931 } | 937 } |
| 932 Iterable<ClassEntity> uses = _liveMixinUses[cls]; | 938 Iterable<ClassEntity> uses = _liveMixinUses[cls]; |
| 933 return uses != null ? uses : const <ClassEntity>[]; | 939 return uses != null ? uses : const <ClassEntity>[]; |
| 934 } | 940 } |
| 935 | 941 |
| 936 /// Returns `true` if any live class that mixes in [mixin] is also a subclass | 942 /// Returns `true` if any live class that mixes in [mixin] is also a subclass |
| 937 /// of [superclass]. | 943 /// of [superclass]. |
| 938 bool hasAnySubclassThatMixes(ClassEntity superclass, ClassEntity mixin) { | 944 bool hasAnySubclassThatMixes(ClassEntity superclass, ClassEntity mixin) { |
| 939 return mixinUsesOf(mixin).any((ClassEntity each) { | 945 return mixinUsesOf(mixin).any((ClassEntity each) { |
| 940 return isSubclassOf(each, superclass); | 946 return isSubclassOf(each, superclass); |
| 941 }); | 947 }); |
| 942 } | 948 } |
| 943 | 949 |
| 944 /// Returns `true` if [cls] or any superclass mixes in [mixin]. | 950 /// Returns `true` if [cls] or any superclass mixes in [mixin]. |
| 945 bool isSubclassOfMixinUseOf(ClassEntity cls, ClassEntity mixin) { | 951 bool isSubclassOfMixinUseOf(ClassEntity cls, ClassEntity mixin) { |
| 946 assert(_checkClass(cls)); | 952 assert(checkClass(cls)); |
| 947 assert(_checkClass(mixin)); | 953 assert(checkClass(mixin)); |
| 948 if (isUsedAsMixin(mixin)) { | 954 if (isUsedAsMixin(mixin)) { |
| 949 ClassEntity current = cls; | 955 ClassEntity current = cls; |
| 950 while (current != null) { | 956 while (current != null) { |
| 951 ClassEntity currentMixin = _getAppliedMixin(current); | 957 ClassEntity currentMixin = getAppliedMixin(current); |
| 952 if (currentMixin == mixin) return true; | 958 if (currentMixin == mixin) return true; |
| 953 current = _getSuperClass(current); | 959 current = getSuperClass(current); |
| 954 } | 960 } |
| 955 } | 961 } |
| 956 return false; | 962 return false; |
| 957 } | 963 } |
| 958 | 964 |
| 959 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies | 965 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies |
| 960 /// of known classes. | 966 /// of known classes. |
| 961 /// | 967 /// |
| 962 /// This method is only provided for testing. For queries on classes, use the | 968 /// This method is only provided for testing. For queries on classes, use the |
| 963 /// methods defined in [ClosedWorld]. | 969 /// methods defined in [ClosedWorld]. |
| 964 ClassHierarchyNode getClassHierarchyNode(ClassEntity cls) { | 970 ClassHierarchyNode getClassHierarchyNode(ClassEntity cls) { |
| 965 assert(_checkClass(cls)); | 971 assert(checkClass(cls)); |
| 966 return _classHierarchyNodes[cls]; | 972 return _classHierarchyNodes[cls]; |
| 967 } | 973 } |
| 968 | 974 |
| 969 /// Returns [ClassSet] for [cls] used to model the extends and implements | 975 /// Returns [ClassSet] for [cls] used to model the extends and implements |
| 970 /// relations of known classes. | 976 /// relations of known classes. |
| 971 /// | 977 /// |
| 972 /// This method is only provided for testing. For queries on classes, use the | 978 /// This method is only provided for testing. For queries on classes, use the |
| 973 /// methods defined in [ClosedWorld]. | 979 /// methods defined in [ClosedWorld]. |
| 974 ClassSet getClassSet(ClassEntity cls) { | 980 ClassSet getClassSet(ClassEntity cls) { |
| 975 assert(_checkClass(cls)); | 981 assert(checkClass(cls)); |
| 976 return _classSets[cls]; | 982 return _classSets[cls]; |
| 977 } | 983 } |
| 978 | 984 |
| 979 Iterable<TypedefElement> get allTypedefs => _allTypedefs; | 985 Iterable<TypedefElement> get allTypedefs => _allTypedefs; |
| 980 | 986 |
| 981 TypeMask computeReceiverType(Selector selector, TypeMask mask) { | 987 TypeMask computeReceiverType(Selector selector, TypeMask mask) { |
| 982 return _allFunctions.receiverType(selector, mask, this); | 988 return _allFunctions.receiverType(selector, mask, this); |
| 983 } | 989 } |
| 984 | 990 |
| 985 Iterable<MemberEntity> locateMembers(Selector selector, TypeMask mask) { | 991 Iterable<MemberEntity> locateMembers(Selector selector, TypeMask mask) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1049 sideEffects.setDependsOnSomething(); | 1055 sideEffects.setDependsOnSomething(); |
| 1050 } | 1056 } |
| 1051 } else { | 1057 } else { |
| 1052 sideEffects.add(getSideEffectsOfElement(e)); | 1058 sideEffects.add(getSideEffectsOfElement(e)); |
| 1053 } | 1059 } |
| 1054 } | 1060 } |
| 1055 return sideEffects; | 1061 return sideEffects; |
| 1056 } | 1062 } |
| 1057 | 1063 |
| 1058 SideEffects getSideEffectsOfElement(Entity element) { | 1064 SideEffects getSideEffectsOfElement(Entity element) { |
| 1059 assert(_checkEntity(element)); | 1065 assert(checkEntity(element)); |
| 1060 return _sideEffects.putIfAbsent(element, _makeSideEffects); | 1066 return _sideEffects.putIfAbsent(element, _makeSideEffects); |
| 1061 } | 1067 } |
| 1062 | 1068 |
| 1063 static _makeSideEffects() => new SideEffects(); | 1069 static _makeSideEffects() => new SideEffects(); |
| 1064 | 1070 |
| 1065 @override | 1071 @override |
| 1066 SideEffects getCurrentlyKnownSideEffects(Entity element) { | 1072 SideEffects getCurrentlyKnownSideEffects(Entity element) { |
| 1067 return getSideEffectsOfElement(element); | 1073 return getSideEffectsOfElement(element); |
| 1068 } | 1074 } |
| 1069 | 1075 |
| 1070 void registerSideEffects(Entity element, SideEffects effects) { | 1076 void registerSideEffects(Entity element, SideEffects effects) { |
| 1071 assert(_checkEntity(element)); | 1077 assert(checkEntity(element)); |
| 1072 if (_sideEffectsFreeElements.contains(element)) return; | 1078 if (_sideEffectsFreeElements.contains(element)) return; |
| 1073 _sideEffects[element] = effects; | 1079 _sideEffects[element] = effects; |
| 1074 } | 1080 } |
| 1075 | 1081 |
| 1076 void registerSideEffectsFree(Entity element) { | 1082 void registerSideEffectsFree(Entity element) { |
| 1077 assert(_checkEntity(element)); | 1083 assert(checkEntity(element)); |
| 1078 _sideEffects[element] = new SideEffects.empty(); | 1084 _sideEffects[element] = new SideEffects.empty(); |
| 1079 _sideEffectsFreeElements.add(element); | 1085 _sideEffectsFreeElements.add(element); |
| 1080 } | 1086 } |
| 1081 | 1087 |
| 1082 void addFunctionCalledInLoop(Entity element) { | 1088 void addFunctionCalledInLoop(Entity element) { |
| 1083 assert(_checkEntity(element)); | 1089 assert(checkEntity(element)); |
| 1084 _functionsCalledInLoop.add(element); | 1090 _functionsCalledInLoop.add(element); |
| 1085 } | 1091 } |
| 1086 | 1092 |
| 1087 bool isCalledInLoop(Entity element) { | 1093 bool isCalledInLoop(Entity element) { |
| 1088 assert(_checkEntity(element)); | 1094 assert(checkEntity(element)); |
| 1089 return _functionsCalledInLoop.contains(element); | 1095 return _functionsCalledInLoop.contains(element); |
| 1090 } | 1096 } |
| 1091 | 1097 |
| 1092 void registerCannotThrow(Entity element) { | 1098 void registerCannotThrow(Entity element) { |
| 1093 assert(_checkEntity(element)); | 1099 assert(checkEntity(element)); |
| 1094 _elementsThatCannotThrow.add(element); | 1100 _elementsThatCannotThrow.add(element); |
| 1095 } | 1101 } |
| 1096 | 1102 |
| 1097 bool getCannotThrow(Entity element) { | 1103 bool getCannotThrow(Entity element) { |
| 1098 return _elementsThatCannotThrow.contains(element); | 1104 return _elementsThatCannotThrow.contains(element); |
| 1099 } | 1105 } |
| 1100 | 1106 |
| 1101 void registerMightBePassedToApply(Entity element) { | 1107 void registerMightBePassedToApply(Entity element) { |
| 1102 _functionsThatMightBePassedToApply.add(element); | 1108 _functionsThatMightBePassedToApply.add(element); |
| 1103 } | 1109 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1139 } | 1145 } |
| 1140 | 1146 |
| 1141 class ClosedWorldImpl extends ClosedWorldBase { | 1147 class ClosedWorldImpl extends ClosedWorldBase { |
| 1142 ClosedWorldImpl( | 1148 ClosedWorldImpl( |
| 1143 {CommonElements commonElements, | 1149 {CommonElements commonElements, |
| 1144 ConstantSystem constantSystem, | 1150 ConstantSystem constantSystem, |
| 1145 NativeData nativeData, | 1151 NativeData nativeData, |
| 1146 InterceptorData interceptorData, | 1152 InterceptorData interceptorData, |
| 1147 BackendUsage backendUsage, | 1153 BackendUsage backendUsage, |
| 1148 ResolutionWorldBuilder resolutionWorldBuilder, | 1154 ResolutionWorldBuilder resolutionWorldBuilder, |
| 1155 Set<ClassEntity> implementedClasses, |
| 1149 FunctionSet functionSet, | 1156 FunctionSet functionSet, |
| 1150 Iterable<TypedefElement> allTypedefs, | 1157 Set<TypedefElement> allTypedefs, |
| 1151 Map<ClassEntity, Set<ClassEntity>> mixinUses, | 1158 Map<ClassEntity, Set<ClassEntity>> mixinUses, |
| 1152 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, | 1159 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, |
| 1153 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, | 1160 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, |
| 1154 Map<ClassEntity, ClassSet> classSets}) | 1161 Map<ClassEntity, ClassSet> classSets}) |
| 1155 : super( | 1162 : super( |
| 1156 commonElements: commonElements, | 1163 commonElements: commonElements, |
| 1157 constantSystem: constantSystem, | 1164 constantSystem: constantSystem, |
| 1158 nativeData: nativeData, | 1165 nativeData: nativeData, |
| 1159 interceptorData: interceptorData, | 1166 interceptorData: interceptorData, |
| 1160 backendUsage: backendUsage, | 1167 backendUsage: backendUsage, |
| 1161 resolutionWorldBuilder: resolutionWorldBuilder, | 1168 resolutionWorldBuilder: resolutionWorldBuilder, |
| 1169 implementedClasses: implementedClasses, |
| 1162 functionSet: functionSet, | 1170 functionSet: functionSet, |
| 1163 allTypedefs: allTypedefs, | 1171 allTypedefs: allTypedefs, |
| 1164 mixinUses: mixinUses, | 1172 mixinUses: mixinUses, |
| 1165 typesImplementedBySubclasses: typesImplementedBySubclasses, | 1173 typesImplementedBySubclasses: typesImplementedBySubclasses, |
| 1166 classHierarchyNodes: classHierarchyNodes, | 1174 classHierarchyNodes: classHierarchyNodes, |
| 1167 classSets: classSets); | 1175 classSets: classSets); |
| 1168 | 1176 |
| 1169 bool _checkClass(ClassElement cls) => cls.isDeclaration; | 1177 bool checkClass(ClassElement cls) => cls.isDeclaration; |
| 1170 | 1178 |
| 1171 bool _checkEntity(Element element) => element.isDeclaration; | 1179 bool checkEntity(Element element) => element.isDeclaration; |
| 1172 | 1180 |
| 1173 bool _checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { | 1181 bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { |
| 1174 assert(cls.isDeclaration, failedAt(cls, '$cls must be the declaration.')); | 1182 assert(cls.isDeclaration, failedAt(cls, '$cls must be the declaration.')); |
| 1175 assert(cls.isResolved, failedAt(cls, '$cls must be resolved.')); | 1183 assert(cls.isResolved, failedAt(cls, '$cls must be resolved.')); |
| 1176 | 1184 |
| 1177 // TODO(johnniwinther): Reinsert this or similar invariant. Currently | 1185 // TODO(johnniwinther): Reinsert this or similar invariant. Currently |
| 1178 // various call sites use uninstantiated classes for isSubtypeOf or | 1186 // various call sites use uninstantiated classes for isSubtypeOf or |
| 1179 // isSubclassOf. Some are valid, some are not. Work out better invariants | 1187 // isSubclassOf. Some are valid, some are not. Work out better invariants |
| 1180 // to catch the latter. | 1188 // to catch the latter. |
| 1181 // if (mustBeInstantiated) { | 1189 // if (mustBeInstantiated) { |
| 1182 // assert(isInstantiated(cls), failedAt(cls, '$cls is not instantiated.')); | 1190 // assert(isInstantiated(cls), failedAt(cls, '$cls is not instantiated.')); |
| 1183 // } | 1191 // } |
| 1184 return true; | 1192 return true; |
| 1185 } | 1193 } |
| 1186 | 1194 |
| 1187 OrderedTypeSet _getOrderedTypeSet(ClassElement cls) => | 1195 OrderedTypeSet getOrderedTypeSet(ClassElement cls) => |
| 1188 cls.allSupertypesAndSelf; | 1196 cls.allSupertypesAndSelf; |
| 1189 | 1197 |
| 1190 int _getHierarchyDepth(ClassElement cls) => cls.hierarchyDepth; | 1198 int getHierarchyDepth(ClassElement cls) => cls.hierarchyDepth; |
| 1191 | 1199 |
| 1192 ClassEntity _getSuperClass(ClassElement cls) => cls.superclass; | 1200 ClassEntity getSuperClass(ClassElement cls) => cls.superclass; |
| 1193 | 1201 |
| 1194 Iterable<ClassEntity> _getInterfaces(ClassElement cls) sync* { | 1202 Iterable<ClassEntity> getInterfaces(ClassElement cls) sync* { |
| 1195 for (Link link = cls.interfaces; !link.isEmpty; link = link.tail) { | 1203 for (Link link = cls.interfaces; !link.isEmpty; link = link.tail) { |
| 1196 yield link.head.element; | 1204 yield link.head.element; |
| 1197 } | 1205 } |
| 1198 } | 1206 } |
| 1199 | 1207 |
| 1200 bool _isNamedMixinApplication(ClassElement cls) => | 1208 bool isNamedMixinApplication(ClassElement cls) => cls.isNamedMixinApplication; |
| 1201 cls.isNamedMixinApplication; | |
| 1202 | 1209 |
| 1203 ClassEntity _getAppliedMixin(ClassElement cls) { | 1210 ClassEntity getAppliedMixin(ClassElement cls) { |
| 1204 if (cls.isMixinApplication) { | 1211 if (cls.isMixinApplication) { |
| 1205 MixinApplicationElement application = cls; | 1212 MixinApplicationElement application = cls; |
| 1206 return application.mixin; | 1213 return application.mixin; |
| 1207 } | 1214 } |
| 1208 return null; | 1215 return null; |
| 1209 } | 1216 } |
| 1210 | 1217 |
| 1211 @override | 1218 @override |
| 1212 bool hasElementIn(ClassEntity cls, Selector selector, Element element) { | 1219 bool hasElementIn(ClassEntity cls, Selector selector, Element element) { |
| 1213 // Use [:implementation:] of [element] | 1220 // Use [:implementation:] of [element] |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1283 } | 1290 } |
| 1284 | 1291 |
| 1285 class KernelClosedWorld extends ClosedWorldBase { | 1292 class KernelClosedWorld extends ClosedWorldBase { |
| 1286 KernelClosedWorld( | 1293 KernelClosedWorld( |
| 1287 {CommonElements commonElements, | 1294 {CommonElements commonElements, |
| 1288 ConstantSystem constantSystem, | 1295 ConstantSystem constantSystem, |
| 1289 NativeData nativeData, | 1296 NativeData nativeData, |
| 1290 InterceptorData interceptorData, | 1297 InterceptorData interceptorData, |
| 1291 BackendUsage backendUsage, | 1298 BackendUsage backendUsage, |
| 1292 ResolutionWorldBuilder resolutionWorldBuilder, | 1299 ResolutionWorldBuilder resolutionWorldBuilder, |
| 1300 Set<ClassEntity> implementedClasses, |
| 1293 FunctionSet functionSet, | 1301 FunctionSet functionSet, |
| 1294 Iterable<TypedefElement> allTypedefs, | 1302 Set<TypedefElement> allTypedefs, |
| 1295 Map<ClassEntity, Set<ClassEntity>> mixinUses, | 1303 Map<ClassEntity, Set<ClassEntity>> mixinUses, |
| 1296 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, | 1304 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, |
| 1297 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, | 1305 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, |
| 1298 Map<ClassEntity, ClassSet> classSets}) | 1306 Map<ClassEntity, ClassSet> classSets}) |
| 1299 : super( | 1307 : super( |
| 1300 commonElements: commonElements, | 1308 commonElements: commonElements, |
| 1301 constantSystem: constantSystem, | 1309 constantSystem: constantSystem, |
| 1302 nativeData: nativeData, | 1310 nativeData: nativeData, |
| 1303 interceptorData: interceptorData, | 1311 interceptorData: interceptorData, |
| 1304 backendUsage: backendUsage, | 1312 backendUsage: backendUsage, |
| 1305 resolutionWorldBuilder: resolutionWorldBuilder, | 1313 resolutionWorldBuilder: resolutionWorldBuilder, |
| 1314 implementedClasses: implementedClasses, |
| 1306 functionSet: functionSet, | 1315 functionSet: functionSet, |
| 1307 allTypedefs: allTypedefs, | 1316 allTypedefs: allTypedefs, |
| 1308 mixinUses: mixinUses, | 1317 mixinUses: mixinUses, |
| 1309 typesImplementedBySubclasses: typesImplementedBySubclasses, | 1318 typesImplementedBySubclasses: typesImplementedBySubclasses, |
| 1310 classHierarchyNodes: classHierarchyNodes, | 1319 classHierarchyNodes: classHierarchyNodes, |
| 1311 classSets: classSets); | 1320 classSets: classSets); |
| 1312 | 1321 |
| 1313 @override | 1322 @override |
| 1314 bool hasConcreteMatch(ClassEntity cls, Selector selector, | 1323 bool hasConcreteMatch(ClassEntity cls, Selector selector, |
| 1315 {ClassEntity stopAtSuperclass}) { | 1324 {ClassEntity stopAtSuperclass}) { |
| 1316 throw new UnimplementedError('KernelClosedWorld.hasConcreteMatch'); | 1325 throw new UnimplementedError('KernelClosedWorld.hasConcreteMatch'); |
| 1317 } | 1326 } |
| 1318 | 1327 |
| 1319 @override | 1328 @override |
| 1320 bool _isNamedMixinApplication(ClassEntity cls) { | 1329 bool isNamedMixinApplication(ClassEntity cls) { |
| 1321 throw new UnimplementedError('KernelClosedWorld._isNamedMixinApplication'); | 1330 throw new UnimplementedError('KernelClosedWorld.isNamedMixinApplication'); |
| 1322 } | 1331 } |
| 1323 | 1332 |
| 1324 @override | 1333 @override |
| 1325 ClassEntity _getAppliedMixin(ClassEntity cls) { | 1334 ClassEntity getAppliedMixin(ClassEntity cls) { |
| 1326 throw new UnimplementedError('KernelClosedWorld._getAppliedMixin'); | 1335 throw new UnimplementedError('KernelClosedWorld.getAppliedMixin'); |
| 1327 } | 1336 } |
| 1328 | 1337 |
| 1329 @override | 1338 @override |
| 1330 Iterable<ClassEntity> _getInterfaces(ClassEntity cls) { | 1339 Iterable<ClassEntity> getInterfaces(ClassEntity cls) { |
| 1331 throw new UnimplementedError('KernelClosedWorld._getInterfaces'); | 1340 throw new UnimplementedError('KernelClosedWorld.getInterfaces'); |
| 1332 } | 1341 } |
| 1333 | 1342 |
| 1334 @override | 1343 @override |
| 1335 ClassEntity _getSuperClass(ClassEntity cls) { | 1344 ClassEntity getSuperClass(ClassEntity cls) { |
| 1336 throw new UnimplementedError('KernelClosedWorld._getSuperClass'); | 1345 throw new UnimplementedError('KernelClosedWorld.getSuperClass'); |
| 1337 } | 1346 } |
| 1338 | 1347 |
| 1339 @override | 1348 @override |
| 1340 int _getHierarchyDepth(ClassEntity cls) { | 1349 int getHierarchyDepth(ClassEntity cls) { |
| 1341 throw new UnimplementedError('KernelClosedWorld._getHierarchyDepth'); | 1350 throw new UnimplementedError('KernelClosedWorld.getHierarchyDepth'); |
| 1342 } | 1351 } |
| 1343 | 1352 |
| 1344 @override | 1353 @override |
| 1345 OrderedTypeSet _getOrderedTypeSet(ClassEntity cls) { | 1354 OrderedTypeSet getOrderedTypeSet(ClassEntity cls) { |
| 1346 throw new UnimplementedError('KernelClosedWorld._getOrderedTypeSet'); | 1355 throw new UnimplementedError('KernelClosedWorld.getOrderedTypeSet'); |
| 1347 } | 1356 } |
| 1348 | 1357 |
| 1349 @override | 1358 @override |
| 1350 bool _checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true}) => | 1359 bool checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true}) => |
| 1351 true; | 1360 true; |
| 1352 | 1361 |
| 1353 @override | 1362 @override |
| 1354 bool _checkClass(ClassEntity cls) => true; | 1363 bool checkClass(ClassEntity cls) => true; |
| 1355 | 1364 |
| 1356 @override | 1365 @override |
| 1357 bool _checkEntity(Entity element) => true; | 1366 bool checkEntity(Entity element) => true; |
| 1358 | 1367 |
| 1359 @override | 1368 @override |
| 1360 void registerClosureClass(ClassElement cls) { | 1369 void registerClosureClass(ClassElement cls) { |
| 1361 throw new UnimplementedError('KernelClosedWorld.registerClosureClass'); | 1370 throw new UnimplementedError('KernelClosedWorld.registerClosureClass'); |
| 1362 } | 1371 } |
| 1363 | 1372 |
| 1364 @override | 1373 @override |
| 1365 bool hasElementIn(ClassEntity cls, Selector selector, Entity element) { | 1374 bool hasElementIn(ClassEntity cls, Selector selector, Entity element) { |
| 1366 throw new UnimplementedError('KernelClosedWorld.hasElementIn'); | 1375 throw new UnimplementedError('KernelClosedWorld.hasElementIn'); |
| 1367 } | 1376 } |
| 1368 } | 1377 } |
| OLD | NEW |