1
0
mirror of https://github.com/dart-lang/sdk synced 2024-07-03 00:08:46 +00:00

[dart2js] Remove obsolete flags.

Removes 'new-deferred-split', 'no-new-deferred-split',
'report-invalid-deferred-types', 'defer-class-types', and
'no-defer-class-types'.

Change-Id: I8d7dd4500c776b2016697bf6c7342846041cc9fd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/164040
Commit-Queue: Joshua Litt <joshualitt@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
Joshua Litt 2020-09-25 17:04:14 +00:00 committed by commit-bot@chromium.org
parent f9e6e38b21
commit f767363767
9 changed files with 189 additions and 490 deletions

View File

@ -6,6 +6,8 @@
### Dart2JS
* Removed `--no-defer-class-types` and `--no-new-deferred-split'.
### Tools
#### Dartanalyzer

View File

@ -113,13 +113,6 @@ class Flags {
static const String soundNullSafety = '--sound-null-safety';
static const String noSoundNullSafety = '--no-sound-null-safety';
static const String newDeferredSplit = '--new-deferred-split';
static const String noNewDeferredSplit = '--no-new-deferred-split';
static const String reportInvalidInferredDeferredTypes =
'--report-invalid-deferred-types';
static const String deferClassTypes = '--defer-class-types';
static const String noDeferClassTypes = '--no-defer-class-types';
/// Flag for a combination of flags for 'production' mode.
static const String benchmarkingProduction = '--benchmarking-production';

View File

@ -468,10 +468,6 @@ Future<api.CompilationResult> compile(List<String> argv,
new OptionHandler(Flags.disableRtiOptimization, passThrough),
new OptionHandler(Flags.terse, passThrough),
new OptionHandler('--deferred-map=.+', passThrough),
new OptionHandler(Flags.newDeferredSplit, passThrough),
new OptionHandler(Flags.reportInvalidInferredDeferredTypes, passThrough),
new OptionHandler(Flags.deferClassTypes, passThrough),
new OptionHandler(Flags.noDeferClassTypes, passThrough),
new OptionHandler('${Flags.dumpInfo}|${Flags.dumpInfo}=.+', setDumpInfo),
new OptionHandler('--disallow-unsafe-eval', ignoreOption),
new OptionHandler(Option.showPackageWarnings, passThrough),

View File

@ -7,6 +7,8 @@ library deferred_load;
import 'dart:collection' show Queue;
import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;
import 'common/metrics.dart' show Metric, Metrics, CountMetric, DurationMetric;
import 'common/tasks.dart' show CompilerTask;
@ -18,12 +20,13 @@ import 'constants/values.dart'
show
ConstantValue,
ConstructedConstantValue,
TypeConstantValue,
DeferredGlobalConstantValue,
InstantiationConstantValue;
import 'elements/types.dart';
import 'elements/entities.dart';
import 'ir/util.dart';
import 'kernel/kelements.dart' show KLocalFunction;
import 'kernel/element_map.dart';
import 'serialization/serialization.dart';
import 'options.dart';
import 'universe/use.dart';
@ -102,7 +105,7 @@ class _DeferredLoadTaskMetrics implements Metrics {
/// For each deferred import, find elements and constants to be loaded when that
/// import is loaded. Elements that are used by several deferred imports are in
/// shared OutputUnits.
abstract class DeferredLoadTask extends CompilerTask {
class DeferredLoadTask extends CompilerTask {
@override
String get name => 'Deferred Loading';
@ -149,17 +152,15 @@ abstract class DeferredLoadTask extends CompilerTask {
final Compiler compiler;
KernelToElementMap _elementMap;
@override
final _DeferredLoadTaskMetrics metrics = _DeferredLoadTaskMetrics();
bool get disableProgramSplit => compiler.options.disableProgramSplit;
bool get newDeferredSplit => compiler.options.newDeferredSplit;
bool get reportInvalidInferredDeferredTypes =>
compiler.options.reportInvalidInferredDeferredTypes;
bool get deferClassTypes => compiler.options.deferClassTypes;
DeferredLoadTask(this.compiler) : super(compiler.measurer) {
_mainOutputUnit = OutputUnit(true, 'main', <ImportEntity>{});
DeferredLoadTask(this.compiler, this._elementMap) : super(compiler.measurer) {
_mainOutputUnit = OutputUnit(true, 'main', {});
importSets.mainSet.unit = _mainOutputUnit;
_allOutputUnits.add(_mainOutputUnit);
}
@ -172,27 +173,6 @@ abstract class DeferredLoadTask extends CompilerTask {
DiagnosticReporter get reporter => compiler.reporter;
/// Given [imports] that refer to an element from a library, determine whether
/// the element is explicitly deferred.
static bool _isExplicitlyDeferred(Iterable<ImportEntity> imports) {
// If the element is not imported explicitly, it is implicitly imported
// not deferred.
if (imports.isEmpty) return false;
// An element could potentially be loaded by several imports. If all of them
// is explicitly deferred, we say the element is explicitly deferred.
// TODO(sigurdm): We might want to give a warning if the imports do not
// agree.
return imports.every((ImportEntity import) => import.isDeferred);
}
/// Returns every [ImportEntity] that imports [element] into [library].
Iterable<ImportEntity> classImportsTo(
ClassEntity element, LibraryEntity library);
/// Returns every [ImportEntity] that imports [element] into [library].
Iterable<ImportEntity> memberImportsTo(
MemberEntity element, LibraryEntity library);
/// Collects all direct dependencies of [element].
///
/// The collected dependent elements and constants are are added to
@ -275,30 +255,37 @@ abstract class DeferredLoadTask extends CompilerTask {
// they are processed as part of the class.
}
/// Extract the set of constants that are used in annotations of [element].
///
/// If the underlying system doesn't support mirrors, then no constants are
/// added.
void collectConstantsFromMetadata(
Entity element, Set<ConstantValue> constants);
/// Extract the set of constants that are used in the body of [element].
void collectConstantsInBody(MemberEntity element, Dependencies dependencies);
void collectConstantsInBody(MemberEntity element, Dependencies dependencies) {
ir.Member node = _elementMap.getMemberNode(element);
// Fetch the internal node in order to skip annotations on the member.
// TODO(sigmund): replace this pattern when the kernel-ast provides a better
// way to skip annotations (issue 31565).
var visitor = new ConstantCollector(
_elementMap, _elementMap.getStaticTypeContext(element), dependencies);
if (node is ir.Field) {
node.initializer?.accept(visitor);
return;
}
if (node is ir.Constructor) {
node.initializers.forEach((i) => i.accept(visitor));
}
node.function?.accept(visitor);
}
/// Recursively collects all the dependencies of [type].
void _collectTypeDependencies(DartType type, Dependencies dependencies,
[ImportEntity import]) {
TypeDependencyVisitor(dependencies, import, commonElements,
collectClassesAndTypes: !deferClassTypes)
.visit(type);
TypeDependencyVisitor(dependencies, import, commonElements).visit(type);
}
void _collectTypeArgumentDependencies(
Iterable<DartType> typeArguments, Dependencies dependencies,
[ImportEntity import]) {
if (typeArguments == null) return;
TypeDependencyVisitor(dependencies, import, commonElements,
collectClassesAndTypes: !deferClassTypes)
TypeDependencyVisitor(dependencies, import, commonElements)
.visitList(typeArguments);
}
@ -600,62 +587,6 @@ abstract class DeferredLoadTask extends CompilerTask {
/// same nodes we have already seen.
_shouldAddDeferredDependency(ImportSet newSet) => newSet.length <= 1;
void _fixDependencyInfo(DependencyInfo info, List<ImportEntity> imports,
String prefix, String name, Spannable context) {
var isDeferred = _isExplicitlyDeferred(imports);
if (isDeferred) {
if (!newDeferredSplit) {
info.isDeferred = true;
info.imports = imports;
}
if (reportInvalidInferredDeferredTypes) {
reporter.reportErrorMessage(context, MessageKind.GENERIC, {
'text': "$prefix '$name' is deferred but appears to be inferred as"
" a return type or a type parameter (dartbug.com/35311)."
});
}
}
}
// The following 3 methods are used to check whether the new deferred split
// algorithm and the old one match. Because of a soundness bug in the old
// algorithm the new algorithm can pull in a lot of code to the main output
// unit. This logic detects it and will make it easier for us to migrate code
// off it incrementally.
// Note: we only expect discrepancies on class-dependency-info due to how
// inferred types expose deferred types in type-variables and return types
// (Issue #35311). We added the other two methods to test our transition, but
// we don't expect to detect any mismatches there.
//
// TODO(sigmund): delete once the new implementation is on by default.
void _fixClassDependencyInfo(DependencyInfo info, ClassEntity cls,
LibraryEntity library, Spannable context) {
if (info.isDeferred) return;
if (newDeferredSplit && !reportInvalidInferredDeferredTypes) return;
var imports = classImportsTo(cls, library);
_fixDependencyInfo(info, imports, "Class", cls.name, context);
}
void _fixMemberDependencyInfo(DependencyInfo info, MemberEntity member,
LibraryEntity library, Spannable context) {
if (info.isDeferred || compiler.options.newDeferredSplit) return;
var imports = memberImportsTo(member, library);
_fixDependencyInfo(info, imports, "Member", member.name, context);
}
void _fixConstantDependencyInfo(DependencyInfo info, ConstantValue constant,
LibraryEntity library, Spannable context) {
if (info.isDeferred || compiler.options.newDeferredSplit) return;
if (constant is TypeConstantValue) {
var type = constant.representedType.withoutNullability;
if (type is InterfaceType) {
var imports = classImportsTo(type.element, library);
_fixDependencyInfo(
info, imports, "Class (in constant) ", type.element.name, context);
}
}
}
void _processDependencies(
KClosedWorld closedWorld,
LibraryEntity library,
@ -665,7 +596,6 @@ abstract class DeferredLoadTask extends CompilerTask {
WorkQueue queue,
Spannable context) {
dependencies.classes.forEach((ClassEntity cls, DependencyInfo info) {
_fixClassDependencyInfo(info, cls, library, context);
if (info.isDeferred) {
if (_shouldAddDeferredDependency(newSet)) {
for (ImportEntity deferredImport in info.imports) {
@ -678,7 +608,6 @@ abstract class DeferredLoadTask extends CompilerTask {
});
dependencies.classType.forEach((ClassEntity cls, DependencyInfo info) {
_fixClassDependencyInfo(info, cls, library, context);
if (info.isDeferred) {
if (_shouldAddDeferredDependency(newSet)) {
for (ImportEntity deferredImport in info.imports) {
@ -691,7 +620,6 @@ abstract class DeferredLoadTask extends CompilerTask {
});
dependencies.members.forEach((MemberEntity member, DependencyInfo info) {
_fixMemberDependencyInfo(info, member, library, context);
if (info.isDeferred) {
if (_shouldAddDeferredDependency(newSet)) {
for (ImportEntity deferredImport in info.imports) {
@ -709,7 +637,6 @@ abstract class DeferredLoadTask extends CompilerTask {
dependencies.constants
.forEach((ConstantValue constant, DependencyInfo info) {
_fixConstantDependencyInfo(info, constant, library, context);
if (info.isDeferred) {
if (_shouldAddDeferredDependency(newSet)) {
for (ImportEntity deferredImport in info.imports) {
@ -948,10 +875,8 @@ abstract class DeferredLoadTask extends CompilerTask {
_localFunctionToSet = null;
_constantToSet = null;
importSets = null;
cleanup();
return OutputUnitData(
this.isProgramSplit && !disableProgramSplit,
deferClassTypes,
this._mainOutputUnit,
classMap,
classTypeMap,
@ -964,15 +889,11 @@ abstract class DeferredLoadTask extends CompilerTask {
_deferredImportDescriptions);
}
/// Frees up strategy-specific temporary data.
void cleanup() {}
void beforeResolution(Uri rootLibraryUri, Iterable<Uri> libraries) {
measureSubtask('prepare', () {
for (Uri uri in libraries) {
LibraryEntity library = elementEnvironment.lookupLibrary(uri);
reporter.withCurrentElement(library, () {
checkForDeferredErrorCases(library);
for (ImportEntity import in elementEnvironment.getImports(library)) {
if (import.isDeferred) {
_deferredImportDescriptions[import] =
@ -985,13 +906,6 @@ abstract class DeferredLoadTask extends CompilerTask {
});
}
/// Detects errors like duplicate uses of a prefix or using the old deferred
/// loading syntax.
///
/// These checks are already done by the shared front-end, so they can be
/// skipped by the new compiler pipeline.
void checkForDeferredErrorCases(LibraryEntity library);
bool ignoreEntityInDump(Entity element) => false;
/// Creates a textual representation of the output unit content.
@ -1014,7 +928,7 @@ abstract class DeferredLoadTask extends CompilerTask {
});
_memberToSet.forEach((MemberEntity element, ImportSet importSet) {
if (ignoreEntityInDump(element)) return;
var elements = elementMap.putIfAbsent(importSet.unit, () => <String>[]);
var elements = elementMap.putIfAbsent(importSet.unit, () => []);
var id = element.name ?? '$element';
var cls = element.enclosingClass?.name;
if (cls != null) id = '$cls.$id';
@ -1024,7 +938,7 @@ abstract class DeferredLoadTask extends CompilerTask {
});
_localFunctionToSet.forEach((Local element, ImportSet importSet) {
if (ignoreEntityInDump(element)) return;
var elements = elementMap.putIfAbsent(importSet.unit, () => <String>[]);
var elements = elementMap.putIfAbsent(importSet.unit, () => []);
var id = element.name ?? '$element';
var context = (element as dynamic).memberContext.name;
id = element.name == null || element.name == '' ? '<anonymous>' : id;
@ -1037,7 +951,7 @@ abstract class DeferredLoadTask extends CompilerTask {
// if they are shared, they end up duplicated anyways across output units.
if (value.isPrimitive) return;
constantMap
.putIfAbsent(importSet.unit, () => <String>[])
.putIfAbsent(importSet.unit, () => [])
.add(value.toStructuredText(dartTypes));
});
@ -1464,7 +1378,6 @@ class OutputUnitData {
static const String tag = 'output-unit-data';
final bool isProgramSplit;
final bool deferClassTypes;
final OutputUnit mainOutputUnit;
final Map<ClassEntity, OutputUnit> _classToUnit;
final Map<ClassEntity, OutputUnit> _classTypeToUnit;
@ -1489,7 +1402,6 @@ class OutputUnitData {
OutputUnitData(
this.isProgramSplit,
this.deferClassTypes,
this.mainOutputUnit,
this._classToUnit,
this._classTypeToUnit,
@ -1532,13 +1444,12 @@ class OutputUnitData {
return OutputUnitData(
other.isProgramSplit,
other.deferClassTypes,
other.mainOutputUnit,
classToUnit,
classTypeToUnit,
memberToUnit,
// Local functions only make sense in the K-world model.
const <Local, OutputUnit>{},
const {},
constantToUnit,
other.outputUnits,
other._importDeferName,
@ -1550,7 +1461,6 @@ class OutputUnitData {
factory OutputUnitData.readFromDataSource(DataSource source) {
source.begin(tag);
bool isProgramSplit = source.readBool();
bool deferClassTypes = source.readBool();
List<OutputUnit> outputUnits = source.readList(() {
bool isMainOutput = source.readBool();
String name = source.readString();
@ -1589,13 +1499,12 @@ class OutputUnitData {
source.end(tag);
return OutputUnitData(
isProgramSplit,
deferClassTypes,
mainOutputUnit,
classToUnit,
classTypeToUnit,
memberToUnit,
// Local functions only make sense in the K-world model.
const <Local, OutputUnit>{},
const {},
constantToUnit,
outputUnits,
importDeferName,
@ -1607,7 +1516,6 @@ class OutputUnitData {
void writeToDataSink(DataSink sink) {
sink.begin(tag);
sink.writeBool(isProgramSplit);
sink.writeBool(deferClassTypes);
Map<OutputUnit, int> outputUnitIndices = {};
sink.writeList(outputUnits, (OutputUnit outputUnit) {
outputUnitIndices[outputUnit] = outputUnitIndices.length;
@ -1661,18 +1569,13 @@ class OutputUnitData {
// TODO(joshualitt): see above TODO regarding allowNull.
OutputUnit outputUnitForClassType(ClassEntity cls, {bool allowNull: false}) {
if (!isProgramSplit) return mainOutputUnit;
OutputUnit unit;
if (deferClassTypes) {
unit = _classTypeToUnit[cls];
} else {
unit = _classToUnit[cls];
}
OutputUnit unit = _classTypeToUnit[cls];
assert(allowNull || unit != null, 'No output unit for type $cls');
return unit ?? mainOutputUnit;
}
OutputUnit outputUnitForClassTypeForTesting(ClassEntity cls) =>
deferClassTypes ? _classTypeToUnit[cls] : _classToUnit[cls];
_classTypeToUnit[cls];
/// Returns the [OutputUnit] where [member] belongs.
OutputUnit outputUnitForMember(MemberEntity member) {
@ -1801,10 +1704,8 @@ class OutputUnitData {
Map<String, dynamic> libraryMap = mapping.putIfAbsent(
description.importingUri,
() => <String, dynamic>{
"name": getName(description._importingLibrary),
"imports": <String, List<String>>{}
});
() =>
{"name": getName(description._importingLibrary), "imports": {}});
List<String> partFileNames = outputUnits
.where((outputUnit) => !omittedUnits.contains(outputUnit))
@ -1874,16 +1775,11 @@ class DependencyInfo {
}
class TypeDependencyVisitor implements DartTypeVisitor<void, Null> {
// If true, collect classes and types, otherwise just collect types.
// Note: When collecting classes, types are added implicitly by the
// dependencies class.
final bool collectClassesAndTypes;
final Dependencies _dependencies;
final ImportEntity _import;
final CommonElements _commonElements;
TypeDependencyVisitor(this._dependencies, this._import, this._commonElements,
{this.collectClassesAndTypes});
TypeDependencyVisitor(this._dependencies, this._import, this._commonElements);
@override
void visit(DartType type, [_]) {
@ -1906,11 +1802,7 @@ class TypeDependencyVisitor implements DartTypeVisitor<void, Null> {
@override
void visitFutureOrType(FutureOrType type, Null argument) {
if (collectClassesAndTypes) {
_dependencies.addClass(_commonElements.futureClass);
} else {
_dependencies.addClassType(_commonElements.futureClass);
}
_dependencies.addClassType(_commonElements.futureClass);
visit(type.typeArgument);
}
@ -1937,11 +1829,7 @@ class TypeDependencyVisitor implements DartTypeVisitor<void, Null> {
@override
void visitInterfaceType(InterfaceType type, Null argument) {
visitList(type.typeArguments);
if (collectClassesAndTypes) {
_dependencies.addClass(type.element, _import);
} else {
_dependencies.addClassType(type.element, _import);
}
_dependencies.addClassType(type.element, _import);
}
@override
@ -1970,3 +1858,108 @@ class TypeDependencyVisitor implements DartTypeVisitor<void, Null> {
// Nothing to add.
}
}
class ConstantCollector extends ir.RecursiveVisitor {
final KernelToElementMap elementMap;
final Dependencies dependencies;
final ir.StaticTypeContext staticTypeContext;
ConstantCollector(this.elementMap, this.staticTypeContext, this.dependencies);
CommonElements get commonElements => elementMap.commonElements;
void add(ir.Expression node, {bool required: true}) {
ConstantValue constant = elementMap
.getConstantValue(staticTypeContext, node, requireConstant: required);
if (constant != null) {
dependencies.addConstant(
constant, elementMap.getImport(getDeferredImport(node)));
}
}
@override
void visitIntLiteral(ir.IntLiteral literal) {}
@override
void visitDoubleLiteral(ir.DoubleLiteral literal) {}
@override
void visitBoolLiteral(ir.BoolLiteral literal) {}
@override
void visitStringLiteral(ir.StringLiteral literal) {}
@override
void visitSymbolLiteral(ir.SymbolLiteral literal) => add(literal);
@override
void visitNullLiteral(ir.NullLiteral literal) {}
@override
void visitListLiteral(ir.ListLiteral literal) {
if (literal.isConst) {
add(literal);
} else {
super.visitListLiteral(literal);
}
}
@override
void visitSetLiteral(ir.SetLiteral literal) {
if (literal.isConst) {
add(literal);
} else {
super.visitSetLiteral(literal);
}
}
@override
void visitMapLiteral(ir.MapLiteral literal) {
if (literal.isConst) {
add(literal);
} else {
super.visitMapLiteral(literal);
}
}
@override
void visitConstructorInvocation(ir.ConstructorInvocation node) {
if (node.isConst) {
add(node);
} else {
super.visitConstructorInvocation(node);
}
}
@override
void visitTypeParameter(ir.TypeParameter node) {
// We avoid visiting metadata on the type parameter declaration. The bound
// cannot hold constants so we skip that as well.
}
@override
void visitVariableDeclaration(ir.VariableDeclaration node) {
// We avoid visiting metadata on the parameter declaration by only visiting
// the initializer. The type cannot hold constants so can kan skip that
// as well.
node.initializer?.accept(this);
}
@override
void visitTypeLiteral(ir.TypeLiteral node) {
if (node.type is! ir.TypeParameterType) add(node);
}
@override
void visitInstantiation(ir.Instantiation node) {
// TODO(johnniwinther): The CFE should mark constant instantiations as
// constant.
add(node, required: false);
super.visitInstantiation(node);
}
@override
void visitConstantExpression(ir.ConstantExpression node) {
add(node);
}
}

View File

@ -9,7 +9,6 @@ part of dart2js.js_emitter.program_builder;
///
/// The code for the containing (used) methods must exist in the `universe`.
class Collector {
final CompilerOptions _options;
final JCommonElements _commonElements;
final JElementEnvironment _elementEnvironment;
final OutputUnitData _outputUnitData;
@ -43,7 +42,6 @@ class Collector {
final List<ClassEntity> nativeClassesAndSubclasses = [];
Collector(
this._options,
this._commonElements,
this._elementEnvironment,
this._outputUnitData,
@ -105,7 +103,7 @@ class Collector {
// Return the classes that are just helpers for the backend's type system.
static Iterable<ClassEntity> getBackendTypeHelpers(
JCommonElements commonElements) {
return <ClassEntity>[
return [
commonElements.jsMutableArrayClass,
commonElements.jsFixedArrayClass,
commonElements.jsExtendableArrayClass,
@ -137,14 +135,6 @@ class Collector {
}
}
Map<OutputUnit, List<ClassEntity>> get _outputListsForClassType {
if (_options.deferClassTypes) {
return outputClassTypeLists;
} else {
return outputClassLists;
}
}
/// Compute all the classes and typedefs that must be emitted.
void computeNeededDeclarations() {
Set<ClassEntity> backendTypeHelpers =
@ -157,7 +147,6 @@ class Collector {
return !backendTypeHelpers.contains(cls) &&
_rtiNeededClasses.contains(cls) &&
!classesOnlyNeededForRti.contains(cls) &&
_options.deferClassTypes &&
_outputUnitData.outputUnitForClass(cls) !=
_outputUnitData.outputUnitForClassType(cls);
}
@ -240,7 +229,7 @@ class Collector {
// 7. Sort classes needed for type checking and then add them to their
// respective OutputUnits.
for (ClassEntity cls in _sorter.sortClasses(neededClassTypes)) {
_outputListsForClassType
outputClassTypeLists
.putIfAbsent(_outputUnitData.outputUnitForClassType(cls), () => [])
.add(cls);
}

View File

@ -135,7 +135,6 @@ class ProgramBuilder {
this._rtiNeededClasses,
this._mainFunction)
: this.collector = new Collector(
_options,
_commonElements,
_elementEnvironment,
_outputUnitData,
@ -653,16 +652,11 @@ class ProgramBuilder {
Class _buildClass(ClassEntity cls) {
bool onlyForConstructor =
collector.classesOnlyNeededForConstructor.contains(cls);
bool onlyForRti = _options.deferClassTypes
? false
: collector.classesOnlyNeededForRti.contains(cls);
// TODO(joshualitt): Can we just emit JSInteropClasses as types?
// TODO(jacobr): check whether the class has any active static fields
// if it does not we can suppress it completely.
bool onlyForRti = _nativeData.isJsInteropClass(cls);
bool hasRtiField = _rtiNeed.classNeedsTypeArguments(cls);
if (_nativeData.isJsInteropClass(cls)) {
// TODO(joshualitt): Can we just emit JSInteropClasses as types?
// TODO(jacobr): check whether the class has any active static fields
// if it does not we can suppress it completely.
onlyForRti = true;
}
bool onlyForConstructorOrRti = onlyForConstructor || onlyForRti;
bool isClosureBaseClass = cls == _commonElements.closureClass;

View File

@ -1,217 +0,0 @@
// Copyright (c) 2014, 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.
library kernel.deferred_load_data;
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;
import '../common_elements.dart';
import '../compiler.dart' show Compiler;
import '../constants/values.dart';
import '../deferred_load.dart';
import '../elements/entities.dart';
import '../ir/util.dart';
import 'element_map.dart';
class KernelDeferredLoadTask extends DeferredLoadTask {
KernelToElementMap _elementMap;
Map<ir.Library, Set<ir.NamedNode>> _additionalExportsSets =
<ir.Library, Set<ir.NamedNode>>{};
KernelDeferredLoadTask(Compiler compiler, this._elementMap) : super(compiler);
Iterable<ImportEntity> _findImportsTo(ir.NamedNode node, String nodeName,
ir.Library enclosingLibrary, LibraryEntity library) {
return measureSubtask('find-imports', () {
List<ImportEntity> imports = [];
ir.Library source = _elementMap.getLibraryNode(library);
if (!source.dependencies.any((d) => d.isDeferred)) return const [];
for (ir.LibraryDependency dependency in source.dependencies) {
if (dependency.isExport) continue;
if (!_isVisible(dependency.combinators, nodeName)) continue;
if (enclosingLibrary == dependency.targetLibrary ||
additionalExports(dependency.targetLibrary).contains(node)) {
imports.add(_elementMap.getImport(dependency));
}
}
return imports;
});
}
@override
Iterable<ImportEntity> classImportsTo(
ClassEntity element, LibraryEntity library) {
ir.Class node = _elementMap.getClassNode(element);
return _findImportsTo(node, node.name, node.enclosingLibrary, library);
}
@override
Iterable<ImportEntity> memberImportsTo(
Entity element, LibraryEntity library) {
ir.Member node = _elementMap.getMemberNode(element);
return _findImportsTo(
node is ir.Constructor ? node.enclosingClass : node,
node is ir.Constructor ? node.enclosingClass.name : node.name.text,
node.enclosingLibrary,
library);
}
@override
void checkForDeferredErrorCases(LibraryEntity library) {
// Nothing to do. The FE checks for error cases upfront.
}
@override
void collectConstantsFromMetadata(
Entity element, Set<ConstantValue> constants) {
// Nothing to do. Kernel-pipeline doesn't support mirrors, so we don't need
// to track any constants from meta-data.
}
@override
void collectConstantsInBody(MemberEntity element, Dependencies dependencies) {
ir.Member node = _elementMap.getMemberNode(element);
// Fetch the internal node in order to skip annotations on the member.
// TODO(sigmund): replace this pattern when the kernel-ast provides a better
// way to skip annotations (issue 31565).
var visitor = new ConstantCollector(
_elementMap, _elementMap.getStaticTypeContext(element), dependencies);
if (node is ir.Field) {
node.initializer?.accept(visitor);
return;
}
if (node is ir.Constructor) {
node.initializers.forEach((i) => i.accept(visitor));
}
node.function?.accept(visitor);
}
Set<ir.NamedNode> additionalExports(ir.Library library) {
return _additionalExportsSets[library] ??= new Set<ir.NamedNode>.from(
library.additionalExports.map((ir.Reference ref) => ref.node));
}
@override
void cleanup() {
_additionalExportsSets = null;
}
}
/// Returns whether [name] would be visible according to the given list of
/// show/hide [combinators].
bool _isVisible(List<ir.Combinator> combinators, String name) {
for (var c in combinators) {
if (c.isShow && !c.names.contains(name)) return false;
if (c.isHide && c.names.contains(name)) return false;
}
return true;
}
class ConstantCollector extends ir.RecursiveVisitor {
final KernelToElementMap elementMap;
final Dependencies dependencies;
final ir.StaticTypeContext staticTypeContext;
ConstantCollector(this.elementMap, this.staticTypeContext, this.dependencies);
CommonElements get commonElements => elementMap.commonElements;
void add(ir.Expression node, {bool required: true}) {
ConstantValue constant = elementMap
.getConstantValue(staticTypeContext, node, requireConstant: required);
if (constant != null) {
dependencies.addConstant(
constant, elementMap.getImport(getDeferredImport(node)));
}
}
@override
void visitIntLiteral(ir.IntLiteral literal) {}
@override
void visitDoubleLiteral(ir.DoubleLiteral literal) {}
@override
void visitBoolLiteral(ir.BoolLiteral literal) {}
@override
void visitStringLiteral(ir.StringLiteral literal) {}
@override
void visitSymbolLiteral(ir.SymbolLiteral literal) => add(literal);
@override
void visitNullLiteral(ir.NullLiteral literal) {}
@override
void visitListLiteral(ir.ListLiteral literal) {
if (literal.isConst) {
add(literal);
} else {
super.visitListLiteral(literal);
}
}
@override
void visitSetLiteral(ir.SetLiteral literal) {
if (literal.isConst) {
add(literal);
} else {
super.visitSetLiteral(literal);
}
}
@override
void visitMapLiteral(ir.MapLiteral literal) {
if (literal.isConst) {
add(literal);
} else {
super.visitMapLiteral(literal);
}
}
@override
void visitConstructorInvocation(ir.ConstructorInvocation node) {
if (node.isConst) {
add(node);
} else {
super.visitConstructorInvocation(node);
}
}
@override
void visitTypeParameter(ir.TypeParameter node) {
// We avoid visiting metadata on the type parameter declaration. The bound
// cannot hold constants so we skip that as well.
}
@override
void visitVariableDeclaration(ir.VariableDeclaration node) {
// We avoid visiting metadata on the parameter declaration by only visiting
// the initializer. The type cannot hold constants so can kan skip that
// as well.
node.initializer?.accept(this);
}
@override
void visitTypeLiteral(ir.TypeLiteral node) {
if (node.type is! ir.TypeParameterType) add(node);
}
@override
void visitInstantiation(ir.Instantiation node) {
// TODO(johnniwinther): The CFE should mark constant instantiations as
// constant.
add(node, required: false);
super.visitInstantiation(node);
}
@override
void visitConstantExpression(ir.ConstantExpression node) {
add(node);
}
}

View File

@ -45,7 +45,6 @@ import '../universe/resolution_world_builder.dart';
import '../universe/world_builder.dart';
import '../universe/world_impact.dart';
import '../util/enumset.dart';
import 'deferred_load.dart';
import 'element_map.dart';
import 'element_map_impl.dart';
import 'loader.dart';
@ -54,7 +53,7 @@ import 'loader.dart';
/// model from kernel IR nodes.
class KernelFrontendStrategy extends FrontendStrategy {
final NativeBasicDataBuilderImpl nativeBasicDataBuilder =
new NativeBasicDataBuilderImpl();
NativeBasicDataBuilderImpl();
NativeBasicData _nativeBasicData;
CompilerOptions _options;
CompilerTask _compilerTask;
@ -87,12 +86,11 @@ class KernelFrontendStrategy extends FrontendStrategy {
KernelFrontendStrategy(this._compilerTask, this._options,
DiagnosticReporter reporter, env.Environment environment) {
assert(_compilerTask != null);
_elementMap =
new KernelToElementMapImpl(reporter, environment, this, _options);
_modularStrategy = new KernelModularStrategy(_compilerTask, _elementMap);
_backendUsageBuilder = new BackendUsageBuilderImpl(this);
noSuchMethodRegistry = new NoSuchMethodRegistryImpl(
commonElements, new KernelNoSuchMethodResolver(_elementMap));
_elementMap = KernelToElementMapImpl(reporter, environment, this, _options);
_modularStrategy = KernelModularStrategy(_compilerTask, _elementMap);
_backendUsageBuilder = BackendUsageBuilderImpl(this);
noSuchMethodRegistry = NoSuchMethodRegistryImpl(
commonElements, KernelNoSuchMethodResolver(_elementMap));
}
NativeResolutionEnqueuer get nativeResolutionEnqueuerForTesting =>
@ -139,32 +137,30 @@ class KernelFrontendStrategy extends FrontendStrategy {
ResolutionEnqueuer createResolutionEnqueuer(
CompilerTask task, Compiler compiler) {
RuntimeTypesNeedBuilder rtiNeedBuilder = _createRuntimeTypesNeedBuilder();
BackendImpacts impacts =
new BackendImpacts(commonElements, compiler.options);
_nativeResolutionEnqueuer = new NativeResolutionEnqueuer(
BackendImpacts impacts = BackendImpacts(commonElements, compiler.options);
_nativeResolutionEnqueuer = NativeResolutionEnqueuer(
compiler.options,
elementEnvironment,
commonElements,
_elementMap.types,
new BaseNativeClassFinder(elementEnvironment, nativeBasicData));
_nativeDataBuilder = new NativeDataBuilderImpl(nativeBasicData);
_customElementsResolutionAnalysis = new CustomElementsResolutionAnalysis(
BaseNativeClassFinder(elementEnvironment, nativeBasicData));
_nativeDataBuilder = NativeDataBuilderImpl(nativeBasicData);
_customElementsResolutionAnalysis = CustomElementsResolutionAnalysis(
elementEnvironment,
commonElements,
nativeBasicData,
_backendUsageBuilder);
_fieldAnalysis = new KFieldAnalysis(this);
ClassQueries classQueries = new KernelClassQueries(elementMap);
_fieldAnalysis = KFieldAnalysis(this);
ClassQueries classQueries = KernelClassQueries(elementMap);
ClassHierarchyBuilder classHierarchyBuilder =
new ClassHierarchyBuilder(commonElements, classQueries);
AnnotationsDataBuilder annotationsDataBuilder =
new AnnotationsDataBuilder();
ClassHierarchyBuilder(commonElements, classQueries);
AnnotationsDataBuilder annotationsDataBuilder = AnnotationsDataBuilder();
// TODO(johnniwinther): This is a hack. The annotation data is built while
// using it. With CFE constants the annotations data can be built fully
// before creating the resolution enqueuer.
AnnotationsData annotationsData = new AnnotationsDataImpl(
AnnotationsData annotationsData = AnnotationsDataImpl(
compiler.options, annotationsDataBuilder.pragmaAnnotations);
ImpactTransformer impactTransformer = new JavaScriptImpactTransformer(
ImpactTransformer impactTransformer = JavaScriptImpactTransformer(
elementEnvironment,
commonElements,
impacts,
@ -175,13 +171,12 @@ class KernelFrontendStrategy extends FrontendStrategy {
rtiNeedBuilder,
classHierarchyBuilder,
annotationsData);
InterceptorDataBuilder interceptorDataBuilder =
new InterceptorDataBuilderImpl(
nativeBasicData, elementEnvironment, commonElements);
return new ResolutionEnqueuer(
InterceptorDataBuilder interceptorDataBuilder = InterceptorDataBuilderImpl(
nativeBasicData, elementEnvironment, commonElements);
return ResolutionEnqueuer(
task,
compiler.reporter,
new ResolutionEnqueuerListener(
ResolutionEnqueuerListener(
compiler.options,
elementEnvironment,
commonElements,
@ -194,7 +189,7 @@ class KernelFrontendStrategy extends FrontendStrategy {
_nativeResolutionEnqueuer,
_fieldAnalysis,
compiler.deferredLoadTask),
new ResolutionWorldBuilderImpl(
ResolutionWorldBuilderImpl(
_options,
elementMap,
elementEnvironment,
@ -212,7 +207,7 @@ class KernelFrontendStrategy extends FrontendStrategy {
const StrongModeWorldStrategy(),
classHierarchyBuilder,
classQueries),
new KernelWorkItemBuilder(
KernelWorkItemBuilder(
_compilerTask,
elementMap,
nativeBasicData,
@ -251,8 +246,8 @@ class KernelFrontendStrategy extends FrontendStrategy {
void registerLoadedLibraries(KernelResult kernelResult) {
_elementMap.addComponent(kernelResult.component);
_irAnnotationData = processAnnotations(
new ModularCore(kernelResult.component, _elementMap.constantEvaluator));
_annotationProcessor = new KernelAnnotationProcessor(
ModularCore(kernelResult.component, _elementMap.constantEvaluator));
_annotationProcessor = KernelAnnotationProcessor(
elementMap, nativeBasicDataBuilder, _irAnnotationData);
for (Uri uri in kernelResult.libraries) {
LibraryEntity library = elementEnvironment.lookupLibrary(uri);
@ -280,7 +275,7 @@ class KernelFrontendStrategy extends FrontendStrategy {
@override
DeferredLoadTask createDeferredLoadTask(Compiler compiler) =>
new KernelDeferredLoadTask(compiler, _elementMap);
DeferredLoadTask(compiler, _elementMap);
@override
FunctionEntity computeMain(WorldImpactBuilder impactBuilder) {
@ -290,7 +285,7 @@ class KernelFrontendStrategy extends FrontendStrategy {
RuntimeTypesNeedBuilder _createRuntimeTypesNeedBuilder() {
return _runtimeTypesNeedBuilder ??= _options.disableRtiOptimization
? const TrivialRuntimeTypesNeedBuilder()
: new RuntimeTypesNeedBuilderImpl(elementEnvironment);
: RuntimeTypesNeedBuilderImpl(elementEnvironment);
}
RuntimeTypesNeedBuilder get runtimeTypesNeedBuilderForTesting =>
@ -326,12 +321,12 @@ class KernelWorkItemBuilder implements WorkItemBuilder {
this._fieldAnalysis,
this._modularStrategy,
this._irAnnotationData)
: _nativeMemberResolver = new KernelNativeMemberResolver(
: _nativeMemberResolver = KernelNativeMemberResolver(
_elementMap, nativeBasicData, nativeDataBuilder);
@override
WorkItem createWorkItem(MemberEntity entity) {
return new KernelWorkItem(
return KernelWorkItem(
_compilerTask,
_elementMap,
_impactTransformer,
@ -404,7 +399,7 @@ class KernelWorkItem implements WorkItem {
ResolutionImpact impact = _elementMap.computeWorldImpact(
element,
scopeModel.variableScopeModel,
new Set<PragmaAnnotation>.from(
Set<PragmaAnnotation>.from(
annotations.iterable(PragmaAnnotation.values)),
impactBuilderData: impactBuilderData);
WorldImpact worldImpact =
@ -440,8 +435,8 @@ class KernelModularStrategy extends ModularStrategy {
@override
ModularMemberData getModularMemberData(
ir.Member node, EnumSet<PragmaAnnotation> annotations) {
ScopeModel scopeModel = _compilerTask.measureSubtask('closures',
() => new ScopeModel.from(node, _elementMap.constantEvaluator));
ScopeModel scopeModel = _compilerTask.measureSubtask(
'closures', () => ScopeModel.from(node, _elementMap.constantEvaluator));
ImpactBuilderData impactBuilderData;
if (useImpactDataForTesting) {
// TODO(johnniwinther): Always create and use the [ImpactBuilderData].
@ -449,8 +444,8 @@ class KernelModularStrategy extends ModularStrategy {
// depend on metadata, so these parts of the impact data need to be
// computed during conversion to [ResolutionImpact].
impactBuilderData = _compilerTask.measureSubtask('worldImpact', () {
ImpactBuilder builder = new ImpactBuilder(
new ir.StaticTypeContext(node, _elementMap.typeEnvironment),
ImpactBuilder builder = ImpactBuilder(
ir.StaticTypeContext(node, _elementMap.typeEnvironment),
_elementMap.classHierarchy,
scopeModel.variableScopeModel,
useAsserts: _elementMap.options.enableUserAssertions,
@ -459,6 +454,6 @@ class KernelModularStrategy extends ModularStrategy {
return builder.computeImpact(node);
});
}
return new ModularMemberData(scopeModel, impactBuilderData);
return ModularMemberData(scopeModel, impactBuilderData);
}
}

View File

@ -142,32 +142,6 @@ class CompilerOptions implements DiagnosticOptions {
/// libraries are subdivided.
Uri deferredMapUri;
/// Whether to apply the new deferred split fixes. The fixes improve on
/// performance and fix a soundness issue with inferred types. The latter will
/// move more code to the main output unit, because of that we are not
/// enabling the feature by default right away.
///
/// When [reportInvalidInferredDeferredTypes] shows no errors, we expect this
/// flag to produce the same or better results than the current unsound
/// implementation.
bool newDeferredSplit = true; // default value.
bool _newDeferredSplit = false;
bool _noNewDeferredSplit = false;
/// Show errors when a deferred type is inferred as a return type of a closure
/// or in a type parameter. Those cases cause the compiler today to behave
/// unsoundly by putting the code in a deferred output unit. In the future
/// when [newDeferredSplit] is on by default, those cases will be treated
/// soundly and will cause more code to be moved to the main output unit.
///
/// This flag is presented to help developers find and fix the affected code.
bool reportInvalidInferredDeferredTypes = false;
/// Whether to defer load class types.
bool deferClassTypes = true; // default value.
bool _deferClassTypes = false;
bool _noDeferClassTypes = false;
/// Whether to disable inlining during the backend optimizations.
// TODO(sigmund): negate, so all flags are positive
bool disableInlining = false;
@ -443,12 +417,6 @@ class CompilerOptions implements DiagnosticOptions {
_extractStringOption(options, '--build-id=', _UNDETERMINED_BUILD_ID)
..compileForServer = _hasOption(options, Flags.serverMode)
..deferredMapUri = _extractUriOption(options, '--deferred-map=')
.._newDeferredSplit = _hasOption(options, Flags.newDeferredSplit)
.._noNewDeferredSplit = _hasOption(options, Flags.noNewDeferredSplit)
..reportInvalidInferredDeferredTypes =
_hasOption(options, Flags.reportInvalidInferredDeferredTypes)
.._deferClassTypes = _hasOption(options, Flags.deferClassTypes)
.._noDeferClassTypes = _hasOption(options, Flags.noDeferClassTypes)
..fatalWarnings = _hasOption(options, Flags.fatalWarnings)
..terseDiagnostics = _hasOption(options, Flags.terse)
..suppressWarnings = _hasOption(options, Flags.suppressWarnings)
@ -555,14 +523,6 @@ class CompilerOptions implements DiagnosticOptions {
throw ArgumentError("'${Flags.soundNullSafety}' requires the "
"'non-nullable' experiment to be enabled");
}
if (_deferClassTypes && _noDeferClassTypes) {
throw ArgumentError("'${Flags.deferClassTypes}' incompatible with "
"'${Flags.noDeferClassTypes}'");
}
if (_newDeferredSplit && _noNewDeferredSplit) {
throw ArgumentError("'${Flags.newDeferredSplit}' incompatible with "
"'${Flags.noNewDeferredSplit}'");
}
}
void deriveOptions() {
@ -620,12 +580,6 @@ class CompilerOptions implements DiagnosticOptions {
if (_disableMinification) {
enableMinification = false;
}
if (_deferClassTypes) deferClassTypes = true;
if (_noDeferClassTypes) deferClassTypes = false;
if (_newDeferredSplit) newDeferredSplit = true;
if (_noNewDeferredSplit) newDeferredSplit = false;
}
/// Returns `true` if warnings and hints are shown for all packages.