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

Unified Diff: pkg/front_end/lib/src/fasta/kernel/kernel_outline_shaker.dart

Issue 2894273002: Revert "First step for modular output in fasta." (Closed)
Patch Set: Created 3 years, 7 months 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 side-by-side diff with in-line comments
Download patch
Index: pkg/front_end/lib/src/fasta/kernel/kernel_outline_shaker.dart
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_outline_shaker.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_outline_shaker.dart
deleted file mode 100644
index 67508365e99deeeffecb824415bf2bb9aaaca924..0000000000000000000000000000000000000000
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_outline_shaker.dart
+++ /dev/null
@@ -1,406 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// A transformation to create a self-contained modular kernel without
-/// unnecessary references to other libraries.
-library fasta.kernel.kernel_outline_shaker;
-
-import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
-
-import '../errors.dart' show internalError;
-
-/// Removes from [program] unnecessary libraries, classes, and members.
-///
-/// This applies a simple "tree-shaking" technique: the full body of libraries
-/// whose URI match [isIncluded] is preserved, and so is the outline of the
-/// members and classes which are indicated by [data] (which should
-/// practically include all members and classes transitively visible from the
-/// included libraries).
-///
-/// The intent is that the resulting program has the entire code that is meant
-/// to be included and the minimum required to prevent dangling references and
-/// allow modular program transformations.
-///
-/// Note that the resulting program may include libraries not in [isIncluded],
-/// but those will be marked as external. There should be no method bodies for
-/// any members of those libraries.
-void trimProgram(Program program, RetainedData data, bool isIncluded(Uri uri)) {
- new KernelOutlineShaker(data, isIncluded).transform(program);
-}
-
-/// Informs about which libraries, classes, and members should be retained by
-/// the [KernelOutlineShaker] when tree-shaking.
-abstract class RetainedData {
- /// Whether a library should be preserved and mark as external.
- bool isLibraryUsed(Library library);
-
- /// Whether a class should be preserved. If a class is preserved, its
- /// supertypes will be preserved too, but some of it members may not be
- /// included.
- bool isClassUsed(Class cls);
-
- /// Whether a member should be preserved. If so, its enclosing class/library
- /// will be preserved too.
- bool isMemberUsed(Member member);
-}
-
-/// A builder of [RetainedData] that recursively marks transitive dependencies.
-///
-/// This builder contains APIs to mark the roots that are needed (e.g.
-/// [markClass] and [markMember]). Note this builder does not determine what
-/// roots to keep, that is done either directly by fasta while it is parsing, or
-/// by using a visitor like the [RootsMarker] below.
-class RetainedDataBuilder extends RetainedData {
- /// Libraries that contained code that is transitively reachable from the
- /// included libraries.
- final Set<Library> libraries = new Set<Library>();
-
- /// Classes that are transitively reachable from the included libraries.
- final Set<Class> classes = new Set<Class>();
-
- /// Members that are transitively reachable from the included libraries.
- final Set<Member> members = new Set<Member>();
-
- TypeMarker typeMarker;
-
- @override
- bool isLibraryUsed(Library library) => libraries.contains(library);
-
- @override
- bool isClassUsed(Class cls) => classes.contains(cls);
-
- @override
- bool isMemberUsed(Member m) => members.contains(m);
-
- RetainedDataBuilder() {
- typeMarker = new TypeMarker(this);
- }
-
- /// Mark a library as used.
- void markLibrary(Library lib) {
- libraries.add(lib);
- }
-
- /// Mark a class and it's supertypes as used.
- void markClass(Class cls) {
- if (cls == null || !classes.add(cls)) return;
- markLibrary(cls.parent);
- // TODO(sigmund): retain annotations?
- // visitList(cls.annotations, this);
- markSupertype(cls.supertype);
- markSupertype(cls.mixedInType);
- cls.implementedTypes.forEach(markSupertype);
- cls.typeParameters.forEach((t) => t.bound.accept(typeMarker));
- }
-
- /// Mark the class and type arguments of [node].
- void markSupertype(Supertype node) {
- if (node == null) return;
- markClass(node.classNode);
- node.typeArguments.forEach((t) => t.accept(typeMarker));
- }
-
- /// Mark a member and types mentioned on its interface.
- void markMember(Member m) {
- if (m == null || !members.add(m)) return;
- markMemberInterface(m);
- var parent = m.parent;
- if (parent is Library) {
- markLibrary(parent);
- } else if (parent is Class) {
- markClass(parent);
- }
- }
-
- void markMemberInterface(Member node) {
- if (node is Field) {
- node.type.accept(typeMarker);
- } else if (node is Procedure) {
- var function = node.function;
- function.typeParameters.forEach((p) => p.bound.accept(typeMarker));
- function.positionalParameters.forEach((p) => p.type.accept(typeMarker));
- function.namedParameters.forEach((p) => p.type.accept(typeMarker));
- function.returnType.accept(typeMarker);
- }
- }
-}
-
-/// A helper visitor used to mark transitive types by the [RetainedDataBuilder].
-class TypeMarker extends DartTypeVisitor {
- RetainedDataBuilder data;
-
- TypeMarker(this.data);
-
- visitInterfaceType(InterfaceType node) {
- data.markClass(node.classNode);
- node.typeArguments.forEach((t) => t.accept(this));
- }
-
- visitFunctionType(FunctionType node) {
- node.typeParameters.forEach((t) => t.bound.accept(this));
- node.positionalParameters.forEach((t) => t.accept(this));
- node.namedParameters.forEach((t) => t.type.accept(this));
- node.returnType.accept(this);
- }
-
- visitTypeParameterType(TypeParameterType node) {
- // Note: node.parameter is marked by marking the enclosing element.
- }
-
- visitTypedefType(TypedefType node) {
- node.typeArguments.forEach((t) => t.accept(this));
- }
-}
-
-/// Determines the root APIs that need to be retained before running the
-/// tree-shaker.
-///
-/// This is implemented using a visitor that walks through the sources that are
-/// intended to be part of the kernel output.
-// TODO(sigmund): delete. We should collect this information while
-// building kernel without having to run a visitor afterwards.
-class RootsMarker extends RecursiveVisitor {
- final RetainedDataBuilder data;
- RootsMarker(this.data);
-
- void run(Program program, bool isIncluded(Uri uri)) {
- markRequired(program);
- data.markMember(program.mainMethod);
- for (var library in program.libraries) {
- if (isIncluded(library.importUri)) {
- library.accept(this);
- }
- }
- }
-
- /// Marks classes and members that are assumed to exist by fasta or by
- /// transformers.
- // TODO(sigmund): consider being more fine-grained and only marking what is
- // seen and used.
- void markRequired(Program program) {
- var coreTypes = new CoreTypes(program);
- coreTypes.objectClass.members.forEach(data.markMember);
-
- // These are assumed to be available by fasta:
- data.markClass(coreTypes.objectClass);
- data.markClass(coreTypes.nullClass);
- data.markClass(coreTypes.boolClass);
- data.markClass(coreTypes.intClass);
- data.markClass(coreTypes.numClass);
- data.markClass(coreTypes.doubleClass);
- data.markClass(coreTypes.stringClass);
- data.markClass(coreTypes.listClass);
- data.markClass(coreTypes.mapClass);
- data.markClass(coreTypes.iterableClass);
- data.markClass(coreTypes.iteratorClass);
- data.markClass(coreTypes.futureClass);
- data.markClass(coreTypes.streamClass);
- data.markClass(coreTypes.symbolClass);
- data.markClass(coreTypes.internalSymbolClass);
- data.markClass(coreTypes.typeClass);
- data.markClass(coreTypes.functionClass);
- data.markClass(coreTypes.invocationClass);
- data.markMember(coreTypes.getMember("dart:_internal", "ExternalName", ""));
-
- // These are needed by the continuation (async/await) transformer:
- data.markClass(coreTypes.getClass('dart:core', 'Iterator'));
- data.markClass(coreTypes.getClass('dart:async', 'Future'));
- data.markClass(coreTypes.getClass('dart:async', 'FutureOr'));
- data.markClass(coreTypes.getClass('dart:async', 'Completer'));
- data.markMember(coreTypes.getMember('dart:async', 'Completer', 'sync'));
- data.markMember(coreTypes.getMember('dart:core', '_SyncIterable', ''));
- data.markMember(coreTypes.getMember('dart:async', '_StreamIterator', ''));
- data.markMember(coreTypes.getMember('dart:async', 'Future', 'microtask'));
- data.markMember(
- coreTypes.getMember('dart:async', '_AsyncStarStreamController', ''));
- data.markMember(coreTypes.getTopLevelMember('dart:core', 'print'));
- data.markMember(
- coreTypes.getTopLevelMember('dart:async', '_asyncThenWrapperHelper'));
- data.markMember(
- coreTypes.getTopLevelMember('dart:async', '_asyncErrorWrapperHelper'));
- data.markMember(coreTypes.getTopLevelMember('dart:async', '_awaitHelper'));
-
- // These are needed by the mixin transformer
- data.markMember(coreTypes.getMember('dart:core', '_InvocationMirror', ''));
- data.markMember(coreTypes.getMember('dart:core', 'List', 'from'));
- }
-
- visitConstructor(Constructor node) {
- if (!node.initializers.any((i) => i is SuperInitializer)) {
- // super() is currently implicit.
- for (var ctor in node.enclosingClass.supertype.classNode.constructors) {
- if (ctor.name.name == '') data.markMember(ctor);
- }
- }
- node.visitChildren(this);
- }
-
- @override
- visitSuperInitializer(SuperInitializer node) {
- data.markMember(node.target);
- node.visitChildren(this);
- }
-
- @override
- visitRedirectingInitializer(RedirectingInitializer node) {
- data.markMember(node.target);
- node.visitChildren(this);
- }
-
- @override
- visitConstructorInvocation(ConstructorInvocation node) {
- data.markMember(node.target);
- node.visitChildren(this);
- }
-
- @override
- visitStaticInvocation(StaticInvocation node) {
- data.markMember(node.target);
- node.visitChildren(this);
- }
-
- @override
- visitDirectMethodInvocation(DirectMethodInvocation node) {
- if (node.receiver is! ThisExpression) {
- return internalError('Direct calls are only supported on "this"');
- }
- data.markMember(node.target);
- node.visitChildren(this);
- }
-
- @override
- visitMethodInvocation(MethodInvocation node) {
- data.markMember(node.interfaceTarget);
- node.visitChildren(this);
- }
-
- @override
- visitStaticGet(StaticGet node) {
- data.markMember(node.target);
- node.visitChildren(this);
- }
-
- @override
- visitStaticSet(StaticSet node) {
- data.markMember(node.target);
- node.visitChildren(this);
- }
-
- @override
- visitDirectPropertyGet(DirectPropertyGet node) {
- data.markMember(node.target);
- node.visitChildren(this);
- }
-
- @override
- visitDirectPropertySet(DirectPropertySet node) {
- data.markMember(node.target);
- node.visitChildren(this);
- }
-
- @override
- visitSuperPropertyGet(SuperPropertyGet node) {
- data.markMember(node.interfaceTarget);
- node.visitChildren(this);
- }
-
- @override
- visitSuperPropertySet(SuperPropertySet node) {
- data.markMember(node.interfaceTarget);
- node.visitChildren(this);
- }
-
- @override
- visitPropertyGet(PropertyGet node) {
- data.markMember(node.interfaceTarget);
- node.visitChildren(this);
- }
-
- @override
- visitPropertySet(PropertySet node) {
- data.markMember(node.interfaceTarget);
- node.visitChildren(this);
- }
-
- @override
- visitInterfaceType(InterfaceType node) {
- data.markClass(node.classNode);
- node.visitChildren(this);
- }
-
- @override
- visitSupertype(Supertype node) {
- data.markClass(node.classNode);
- node.visitChildren(this);
- }
-
- @override
- visitTypedefReference(Typedef node) {
- return internalError('not implemented');
- }
-}
-
-/// Transformer that trims everything in the excluded libraries that is not
-/// marked as preserved by the given [RetainedData]. For every member in these
-/// excluded libraries, this transformer also removes function bodies and
-/// initializers.
-class KernelOutlineShaker extends Transformer {
- final RetainedData data;
- final Filter isIncluded;
-
- KernelOutlineShaker(this.data, this.isIncluded);
-
- void transform(Program program) {
- var toRemove = new Set<Library>();
- for (var library in program.libraries) {
- if (!isIncluded(library.importUri)) {
- if (!data.isLibraryUsed(library)) {
- toRemove.add(library);
- } else {
- library.isExternal = true;
- library.transformChildren(this);
- }
- }
- }
- program.libraries.removeWhere(toRemove.contains);
- }
-
- Class visitClass(Class node) {
- if (!data.isClassUsed(node)) {
- node.canonicalName?.unbind();
- return null; // Remove the class.
- } else {
- node.transformChildren(this);
- return node;
- }
- }
-
- Member defaultMember(Member node) {
- if (!data.isMemberUsed(node)) {
- node.canonicalName?.unbind();
- return null;
- } else {
- if (node is Procedure) {
- node.function.body = null;
- } else if (node is Field) {
- node.initializer = null;
- } else if (node is Constructor) {
- node.initializers.clear();
- node.function.body = null;
- }
- return node;
- }
- }
-
- /// Types appear to be encoded directly, so we have no need to preserve
- /// typedefs.
- // TODO(sigmund): revisit if this is not the case, the `inputError` in
- // [RootsMarker] is meant to detect this.
- Typedef visitTypedef(Typedef node) => null;
-
- TreeNode defaultTreeNode(TreeNode node) => node;
-}
-
-typedef bool Filter(Uri uri);
« no previous file with comments | « pkg/front_end/lib/src/base/processed_options.dart ('k') | pkg/front_end/lib/src/fasta/kernel/kernel_target.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698