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

Side by Side Diff: pkg/compiler/lib/src/world.dart

Issue 2580403002: Extract ClosedWorldImpl from WorldImpl. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/use_unused_api.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 'cache_strategy.dart'; 7 import 'cache_strategy.dart';
8 import 'closure.dart' show SynthesizedCallMethodElementX; 8 import 'closure.dart' show ClosureClassElement, SynthesizedCallMethodElementX;
9 import 'common/backend_api.dart' show BackendClasses; 9 import 'common/backend_api.dart' show BackendClasses;
10 import 'common.dart'; 10 import 'common.dart';
11 import 'constants/constant_system.dart'; 11 import 'constants/constant_system.dart';
12 import 'core_types.dart' show CoreTypes, CoreClasses, CommonElements; 12 import 'core_types.dart' show CoreTypes, CoreClasses, CommonElements;
13 import 'dart_types.dart'; 13 import 'dart_types.dart';
14 import 'elements/elements.dart' 14 import 'elements/elements.dart'
15 show 15 show
16 ClassElement, 16 ClassElement,
17 Element, 17 Element,
18 FunctionElement, 18 FunctionElement,
19 MixinApplicationElement, 19 MixinApplicationElement,
20 TypedefElement, 20 TypedefElement,
21 FieldElement; 21 FieldElement;
22 import 'js_backend/backend.dart' show JavaScriptBackend; 22 import 'js_backend/backend.dart' show JavaScriptBackend;
23 import 'ordered_typeset.dart'; 23 import 'ordered_typeset.dart';
24 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask; 24 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask;
25 import 'universe/class_set.dart'; 25 import 'universe/class_set.dart';
26 import 'universe/function_set.dart' show FunctionSet; 26 import 'universe/function_set.dart' show FunctionSet, FunctionSetBuilder;
27 import 'universe/selector.dart' show Selector; 27 import 'universe/selector.dart' show Selector;
28 import 'universe/side_effects.dart' show SideEffects; 28 import 'universe/side_effects.dart' show SideEffects;
29 import 'universe/world_builder.dart' 29 import 'universe/world_builder.dart'
30 show InstantiationInfo, ResolutionWorldBuilder; 30 show InstantiationInfo, ResolutionWorldBuilder;
31 import 'util/util.dart' show Link; 31 import 'util/util.dart' show Link;
32 32
33 /// Common superinterface for [OpenWorld] and [ClosedWorld]. 33 /// Common superinterface for [OpenWorld] and [ClosedWorld].
34 abstract class World {} 34 abstract class World {}
35 35
36 /// The [ClosedWorld] represents the information known about a program when 36 /// The [ClosedWorld] represents the information known about a program when
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 343
344 void registerUsedElement(Element element); 344 void registerUsedElement(Element element);
345 void registerTypedef(TypedefElement typedef); 345 void registerTypedef(TypedefElement typedef);
346 346
347 ClosedWorld closeWorld(DiagnosticReporter reporter); 347 ClosedWorld closeWorld(DiagnosticReporter reporter);
348 348
349 /// Returns an iterable over all mixin applications that mixin [cls]. 349 /// Returns an iterable over all mixin applications that mixin [cls].
350 Iterable<MixinApplicationElement> allMixinUsesOf(ClassElement cls); 350 Iterable<MixinApplicationElement> allMixinUsesOf(ClassElement cls);
351 } 351 }
352 352
353 class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld { 353 class WorldImpl implements OpenWorld {
354 bool _closed = false; 354 bool _closed = false;
355 355 ClosedWorld _closedWorldCache;
356 TypeMask getCachedMask(ClassElement base, int flags, TypeMask createMask()) { 356
357 Map<ClassElement, TypeMask> cachedMasks = 357 final JavaScriptBackend _backend;
358 _canonicalizedTypeMasks[flags] ??= <ClassElement, TypeMask>{}; 358 FunctionSetBuilder _allFunctions;
359 return cachedMasks.putIfAbsent(base, createMask); 359
360 final Set<TypedefElement> _allTypedefs = new Set<TypedefElement>();
361
362 final Map<ClassElement, Set<MixinApplicationElement>> _mixinUses =
363 new Map<ClassElement, Set<MixinApplicationElement>>();
364
365 // We keep track of subtype and subclass relationships in four
366 // distinct sets to make class hierarchy analysis faster.
367 final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes =
368 <ClassElement, ClassHierarchyNode>{};
369 final Map<ClassElement, ClassSet> _classSets = <ClassElement, ClassSet>{};
370
371 final Map<ClassElement, Map<ClassElement, bool>> _subtypeCoveredByCache =
372 <ClassElement, Map<ClassElement, bool>>{};
373
374 final Set<Element> alreadyPopulated;
375
376 final CommonElements commonElements;
377
378 final CoreTypes coreTypes;
379
380 final CacheStrategy cacheStrategy;
381
382 final ResolutionWorldBuilder resolverWorld;
383
384 bool get isClosed => _closed;
385
386 WorldImpl(this.resolverWorld, this._backend, this.commonElements,
387 this.coreTypes, CacheStrategy cacheStrategy)
388 : this.cacheStrategy = cacheStrategy,
389 alreadyPopulated = cacheStrategy.newSet() {
390 _allFunctions = new FunctionSetBuilder();
391 }
392
393 /// Returns an iterable over all mixin applications that mixin [cls].
394 Iterable<MixinApplicationElement> allMixinUsesOf(ClassElement cls) {
395 Iterable<MixinApplicationElement> uses = _mixinUses[cls];
396 return uses != null ? uses : const <MixinApplicationElement>[];
397 }
398
399 /// Called to add [cls] to the set of known classes.
400 ///
401 /// This ensures that class hierarchy queries can be performed on [cls] and
402 /// classes that extend or implement it.
403 void registerClass(ClassElement cls) => _registerClass(cls);
404
405 void _registerClass(ClassElement cls, {bool isDirectlyInstantiated: false}) {
406 _ensureClassSet(cls);
407 if (isDirectlyInstantiated) {
408 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true);
409 }
410 }
411
412 void registerTypedef(TypedefElement typdef) {
413 _allTypedefs.add(typdef);
414 }
415
416 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) {
417 cls = cls.declaration;
418 return _classHierarchyNodes.putIfAbsent(cls, () {
419 ClassHierarchyNode parentNode;
420 if (cls.superclass != null) {
421 parentNode = _ensureClassHierarchyNode(cls.superclass);
422 }
423 return new ClassHierarchyNode(parentNode, cls);
424 });
425 }
426
427 ClassSet _ensureClassSet(ClassElement cls) {
428 cls = cls.declaration;
429 return _classSets.putIfAbsent(cls, () {
430 ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
431 ClassSet classSet = new ClassSet(node);
432
433 for (InterfaceType type in cls.allSupertypes) {
434 // TODO(johnniwinther): Optimization: Avoid adding [cls] to
435 // superclasses.
436 ClassSet subtypeSet = _ensureClassSet(type.element);
437 subtypeSet.addSubtype(node);
438 }
439 if (cls.isMixinApplication) {
440 // TODO(johnniwinther): Store this in the [ClassSet].
441 MixinApplicationElement mixinApplication = cls;
442 if (mixinApplication.mixin != null) {
443 // If [mixinApplication] is malformed [mixin] is `null`.
444 registerMixinUse(mixinApplication, mixinApplication.mixin);
445 }
446 }
447
448 return classSet;
449 });
450 }
451
452 void _updateSuperClassHierarchyNodeForClass(ClassHierarchyNode node) {
453 // Ensure that classes implicitly implementing `Function` are in its
454 // subtype set.
455 ClassElement cls = node.cls;
456 if (cls != commonElements.functionClass &&
457 cls.implementsFunction(commonElements)) {
458 ClassSet subtypeSet = _ensureClassSet(commonElements.functionClass);
459 subtypeSet.addSubtype(node);
460 }
461 if (!node.isInstantiated && node.parentNode != null) {
462 _updateSuperClassHierarchyNodeForClass(node.parentNode);
463 }
464 }
465
466 void _updateClassHierarchyNodeForClass(ClassElement cls,
467 {bool directlyInstantiated: false, bool abstractlyInstantiated: false}) {
468 ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
469 _updateSuperClassHierarchyNodeForClass(node);
470 if (directlyInstantiated) {
471 node.isDirectlyInstantiated = true;
472 }
473 if (abstractlyInstantiated) {
474 node.isAbstractlyInstantiated = true;
475 }
476 }
477
478 ClosedWorld closeWorld(DiagnosticReporter reporter) {
479 Map<ClassElement, Set<ClassElement>> typesImplementedBySubclasses =
480 new Map<ClassElement, Set<ClassElement>>();
481
482 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated`
483 /// properties of the [ClassHierarchyNode] for [cls].
484
485 void addSubtypes(ClassElement cls, InstantiationInfo info) {
486 if (!info.hasInstantiation) {
487 return;
488 }
489 if (cacheStrategy.hasIncrementalSupport && !alreadyPopulated.add(cls)) {
490 return;
491 }
492 assert(cls.isDeclaration);
493 if (!cls.isResolved) {
494 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.');
Siggi Cherem (dart-lang) 2016/12/20 15:36:36 related to the discussion in the other CL - this w
Johnni Winther 2016/12/21 08:41:25 Yes. Will do later.
495 }
496
497 _updateClassHierarchyNodeForClass(cls,
498 directlyInstantiated: info.isDirectlyInstantiated,
499 abstractlyInstantiated: info.isAbstractlyInstantiated);
500
501 // Walk through the superclasses, and record the types
502 // implemented by that type on the superclasses.
503 ClassElement superclass = cls.superclass;
504 while (superclass != null) {
505 Set<Element> typesImplementedBySubclassesOfCls =
506 typesImplementedBySubclasses.putIfAbsent(
507 superclass, () => new Set<ClassElement>());
508 for (DartType current in cls.allSupertypes) {
509 typesImplementedBySubclassesOfCls.add(current.element);
510 }
511 superclass = superclass.superclass;
512 }
513 }
514
515 // Use the [:seenClasses:] set to include non-instantiated
516 // classes: if the superclass of these classes require RTI, then
517 // they also need RTI, so that a constructor passes the type
518 // variables to the super constructor.
519 resolverWorld.forEachInstantiatedClass(addSubtypes);
520
521 _closed = true;
522 return _closedWorldCache = new ClosedWorldImpl(
523 backend: _backend,
524 commonElements: commonElements,
525 coreTypes: coreTypes,
526 resolverWorld: resolverWorld,
527 functionSetBuilder: _allFunctions,
528 allTypedefs: _allTypedefs,
529 mixinUses: _mixinUses,
530 typesImplementedBySubclasses: typesImplementedBySubclasses,
531 classHierarchyNodes: _classHierarchyNodes,
532 classSets: _classSets);
533 }
534
535 void registerMixinUse(
536 MixinApplicationElement mixinApplication, ClassElement mixin) {
537 // TODO(johnniwinther): Add map restricted to live classes.
538 // We don't support patch classes as mixin.
539 assert(mixin.isDeclaration);
540 Set<MixinApplicationElement> users =
541 _mixinUses.putIfAbsent(mixin, () => new Set<MixinApplicationElement>());
542 users.add(mixinApplication);
543 }
544
545 void registerUsedElement(Element element) {
546 if (element.isInstanceMember && !element.isAbstract) {
547 _allFunctions.add(element);
548 }
549 }
550
551 ClosedWorld get closedWorldCache {
552 assert(isClosed);
553 return _closedWorldCache;
554 }
555 }
556
557 /// Enum values defining subset of classes included in queries.
558 enum ClassQuery {
559 /// Only the class itself is included.
560 EXACT,
561
562 /// The class and all subclasses (transitively) are included.
563 SUBCLASS,
564
565 /// The class and all classes that implement or subclass it (transitively)
566 /// are included.
567 SUBTYPE,
568 }
569
570 class ClosedWorldImpl implements ClosedWorld, ClosedWorldRefiner {
571 final JavaScriptBackend _backend;
572 BackendClasses get backendClasses => _backend.backendClasses;
573 FunctionSet _allFunctions;
574
575 final Iterable<TypedefElement> _allTypedefs;
576
577 final Map<ClassElement, Set<MixinApplicationElement>> _mixinUses;
578 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses;
579
580 final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses;
581
582 // We keep track of subtype and subclass relationships in four
583 // distinct sets to make class hierarchy analysis faster.
584 final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes;
585 final Map<ClassElement, ClassSet> _classSets;
586
587 final Map<ClassElement, Map<ClassElement, bool>> _subtypeCoveredByCache =
588 <ClassElement, Map<ClassElement, bool>>{};
589
590 final Set<Element> functionsCalledInLoop = new Set<Element>();
591 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>();
592
593 final Set<Element> sideEffectsFreeElements = new Set<Element>();
594
595 final Set<Element> elementsThatCannotThrow = new Set<Element>();
596
597 final Set<Element> functionsThatMightBePassedToApply =
598 new Set<FunctionElement>();
599
600 CommonMasks _commonMasks;
601
602 final CommonElements commonElements;
603
604 final CoreTypes coreTypes;
605
606 final ResolutionWorldBuilder _resolverWorld;
607
608 bool get isClosed => true;
609
610 ClosedWorldImpl(
611 {JavaScriptBackend backend,
612 this.commonElements,
613 this.coreTypes,
614 ResolutionWorldBuilder resolverWorld,
615 FunctionSetBuilder functionSetBuilder,
616 Iterable<TypedefElement> allTypedefs,
617 Map<ClassElement, Set<MixinApplicationElement>> mixinUses,
618 Map<ClassElement, Set<ClassElement>> typesImplementedBySubclasses,
619 Map<ClassElement, ClassHierarchyNode> classHierarchyNodes,
620 Map<ClassElement, ClassSet> classSets})
621 : this._backend = backend,
622 this._resolverWorld = resolverWorld,
623 this._allTypedefs = allTypedefs,
624 this._mixinUses = mixinUses,
625 this._typesImplementedBySubclasses = typesImplementedBySubclasses,
626 this._classHierarchyNodes = classHierarchyNodes,
627 this._classSets = classSets {
628 _commonMasks = new CommonMasks(this);
629 _allFunctions = functionSetBuilder.close(this);
360 } 630 }
361 631
362 /// Cache of [FlatTypeMask]s grouped by the 8 possible values of the 632 /// Cache of [FlatTypeMask]s grouped by the 8 possible values of the
363 /// `FlatTypeMask.flags` property. 633 /// `FlatTypeMask.flags` property.
364 final List<Map<ClassElement, TypeMask>> _canonicalizedTypeMasks = 634 final List<Map<ClassElement, TypeMask>> _canonicalizedTypeMasks =
365 new List<Map<ClassElement, TypeMask>>.filled(8, null); 635 new List<Map<ClassElement, TypeMask>>.filled(8, null);
366 636
637 FunctionSet get allFunctions => _allFunctions;
638
639 CommonMasks get commonMasks {
640 assert(isClosed);
641 return _commonMasks;
642 }
643
644 CoreClasses get coreClasses => commonElements;
645
646 ConstantSystem get constantSystem => _backend.constantSystem;
647
648 TypeMask getCachedMask(ClassElement base, int flags, TypeMask createMask()) {
649 Map<ClassElement, TypeMask> cachedMasks =
650 _canonicalizedTypeMasks[flags] ??= <ClassElement, TypeMask>{};
651 return cachedMasks.putIfAbsent(base, createMask);
652 }
653
367 bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { 654 bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) {
368 return invariant(cls, cls.isDeclaration, 655 return invariant(cls, cls.isDeclaration,
369 message: '$cls must be the declaration.') && 656 message: '$cls must be the declaration.') &&
370 invariant(cls, cls.isResolved, 657 invariant(cls, cls.isResolved,
371 message: 658 message:
372 '$cls must be resolved.') /* && 659 '$cls must be resolved.') /* &&
373 // TODO(johnniwinther): Reinsert this or similar invariant. 660 // TODO(johnniwinther): Reinsert this or similar invariant.
374 (!mustBeInstantiated || 661 (!mustBeInstantiated ||
375 invariant(cls, isInstantiated(cls), 662 invariant(cls, isInstantiated(cls),
376 message: '$cls is not instantiated.'))*/ 663 message: '$cls is not instantiated.'))*/
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; 727 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration];
441 return node != null && node.isIndirectlyInstantiated; 728 return node != null && node.isIndirectlyInstantiated;
442 } 729 }
443 730
444 @override 731 @override
445 bool isAbstract(ClassElement cls) => cls.isAbstract; 732 bool isAbstract(ClassElement cls) => cls.isAbstract;
446 733
447 /// Returns `true` if [cls] is implemented by an instantiated class. 734 /// Returns `true` if [cls] is implemented by an instantiated class.
448 bool isImplemented(ClassElement cls) { 735 bool isImplemented(ClassElement cls) {
449 assert(isClosed); 736 assert(isClosed);
450 return resolverWorld.isImplemented(cls); 737 return _resolverWorld.isImplemented(cls);
451 } 738 }
452 739
453 /// Returns an iterable over the directly instantiated classes that extend 740 /// Returns an iterable over the directly instantiated classes that extend
454 /// [cls] possibly including [cls] itself, if it is live. 741 /// [cls] possibly including [cls] itself, if it is live.
455 Iterable<ClassElement> subclassesOf(ClassElement cls) { 742 Iterable<ClassElement> subclassesOf(ClassElement cls) {
456 assert(isClosed); 743 assert(isClosed);
457 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; 744 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration];
458 if (hierarchy == null) return const <ClassElement>[]; 745 if (hierarchy == null) return const <ClassElement>[];
459 return hierarchy 746 return hierarchy
460 .subclassesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED); 747 .subclassesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED);
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 if (link.head.asInstanceOf(cls) == null) { 948 if (link.head.asInstanceOf(cls) == null) {
662 continue OUTER; 949 continue OUTER;
663 } 950 }
664 } 951 }
665 commonSupertypes.add(cls); 952 commonSupertypes.add(cls);
666 } 953 }
667 commonSupertypes.add(coreClasses.objectClass); 954 commonSupertypes.add(coreClasses.objectClass);
668 return commonSupertypes; 955 return commonSupertypes;
669 } 956 }
670 957
671 /// Returns an iterable over all mixin applications that mixin [cls].
672 Iterable<MixinApplicationElement> allMixinUsesOf(ClassElement cls) {
673 Iterable<MixinApplicationElement> uses = _mixinUses[cls];
674 return uses != null ? uses : const <MixinApplicationElement>[];
675 }
676
677 /// Returns an iterable over the live mixin applications that mixin [cls]. 958 /// Returns an iterable over the live mixin applications that mixin [cls].
678 Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls) { 959 Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls) {
679 assert(isClosed); 960 assert(isClosed);
680 if (_liveMixinUses == null) { 961 if (_liveMixinUses == null) {
681 _liveMixinUses = new Map<ClassElement, List<MixinApplicationElement>>(); 962 _liveMixinUses = new Map<ClassElement, List<MixinApplicationElement>>();
682 for (ClassElement mixin in _mixinUses.keys) { 963 for (ClassElement mixin in _mixinUses.keys) {
683 List<MixinApplicationElement> uses = <MixinApplicationElement>[]; 964 List<MixinApplicationElement> uses = <MixinApplicationElement>[];
684 965
685 void addLiveUse(MixinApplicationElement mixinApplication) { 966 void addLiveUse(MixinApplicationElement mixinApplication) {
686 if (isInstantiated(mixinApplication)) { 967 if (isInstantiated(mixinApplication)) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
751 Map<ClassElement, bool> secondMap = 1032 Map<ClassElement, bool> secondMap =
752 _subtypeCoveredByCache[x] ??= <ClassElement, bool>{}; 1033 _subtypeCoveredByCache[x] ??= <ClassElement, bool>{};
753 return secondMap[y] ??= subtypesOf(x).every((ClassElement cls) => 1034 return secondMap[y] ??= subtypesOf(x).every((ClassElement cls) =>
754 isSubclassOf(cls, y) || isSubclassOfMixinUseOf(cls, y)); 1035 isSubclassOf(cls, y) || isSubclassOfMixinUseOf(cls, y));
755 } 1036 }
756 1037
757 /// Returns `true` if any subclass of [superclass] implements [type]. 1038 /// Returns `true` if any subclass of [superclass] implements [type].
758 bool hasAnySubclassThatImplements( 1039 bool hasAnySubclassThatImplements(
759 ClassElement superclass, ClassElement type) { 1040 ClassElement superclass, ClassElement type) {
760 assert(isClosed); 1041 assert(isClosed);
761 Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass); 1042
1043 Set<ClassElement> subclasses =
1044 _typesImplementedBySubclasses[superclass.declaration];
762 if (subclasses == null) return false; 1045 if (subclasses == null) return false;
763 return subclasses.contains(type); 1046 return subclasses.contains(type);
764 } 1047 }
765 1048
766 @override 1049 @override
767 bool hasElementIn(ClassElement cls, Selector selector, Element element) { 1050 bool hasElementIn(ClassElement cls, Selector selector, Element element) {
768 // Use [:implementation:] of [element] 1051 // Use [:implementation:] of [element]
769 // because our function set only stores declarations. 1052 // because our function set only stores declarations.
770 Element result = findMatchIn(cls, selector); 1053 Element result = findMatchIn(cls, selector);
771 return result == null 1054 return result == null
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 return subclassesNeedNoSuchMethod(node); 1122 return subclassesNeedNoSuchMethod(node);
840 } else { 1123 } else {
841 if (subclassesNeedNoSuchMethod(node)) return true; 1124 if (subclassesNeedNoSuchMethod(node)) return true;
842 for (ClassHierarchyNode subtypeNode in classSet.subtypeNodes) { 1125 for (ClassHierarchyNode subtypeNode in classSet.subtypeNodes) {
843 if (subclassesNeedNoSuchMethod(subtypeNode)) return true; 1126 if (subclassesNeedNoSuchMethod(subtypeNode)) return true;
844 } 1127 }
845 return false; 1128 return false;
846 } 1129 }
847 } 1130 }
848 1131
849 final JavaScriptBackend _backend;
850 BackendClasses get backendClasses => _backend.backendClasses;
851 FunctionSet _allFunctions;
852 final Set<Element> functionsCalledInLoop = new Set<Element>();
853 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>();
854
855 final Set<TypedefElement> _allTypedefs = new Set<TypedefElement>();
856
857 final Map<ClassElement, Set<MixinApplicationElement>> _mixinUses =
858 new Map<ClassElement, Set<MixinApplicationElement>>();
859 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses;
860
861 final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses =
862 new Map<ClassElement, Set<ClassElement>>();
863
864 // We keep track of subtype and subclass relationships in four
865 // distinct sets to make class hierarchy analysis faster.
866 final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes =
867 <ClassElement, ClassHierarchyNode>{};
868 final Map<ClassElement, ClassSet> _classSets = <ClassElement, ClassSet>{};
869
870 final Map<ClassElement, Map<ClassElement, bool>> _subtypeCoveredByCache =
871 <ClassElement, Map<ClassElement, bool>>{};
872
873 final Set<Element> sideEffectsFreeElements = new Set<Element>();
874
875 final Set<Element> elementsThatCannotThrow = new Set<Element>();
876
877 final Set<Element> functionsThatMightBePassedToApply =
878 new Set<FunctionElement>();
879
880 final Set<Element> alreadyPopulated;
881
882 CommonMasks _commonMasks;
883
884 final CommonElements commonElements;
885
886 final CoreTypes coreTypes;
887
888 final CacheStrategy cacheStrategy;
889
890 final ResolutionWorldBuilder resolverWorld;
891
892 bool get isClosed => _closed;
893
894 Set<ClassElement> typesImplementedBySubclassesOf(ClassElement cls) {
895 return _typesImplementedBySubclasses[cls.declaration];
896 }
897
898 WorldImpl(this.resolverWorld, this._backend, this.commonElements,
899 this.coreTypes, CacheStrategy cacheStrategy)
900 : this.cacheStrategy = cacheStrategy,
901 alreadyPopulated = cacheStrategy.newSet() {
902 _allFunctions = new FunctionSet(this);
903 }
904
905 FunctionSet get allFunctions => _allFunctions;
906
907 CommonMasks get commonMasks {
908 assert(isClosed);
909 return _commonMasks;
910 }
911
912 CoreClasses get coreClasses => commonElements;
913
914 ConstantSystem get constantSystem => _backend.constantSystem;
915
916 /// Called to add [cls] to the set of known classes.
917 ///
918 /// This ensures that class hierarchy queries can be performed on [cls] and
919 /// classes that extend or implement it.
920 void registerClass(ClassElement cls) => _registerClass(cls);
921
922 void registerClosureClass(ClassElement cls) {
923 _registerClass(cls, isDirectlyInstantiated: true);
924 }
925
926 void _registerClass(ClassElement cls, {bool isDirectlyInstantiated: false}) {
927 _ensureClassSet(cls);
928 if (isDirectlyInstantiated) {
929 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true);
930 }
931 }
932
933 void registerTypedef(TypedefElement typdef) {
934 _allTypedefs.add(typdef);
935 }
936
937 Iterable<TypedefElement> get allTypedefs => _allTypedefs;
938
939 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies 1132 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
940 /// of known classes. 1133 /// of known classes.
941 /// 1134 ///
942 /// This method is only provided for testing. For queries on classes, use the 1135 /// This method is only provided for testing. For queries on classes, use the
943 /// methods defined in [ClosedWorld]. 1136 /// methods defined in [ClosedWorld].
944 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) { 1137 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) {
945 return _classHierarchyNodes[cls.declaration]; 1138 return _classHierarchyNodes[cls.declaration];
946 } 1139 }
947 1140
948 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) {
949 cls = cls.declaration;
950 return _classHierarchyNodes.putIfAbsent(cls, () {
951 ClassHierarchyNode parentNode;
952 if (cls.superclass != null) {
953 parentNode = _ensureClassHierarchyNode(cls.superclass);
954 }
955 return new ClassHierarchyNode(parentNode, cls);
956 });
957 }
958
959 /// Returns [ClassSet] for [cls] used to model the extends and implements 1141 /// Returns [ClassSet] for [cls] used to model the extends and implements
960 /// relations of known classes. 1142 /// relations of known classes.
961 /// 1143 ///
962 /// This method is only provided for testing. For queries on classes, use the 1144 /// This method is only provided for testing. For queries on classes, use the
963 /// methods defined in [ClosedWorld]. 1145 /// methods defined in [ClosedWorld].
964 ClassSet getClassSet(ClassElement cls) { 1146 ClassSet getClassSet(ClassElement cls) {
965 return _classSets[cls.declaration]; 1147 return _classSets[cls.declaration];
966 } 1148 }
967 1149
968 ClassSet _ensureClassSet(ClassElement cls) { 1150 void registerClosureClass(ClosureClassElement cls) {
969 cls = cls.declaration; 1151 ClassHierarchyNode parentNode = getClassHierarchyNode(cls.superclass);
970 return _classSets.putIfAbsent(cls, () { 1152 ClassHierarchyNode node =
971 ClassHierarchyNode node = _ensureClassHierarchyNode(cls); 1153 _classHierarchyNodes[cls] = new ClassHierarchyNode(parentNode, cls);
972 ClassSet classSet = new ClassSet(node); 1154 for (InterfaceType type in cls.allSupertypes) {
973 1155 ClassSet subtypeSet = getClassSet(type.element);
974 for (InterfaceType type in cls.allSupertypes) { 1156 subtypeSet.addSubtype(node);
975 // TODO(johnniwinther): Optimization: Avoid adding [cls] to 1157 }
976 // superclasses. 1158 _classSets[cls] = new ClassSet(node);
977 ClassSet subtypeSet = _ensureClassSet(type.element); 1159 _updateSuperClassHierarchyNodeForClass(node);
978 subtypeSet.addSubtype(node); 1160 node.isDirectlyInstantiated = true;
979 }
980 if (cls.isMixinApplication) {
981 // TODO(johnniwinther): Store this in the [ClassSet].
982 MixinApplicationElement mixinApplication = cls;
983 if (mixinApplication.mixin != null) {
984 // If [mixinApplication] is malformed [mixin] is `null`.
985 registerMixinUse(mixinApplication, mixinApplication.mixin);
986 }
987 }
988
989 return classSet;
990 });
991 } 1161 }
992 1162
993 void _updateSuperClassHierarchyNodeForClass(ClassHierarchyNode node) { 1163 void _updateSuperClassHierarchyNodeForClass(ClassHierarchyNode node) {
994 // Ensure that classes implicitly implementing `Function` are in its 1164 // Ensure that classes implicitly implementing `Function` are in its
995 // subtype set. 1165 // subtype set.
996 ClassElement cls = node.cls; 1166 ClassElement cls = node.cls;
997 if (cls != coreClasses.functionClass && 1167 if (cls != commonElements.functionClass &&
998 cls.implementsFunction(coreClasses)) { 1168 cls.implementsFunction(commonElements)) {
999 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); 1169 ClassSet subtypeSet = getClassSet(commonElements.functionClass);
1000 subtypeSet.addSubtype(node); 1170 subtypeSet.addSubtype(node);
1001 } 1171 }
1002 if (!node.isInstantiated && node.parentNode != null) { 1172 if (!node.isInstantiated && node.parentNode != null) {
1003 _updateSuperClassHierarchyNodeForClass(node.parentNode); 1173 _updateSuperClassHierarchyNodeForClass(node.parentNode);
1004 } 1174 }
1005 } 1175 }
1006 1176
1007 void _updateClassHierarchyNodeForClass(ClassElement cls, 1177 Iterable<TypedefElement> get allTypedefs => _allTypedefs;
1008 {bool directlyInstantiated: false, bool abstractlyInstantiated: false}) {
1009 ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
1010 _updateSuperClassHierarchyNodeForClass(node);
1011 if (directlyInstantiated) {
1012 node.isDirectlyInstantiated = true;
1013 }
1014 if (abstractlyInstantiated) {
1015 node.isAbstractlyInstantiated = true;
1016 }
1017 }
1018
1019 ClosedWorld closeWorld(DiagnosticReporter reporter) {
1020 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated`
1021 /// properties of the [ClassHierarchyNode] for [cls].
1022
1023 void addSubtypes(ClassElement cls, InstantiationInfo info) {
1024 if (!info.hasInstantiation) {
1025 return;
1026 }
1027 if (cacheStrategy.hasIncrementalSupport && !alreadyPopulated.add(cls)) {
1028 return;
1029 }
1030 assert(cls.isDeclaration);
1031 if (!cls.isResolved) {
1032 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.');
1033 }
1034
1035 _updateClassHierarchyNodeForClass(cls,
1036 directlyInstantiated: info.isDirectlyInstantiated,
1037 abstractlyInstantiated: info.isAbstractlyInstantiated);
1038
1039 // Walk through the superclasses, and record the types
1040 // implemented by that type on the superclasses.
1041 ClassElement superclass = cls.superclass;
1042 while (superclass != null) {
1043 Set<Element> typesImplementedBySubclassesOfCls =
1044 _typesImplementedBySubclasses.putIfAbsent(
1045 superclass, () => new Set<ClassElement>());
1046 for (DartType current in cls.allSupertypes) {
1047 typesImplementedBySubclassesOfCls.add(current.element);
1048 }
1049 superclass = superclass.superclass;
1050 }
1051 }
1052
1053 // Use the [:seenClasses:] set to include non-instantiated
1054 // classes: if the superclass of these classes require RTI, then
1055 // they also need RTI, so that a constructor passes the type
1056 // variables to the super constructor.
1057 resolverWorld.forEachInstantiatedClass(addSubtypes);
1058
1059 _closed = true;
1060 _commonMasks = new CommonMasks(this);
1061 return this;
1062 }
1063 1178
1064 @override 1179 @override
1065 String dump([ClassElement cls]) { 1180 String dump([ClassElement cls]) {
1066 StringBuffer sb = new StringBuffer(); 1181 StringBuffer sb = new StringBuffer();
1067 if (cls != null) { 1182 if (cls != null) {
1068 sb.write("Classes in the closed world related to $cls:\n"); 1183 sb.write("Classes in the closed world related to $cls:\n");
1069 } else { 1184 } else {
1070 sb.write("Instantiated classes in the closed world:\n"); 1185 sb.write("Instantiated classes in the closed world:\n");
1071 } 1186 }
1072 getClassHierarchyNode(coreClasses.objectClass) 1187 getClassHierarchyNode(coreClasses.objectClass)
1073 .printOn(sb, ' ', instantiatedOnly: cls == null, withRespectTo: cls); 1188 .printOn(sb, ' ', instantiatedOnly: cls == null, withRespectTo: cls);
1074 return sb.toString(); 1189 return sb.toString();
1075 } 1190 }
1076 1191
1077 void registerMixinUse(
1078 MixinApplicationElement mixinApplication, ClassElement mixin) {
1079 // TODO(johnniwinther): Add map restricted to live classes.
1080 // We don't support patch classes as mixin.
1081 assert(mixin.isDeclaration);
1082 Set<MixinApplicationElement> users =
1083 _mixinUses.putIfAbsent(mixin, () => new Set<MixinApplicationElement>());
1084 users.add(mixinApplication);
1085 }
1086
1087 bool hasAnyUserDefinedGetter(Selector selector, TypeMask mask) { 1192 bool hasAnyUserDefinedGetter(Selector selector, TypeMask mask) {
1088 return allFunctions.filter(selector, mask).any((each) => each.isGetter); 1193 return allFunctions.filter(selector, mask).any((each) => each.isGetter);
1089 } 1194 }
1090 1195
1091 void registerUsedElement(Element element) {
1092 if (element.isInstanceMember && !element.isAbstract) {
1093 allFunctions.add(element);
1094 }
1095 }
1096
1097 FieldElement locateSingleField(Selector selector, TypeMask mask) { 1196 FieldElement locateSingleField(Selector selector, TypeMask mask) {
1098 Element result = locateSingleElement(selector, mask); 1197 Element result = locateSingleElement(selector, mask);
1099 return (result != null && result.isField) ? result : null; 1198 return (result != null && result.isField) ? result : null;
1100 } 1199 }
1101 1200
1102 Element locateSingleElement(Selector selector, TypeMask mask) { 1201 Element locateSingleElement(Selector selector, TypeMask mask) {
1103 assert(isClosed); 1202 assert(isClosed);
1104 mask ??= commonMasks.dynamicType; 1203 mask ??= commonMasks.dynamicType;
1105 return mask.locateSingleElement(selector, this); 1204 return mask.locateSingleElement(selector, this);
1106 } 1205 }
(...skipping 23 matching lines...) Expand all
1130 // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2). 1229 // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2).
1131 // TODO(sra): Refine the effect classification so that native effects are 1230 // TODO(sra): Refine the effect classification so that native effects are
1132 // distinct from ordinary Dart effects. 1231 // distinct from ordinary Dart effects.
1133 return false; 1232 return false;
1134 } 1233 }
1135 1234
1136 if (element.isFinal || element.isConst) { 1235 if (element.isFinal || element.isConst) {
1137 return true; 1236 return true;
1138 } 1237 }
1139 if (element.isInstanceMember) { 1238 if (element.isInstanceMember) {
1140 return !resolverWorld.hasInvokedSetter(element) && 1239 return !_resolverWorld.hasInvokedSetter(element) &&
1141 !resolverWorld.fieldSetters.contains(element); 1240 !_resolverWorld.fieldSetters.contains(element);
1142 } 1241 }
1143 return false; 1242 return false;
1144 } 1243 }
1145 1244
1146 SideEffects getSideEffectsOfElement(Element element) { 1245 SideEffects getSideEffectsOfElement(Element element) {
1147 // The type inferrer (where the side effects are being computed), 1246 // The type inferrer (where the side effects are being computed),
1148 // does not see generative constructor bodies because they are 1247 // does not see generative constructor bodies because they are
1149 // created by the backend. Also, it does not make any distinction 1248 // created by the backend. Also, it does not make any distinction
1150 // between a constructor and its body for side effects. This 1249 // between a constructor and its body for side effects. This
1151 // implies that currently, the side effects of a constructor body 1250 // implies that currently, the side effects of a constructor body
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1219 return getMightBePassedToApply(element.expression); 1318 return getMightBePassedToApply(element.expression);
1220 } 1319 }
1221 return functionsThatMightBePassedToApply.contains(element); 1320 return functionsThatMightBePassedToApply.contains(element);
1222 } 1321 }
1223 1322
1224 @override 1323 @override
1225 bool getCurrentlyKnownMightBePassedToApply(Element element) { 1324 bool getCurrentlyKnownMightBePassedToApply(Element element) {
1226 return getMightBePassedToApply(element); 1325 return getMightBePassedToApply(element);
1227 } 1326 }
1228 } 1327 }
1229
1230 /// Enum values defining subset of classes included in queries.
1231 enum ClassQuery {
1232 /// Only the class itself is included.
1233 EXACT,
1234
1235 /// The class and all subclasses (transitively) are included.
1236 SUBCLASS,
1237
1238 /// The class and all classes that implement or subclass it (transitively)
1239 /// are included.
1240 SUBTYPE,
1241 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/use_unused_api.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698