Index: pkg/kernel/lib/transformations/treeshaker.dart |
diff --git a/pkg/kernel/lib/transformations/treeshaker.dart b/pkg/kernel/lib/transformations/treeshaker.dart |
index b4c331b72578d263c5b222c6f156d6e36b9dca1a..9ea89aa8494d0bca02b0c4f2dc5c6fecf9c54683 100644 |
--- a/pkg/kernel/lib/transformations/treeshaker.dart |
+++ b/pkg/kernel/lib/transformations/treeshaker.dart |
@@ -8,6 +8,7 @@ import '../ast.dart'; |
import '../class_hierarchy.dart'; |
import '../core_types.dart'; |
import '../type_environment.dart'; |
+import '../library_index.dart'; |
Program transformProgram(Program program, {List<ProgramRoot> programRoots}) { |
new TreeShaker(program, programRoots: programRoots).transform(program); |
@@ -49,6 +50,24 @@ class ProgramRoot { |
ProgramRoot(this.library, this.klass, this.member, this.kind); |
String toString() => "ProgramRoot($library, $klass, $member, $kind)"; |
+ |
+ String get disambiguatedName { |
+ if (kind == ProgramRootKind.Getter) return 'get:$member'; |
+ if (kind == ProgramRootKind.Setter) return 'set:$member'; |
+ return member; |
+ } |
+ |
+ Member getMember(LibraryIndex table) { |
+ assert(klass != null); |
+ assert(member != null); |
+ return table.getMember( |
+ library, klass ?? LibraryIndex.topLevel, disambiguatedName); |
+ } |
+ |
+ Class getClass(LibraryIndex table) { |
+ assert(klass != null); |
+ return table.getClass(library, klass); |
+ } |
} |
/// Tree shaking based on class hierarchy analysis. |
@@ -203,7 +222,7 @@ class TreeShaker { |
new _ExternalTypeVisitor(this, isContravariant: true); |
_invariantVisitor = new _ExternalTypeVisitor(this, |
isCovariant: true, isContravariant: true); |
- _mirrorsLibrary = coreTypes.getCoreLibrary('dart:mirrors'); |
+ _mirrorsLibrary = coreTypes.tryGetLibrary('dart:mirrors'); |
try { |
_build(); |
} on _UsingMirrorsException { |
@@ -223,7 +242,12 @@ class TreeShaker { |
_addDispatchedName(hierarchy.rootClass, new Name('noSuchMethod')); |
_addPervasiveUses(); |
_addUsedMember(null, program.mainMethod); |
- programRoots?.forEach(_addUsedRoot); |
+ if (programRoots != null) { |
+ var table = new LibraryIndex(program, programRoots.map((r) => r.library)); |
+ for (var root in programRoots) { |
+ _addUsedRoot(root, table); |
+ } |
+ } |
_iterateWorklist(); |
@@ -417,44 +441,33 @@ class TreeShaker { |
} |
/// Registers the given root as being used. |
- void _addUsedRoot(ProgramRoot root) { |
- Library rootLibrary = _findLibraryRoot(root, program); |
- |
+ void _addUsedRoot(ProgramRoot root, LibraryIndex table) { |
if (root.kind == ProgramRootKind.ExternallyInstantiatedClass) { |
- Class rootClass = _findClassRoot(root, rootLibrary); |
+ Class class_ = root.getClass(table); |
// This is a class which will be instantiated by non-Dart code (whether it |
// has a valid generative construtor or not). |
- _addInstantiatedClass(rootClass); |
+ _addInstantiatedClass(class_); |
// We keep all the constructors of externally instantiated classes. |
// Sometimes the runtime might do a constructor call and sometimes it |
// might just allocate the class without invoking the constructor. |
// So we try to be on the safe side here! |
- for (var constructor in rootClass.constructors) { |
- _addUsedMember(rootClass, constructor); |
+ for (var constructor in class_.constructors) { |
+ _addUsedMember(class_, constructor); |
} |
// We keep all factory constructors as well for the same reason. |
- for (var member in rootClass.procedures) { |
+ for (var member in class_.procedures) { |
if (member.isStatic && member.kind == ProcedureKind.Factory) { |
- _addUsedMember(rootClass, member); |
+ _addUsedMember(class_, member); |
} |
} |
} else { |
- if (root.klass != null) { |
- // For class members we mark the Field/Procedure/Constructor as used. |
- // We also mark it as instantiated if it's a constructor. |
- Class rootClass = _findClassRoot(root, rootLibrary); |
- Member rootMember = _findMemberRoot(root, rootClass.members); |
- _addUsedMember(rootClass, rootMember); |
- if (rootMember is Constructor) { |
- _addInstantiatedClass(rootClass); |
- } |
- } else { |
- // For library members we mark the Field/Procedure as used. |
- Member rootMember = _findMemberRoot(root, rootLibrary.members); |
- _addUsedMember(null, rootMember); |
+ var member = root.getMember(table); |
+ _addUsedMember(member.enclosingClass, member); |
+ if (member is Constructor) { |
+ _addInstantiatedClass(member.enclosingClass); |
} |
} |
} |
@@ -1070,53 +1083,3 @@ class _ExternalTypeVisitor extends DartTypeVisitor { |
/// Exception that is thrown to stop the tree shaking analysis when a use |
/// of `dart:mirrors` is found. |
class _UsingMirrorsException {} |
- |
-Library _findLibraryRoot(ProgramRoot root, Program program) { |
- for (var library in program.libraries) { |
- if (library.importUri.toString() == root.library) { |
- return library; |
- } |
- } |
- |
- throw "$root not found!"; |
-} |
- |
-Class _findClassRoot(ProgramRoot root, Library rootLibrary) { |
- for (var klass in rootLibrary.classes) { |
- if (klass.name == root.klass) { |
- return klass; |
- } |
- } |
- throw "$root not found!"; |
-} |
- |
-Member _findMemberRoot(ProgramRoot root, Iterable<Member> membersToSearch) { |
- for (var member in membersToSearch) { |
- if (member.name.name == root.member) { |
- switch (root.kind) { |
- case ProgramRootKind.Constructor: |
- if (member is Procedure && member.kind == ProcedureKind.Factory || |
- member is Constructor) { |
- return member; |
- } |
- break; |
- case ProgramRootKind.Setter: |
- if (member is Procedure && member.kind == ProcedureKind.Setter || |
- member is Field) { |
- return member; |
- } |
- break; |
- case ProgramRootKind.Getter: |
- if (member is Procedure && member.kind == ProcedureKind.Getter || |
- member is Field) { |
- return member; |
- } |
- break; |
- case ProgramRootKind.Other: |
- return member; |
- default: |
- } |
- } |
- } |
- throw "$root not found!"; |
-} |