| 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!";
|
| -}
|
|
|