diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart index 570fa8243ac..f7118bdc96d 100644 --- a/pkg/compiler/lib/src/ir/impact.dart +++ b/pkg/compiler/lib/src/ir/impact.dart @@ -10,15 +10,185 @@ import 'package:kernel/class_hierarchy.dart' as ir; import 'package:kernel/type_environment.dart' as ir; import '../common.dart'; +import 'impact_data.dart'; +import 'runtime_type_analysis.dart'; import 'scope.dart'; import 'static_type.dart'; import 'static_type_base.dart'; import 'util.dart'; -abstract class ImpactBuilder extends StaticTypeVisitor { +/// Interface for collecting world impact data. +/// +/// This is used both for direct world impact computation through the +/// [KernelImpactBuilder] and for serialization through the [ImpactBuilder] +/// and [ImpactLoader]. +abstract class ImpactRegistry { + void registerIntLiteral(int value); + + void registerDoubleLiteral(double value); + + void registerBoolLiteral(bool value); + + void registerStringLiteral(String value); + + void registerSymbolLiteral(String value); + + void registerNullLiteral(); + + void registerListLiteral(ir.DartType elementType, + {bool isConst, bool isEmpty}); + + void registerSetLiteral(ir.DartType elementType, + {bool isConst, bool isEmpty}); + + void registerMapLiteral(ir.DartType keyType, ir.DartType valueType, + {bool isConst, bool isEmpty}); + + void registerStaticTearOff( + ir.Procedure procedure, ir.LibraryDependency import); + + void registerStaticGet(ir.Member member, ir.LibraryDependency import); + + void registerStaticSet(ir.Member member, ir.LibraryDependency import); + + void registerAssert({bool withMessage}); + + void registerGenericInstantiation( + ir.FunctionType expressionType, List typeArguments); + + void registerSyncStar(ir.DartType elementType); + + void registerAsync(ir.DartType elementType); + + void registerAsyncStar(ir.DartType elementType); + + void registerStringConcatenation(); + + void registerLocalFunction(ir.TreeNode node); + + void registerLocalWithoutInitializer(); + + void registerIsCheck(ir.DartType type); + + void registerImplicitCast(ir.DartType type); + + void registerAsCast(ir.DartType type); + + void registerThrow(); + + void registerSyncForIn(ir.DartType iterableType); + + void registerAsyncForIn(ir.DartType iterableType); + + void registerCatch(); + + void registerStackTrace(); + + void registerCatchType(ir.DartType type); + + void registerTypeLiteral(ir.DartType type, ir.LibraryDependency import); + + void registerFieldInitializer(ir.Field node); + + void registerLoadLibrary(); + + void registerRedirectingInitializer( + ir.Constructor constructor, + int positionalArguments, + List namedArguments, + List typeArguments); + + void registerParameterCheck(ir.DartType type); + + void registerLazyField(); + + void registerNew( + ir.Member constructor, + ir.InterfaceType type, + int positionalArguments, + List namedArguments, + List typeArguments, + ir.LibraryDependency import, + {bool isConst}); + + void registerStaticInvocation( + ir.Procedure target, + int positionalArguments, + List namedArguments, + List typeArguments, + ir.LibraryDependency import); + + void registerLocalFunctionInvocation( + ir.FunctionDeclaration localFunction, + int positionalArguments, + List namedArguments, + List typeArguments); + + void registerDynamicInvocation( + ir.DartType receiverType, + ClassRelation relation, + ir.Name name, + int positionalArguments, + List namedArguments, + List typeArguments); + + void registerInstanceInvocation( + ir.DartType receiverType, + ClassRelation relation, + ir.Member target, + int positionalArguments, + List namedArguments, + List typeArguments); + + void registerFunctionInvocation( + ir.DartType receiverType, + int positionalArguments, + List namedArguments, + List typeArguments); + + void registerDynamicGet( + ir.DartType receiverType, ClassRelation relation, ir.Name name); + + void registerInstanceGet( + ir.DartType receiverType, ClassRelation relation, ir.Member target); + + void registerDynamicSet( + ir.DartType receiverType, ClassRelation relation, ir.Name name); + + void registerInstanceSet( + ir.DartType receiverType, ClassRelation relation, ir.Member target); + + void registerSuperInvocation(ir.Name name, int positionalArguments, + List namedArguments, List typeArguments); + + void registerSuperGet(ir.Name name); + + void registerSuperSet(ir.Name name); + + void registerSuperInitializer( + ir.Constructor source, + ir.Constructor target, + int positionalArguments, + List namedArguments, + List typeArguments); + + void registerRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind, + ir.DartType receiverType, ir.DartType argumentType); + + // TODO(johnniwinther): Remove these when CFE provides constants. + void registerConstructorNode(ir.Constructor node); + void registerFieldNode(ir.Field node); + void registerProcedureNode(ir.Procedure node); + void registerStaticInvocationNode(ir.StaticInvocation node); + void registerSwitchStatementNode(ir.SwitchStatement node); + void registerConstConstructorInvocationNode(ir.ConstructorInvocation node); +} + +abstract class ImpactBuilderBase extends StaticTypeVisitor + implements ImpactRegistry { final VariableScopeModel variableScopeModel; - ImpactBuilder(ir.TypeEnvironment typeEnvironment, + ImpactBuilderBase(ir.TypeEnvironment typeEnvironment, ir.ClassHierarchy classHierarchy, this.variableScopeModel) : super(typeEnvironment, classHierarchy); @@ -32,71 +202,54 @@ abstract class ImpactBuilder extends StaticTypeVisitor { } } - void registerIntLiteral(int value); - @override void handleIntLiteral(ir.IntLiteral node) { registerIntLiteral(node.value); } - void registerDoubleLiteral(double value); - @override void handleDoubleLiteral(ir.DoubleLiteral node) { registerDoubleLiteral(node.value); } - void registerBoolLiteral(bool value); - @override void handleBoolLiteral(ir.BoolLiteral node) { registerBoolLiteral(node.value); } - void registerStringLiteral(String value); - @override void handleStringLiteral(ir.StringLiteral node) { registerStringLiteral(node.value); } - void registerSymbolLiteral(String value); - @override void handleSymbolLiteral(ir.SymbolLiteral node) { registerSymbolLiteral(node.value); } - void registerNullLiteral(); - @override void handleNullLiteral(ir.NullLiteral node) { registerNullLiteral(); } - void registerListLiteral(ir.DartType elementType, - {bool isConstant, bool isEmpty}); - @override void handleListLiteral(ir.ListLiteral node) { registerListLiteral(node.typeArgument, - isConstant: node.isConst, isEmpty: node.expressions.isEmpty); + isConst: node.isConst, isEmpty: node.expressions.isEmpty); } - void registerMapLiteral(ir.DartType keyType, ir.DartType valueType, - {bool isConstant, bool isEmpty}); + @override + void handleSetLiteral(ir.SetLiteral node) { + registerSetLiteral(node.typeArgument, + isConst: node.isConst, isEmpty: node.expressions.isEmpty); + } @override void handleMapLiteral(ir.MapLiteral node) { registerMapLiteral(node.keyType, node.valueType, - isConstant: node.isConst, isEmpty: node.entries.isEmpty); + isConst: node.isConst, isEmpty: node.entries.isEmpty); } - void registerStaticTearOff( - ir.Procedure procedure, ir.LibraryDependency import); - - void registerStaticGet(ir.Member member, ir.LibraryDependency import); - @override void handleStaticGet(ir.StaticGet node, ir.DartType resultType) { ir.Member target = node.target; @@ -107,35 +260,22 @@ abstract class ImpactBuilder extends StaticTypeVisitor { } } - void registerStaticSet(ir.Member member, ir.LibraryDependency import); - @override void handleStaticSet(ir.StaticSet node, ir.DartType valueType) { registerStaticSet(node.target, getDeferredImport(node)); } - void registerAssert({bool withMessage}); - @override void handleAssertStatement(ir.AssertStatement node) { registerAssert(withMessage: node.message != null); } - void registerGenericInstantiation( - ir.FunctionType expressionType, List typeArguments); - @override void handleInstantiation(ir.Instantiation node, ir.FunctionType expressionType, ir.DartType resultType) { registerGenericInstantiation(expressionType, node.typeArguments); } - void registerSyncStar(ir.DartType elementType); - - void registerAsync(ir.DartType elementType); - - void registerAsyncStar(ir.DartType elementType); - void handleAsyncMarker(ir.FunctionNode function) { ir.AsyncMarker asyncMarker = function.asyncMarker; ir.DartType returnType = function.returnType; @@ -182,15 +322,11 @@ abstract class ImpactBuilder extends StaticTypeVisitor { } } - void registerStringConcatenation(); - @override void handleStringConcatenation(ir.StringConcatenation node) { registerStringConcatenation(); } - void registerLocalFunction(ir.TreeNode node); - @override Null handleFunctionDeclaration(ir.FunctionDeclaration node) { registerLocalFunction(node); @@ -203,8 +339,6 @@ abstract class ImpactBuilder extends StaticTypeVisitor { handleAsyncMarker(node.function); } - void registerLocalWithoutInitializer(); - @override void handleVariableDeclaration(ir.VariableDeclaration node) { if (node.initializer == null) { @@ -212,17 +346,11 @@ abstract class ImpactBuilder extends StaticTypeVisitor { } } - void registerIsCheck(ir.DartType type); - @override void handleIsExpression(ir.IsExpression node) { registerIsCheck(node.type); } - void registerImplicitCast(ir.DartType type); - - void registerAsCast(ir.DartType type); - @override void handleAsExpression(ir.AsExpression node, ir.DartType operandType) { if (typeEnvironment.isSubtypeOf(operandType, node.type)) { @@ -236,17 +364,11 @@ abstract class ImpactBuilder extends StaticTypeVisitor { } } - void registerThrow(); - @override void handleThrow(ir.Throw node) { registerThrow(); } - void registerSyncForIn(ir.DartType iterableType); - - void registerAsyncForIn(ir.DartType iterableType); - @override void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType) { if (node.isAsync) { @@ -256,12 +378,6 @@ abstract class ImpactBuilder extends StaticTypeVisitor { } } - void registerCatch(); - - void registerStackTrace(); - - void registerCatchType(ir.DartType type); - @override void handleCatch(ir.Catch node) { registerCatch(); @@ -273,37 +389,30 @@ abstract class ImpactBuilder extends StaticTypeVisitor { } } - void registerTypeLiteral(ir.DartType type, ir.LibraryDependency import); - @override void handleTypeLiteral(ir.TypeLiteral node) { registerTypeLiteral(node.type, getDeferredImport(node)); } - void registerFieldInitializer(ir.Field node); - @override void handleFieldInitializer(ir.FieldInitializer node) { registerFieldInitializer(node.field); } - void registerLoadLibrary(); - @override void handleLoadLibrary(ir.LoadLibrary node) { registerLoadLibrary(); } - void registerRedirectingInitializer( - ir.Constructor constructor, ir.Arguments arguments); - void handleRedirectingInitializer( ir.RedirectingInitializer node, ArgumentTypes argumentTypes) { - registerRedirectingInitializer(node.target, node.arguments); + registerRedirectingInitializer( + node.target, + node.arguments.positional.length, + _getNamedArguments(node.arguments), + node.arguments.types); } - void registerParameterCheck(ir.DartType type); - @override void handleParameter(ir.VariableDeclaration parameter) { registerParameterCheck(parameter.type); @@ -316,7 +425,10 @@ abstract class ImpactBuilder extends StaticTypeVisitor { } } - void registerLazyField(); + @override + void handleConstructor(ir.Constructor node) { + registerConstructorNode(node); + } @override void handleField(ir.Field field) { @@ -330,31 +442,37 @@ abstract class ImpactBuilder extends StaticTypeVisitor { } else { registerNullLiteral(); } + registerFieldNode(field); } @override void handleProcedure(ir.Procedure procedure) { handleAsyncMarker(procedure.function); + registerProcedureNode(procedure); } - void registerNew(ir.Member constructor, ir.InterfaceType type, - ir.Arguments arguments, ir.LibraryDependency import, - {bool isConst}); - @override void handleConstructorInvocation(ir.ConstructorInvocation node, ArgumentTypes argumentTypes, ir.DartType resultType) { - registerNew(node.target, node.constructedType, node.arguments, + registerNew( + node.target, + node.constructedType, + node.arguments.positional.length, + _getNamedArguments(node.arguments), + node.arguments.types, getDeferredImport(node), isConst: node.isConst); + if (node.isConst) { + registerConstConstructorInvocationNode(node); + } } - void registerStaticInvocation( - ir.Procedure target, ir.Arguments arguments, ir.LibraryDependency import); - @override void handleStaticInvocation(ir.StaticInvocation node, ArgumentTypes argumentTypes, ir.DartType returnType) { + int positionArguments = node.arguments.positional.length; + List namedArguments = _getNamedArguments(node.arguments); + List typeArguments = node.arguments.types; if (node.target.kind == ir.ProcedureKind.Factory) { // TODO(johnniwinther): We should not mark the type as instantiated but // rather follow the type arguments directly. @@ -380,65 +498,60 @@ abstract class ImpactBuilder extends StaticTypeVisitor { // instantiated as int and String. registerNew( node.target, - new ir.InterfaceType( - node.target.enclosingClass, node.arguments.types), - node.arguments, + new ir.InterfaceType(node.target.enclosingClass, typeArguments), + positionArguments, + namedArguments, + node.arguments.types, getDeferredImport(node), isConst: node.isConst); } else { - registerStaticInvocation( - node.target, node.arguments, getDeferredImport(node)); + registerStaticInvocation(node.target, positionArguments, namedArguments, + typeArguments, getDeferredImport(node)); } + registerStaticInvocationNode(node); } - void registerLocalFunctionInvocation( - ir.FunctionDeclaration localFunction, ir.Arguments arguments); - - void registerDynamicInvocation(ir.DartType receiverType, - ClassRelation relation, ir.Name name, ir.Arguments arguments); - - void registerInstanceInvocation(ir.DartType receiverType, - ClassRelation relation, ir.Member target, ir.Arguments arguments); - - void registerFunctionInvocation( - ir.DartType receiverType, ir.Arguments arguments); - @override void handleMethodInvocation( ir.MethodInvocation node, ir.DartType receiverType, ArgumentTypes argumentTypes, ir.DartType returnType) { + int positionArguments = node.arguments.positional.length; + List namedArguments = _getNamedArguments(node.arguments); + List typeArguments = node.arguments.types; ir.Expression receiver = node.receiver; if (receiver is ir.VariableGet && receiver.variable.isFinal && receiver.variable.parent is ir.FunctionDeclaration) { - registerLocalFunctionInvocation(receiver.variable.parent, node.arguments); + registerLocalFunctionInvocation(receiver.variable.parent, + positionArguments, namedArguments, typeArguments); } else { ClassRelation relation = _computeClassRelationFromType(receiverType); ir.Member interfaceTarget = node.interfaceTarget; if (interfaceTarget == null) { - registerDynamicInvocation( - receiverType, relation, node.name, node.arguments); + registerDynamicInvocation(receiverType, relation, node.name, + positionArguments, namedArguments, typeArguments); // TODO(johnniwinther): Avoid treating a known function call as a // dynamic call when CFE provides a way to distinguish the two. if (operatorFromString(node.name.name) == null && receiverType is ir.DynamicType) { // We might implicitly call a getter that returns a function. - registerFunctionInvocation(const ir.DynamicType(), node.arguments); + registerFunctionInvocation(const ir.DynamicType(), positionArguments, + namedArguments, typeArguments); } } else { if (interfaceTarget is ir.Field || interfaceTarget is ir.Procedure && interfaceTarget.kind == ir.ProcedureKind.Getter) { - registerInstanceInvocation( - receiverType, relation, interfaceTarget, node.arguments); - registerFunctionInvocation( - interfaceTarget.getterType, node.arguments); + registerInstanceInvocation(receiverType, relation, interfaceTarget, + positionArguments, namedArguments, typeArguments); + registerFunctionInvocation(interfaceTarget.getterType, + positionArguments, namedArguments, typeArguments); } else { - registerInstanceInvocation( - receiverType, relation, interfaceTarget, node.arguments); + registerInstanceInvocation(receiverType, relation, interfaceTarget, + positionArguments, namedArguments, typeArguments); } } } @@ -451,15 +564,14 @@ abstract class ImpactBuilder extends StaticTypeVisitor { ArgumentTypes argumentTypes, ir.DartType returnType) { registerInstanceInvocation( - receiverType, ClassRelation.exact, node.target, node.arguments); + receiverType, + ClassRelation.exact, + node.target, + node.arguments.positional.length, + _getNamedArguments(node.arguments), + node.arguments.types); } - void registerDynamicGet( - ir.DartType receiverType, ClassRelation relation, ir.Name name); - - void registerInstanceGet( - ir.DartType receiverType, ClassRelation relation, ir.Member target); - @override void handlePropertyGet( ir.PropertyGet node, ir.DartType receiverType, ir.DartType resultType) { @@ -477,12 +589,6 @@ abstract class ImpactBuilder extends StaticTypeVisitor { registerInstanceGet(receiverType, ClassRelation.exact, node.target); } - void registerDynamicSet( - ir.DartType receiverType, ClassRelation relation, ir.Name name); - - void registerInstanceSet( - ir.DartType receiverType, ClassRelation relation, ir.Member target); - @override void handlePropertySet( ir.PropertySet node, ir.DartType receiverType, ir.DartType valueType) { @@ -500,35 +606,59 @@ abstract class ImpactBuilder extends StaticTypeVisitor { registerInstanceSet(receiverType, ClassRelation.exact, node.target); } - void registerSuperInvocation(ir.Name name, ir.Arguments arguments); - @override void handleSuperMethodInvocation(ir.SuperMethodInvocation node, ArgumentTypes argumentTypes, ir.DartType returnType) { - registerSuperInvocation(node.name, node.arguments); + registerSuperInvocation(node.name, node.arguments.positional.length, + _getNamedArguments(node.arguments), node.arguments.types); } - void registerSuperGet(ir.Name name); - @override void handleSuperPropertyGet( ir.SuperPropertyGet node, ir.DartType resultType) { registerSuperGet(node.name); } - void registerSuperSet(ir.Name name); - @override void handleSuperPropertySet(ir.SuperPropertySet node, ir.DartType valueType) { registerSuperSet(node.name); } - void registerSuperInitializer( - ir.Constructor source, ir.Constructor target, ir.Arguments arguments); - @override void handleSuperInitializer( ir.SuperInitializer node, ArgumentTypes argumentTypes) { - registerSuperInitializer(node.parent, node.target, node.arguments); + registerSuperInitializer( + node.parent, + node.target, + node.arguments.positional.length, + _getNamedArguments(node.arguments), + node.arguments.types); + } + + @override + Null visitSwitchStatement(ir.SwitchStatement node) { + registerSwitchStatementNode(node); + return super.visitSwitchStatement(node); + } + + void handleRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind, + ir.DartType receiverType, ir.DartType argumentType) { + registerRuntimeTypeUse(node, kind, receiverType, argumentType); } } + +/// Visitor that builds an [ImpactData] object for the world impact. +class ImpactBuilder extends ImpactBuilderBase with ImpactRegistryMixin { + final bool useAsserts; + + final inferEffectivelyFinalVariableTypes; + + ImpactBuilder(ir.TypeEnvironment typeEnvironment, + ir.ClassHierarchy classHierarchy, VariableScopeModel variableScopeModel, + {this.useAsserts: false, this.inferEffectivelyFinalVariableTypes: true}) + : super(typeEnvironment, classHierarchy, variableScopeModel); +} + +/// Return the named arguments names as a list of strings. +List _getNamedArguments(ir.Arguments arguments) => + arguments.named.map((n) => n.name).toList(); diff --git a/pkg/compiler/lib/src/ir/impact_data.dart b/pkg/compiler/lib/src/ir/impact_data.dart new file mode 100644 index 00000000000..20bd480eb68 --- /dev/null +++ b/pkg/compiler/lib/src/ir/impact_data.dart @@ -0,0 +1,1545 @@ +// Copyright (c) 2019, 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. + +import 'package:kernel/ast.dart' as ir; +import 'package:kernel/class_hierarchy.dart' as ir; +import 'package:kernel/type_environment.dart' as ir; + +import '../serialization/serialization.dart'; +import '../util/enumset.dart'; +import 'impact.dart'; +import 'runtime_type_analysis.dart'; +import 'static_type.dart'; + +/// [ImpactRegistry] that stores registered impact in an [ImpactData] object. +abstract class ImpactRegistryMixin implements ImpactRegistry { + final ImpactDataImpl _data = new ImpactDataImpl(); + + ImpactData get impactData => _data; + + void _registerFeature(_Feature feature) { + _data._features ??= new EnumSet<_Feature>(); + _data._features.add(feature); + } + + void _registerTypeUse(ir.DartType type, _TypeUseKind kind) { + _data._typeUses ??= []; + _data._typeUses.add(new _TypeUse(type, kind)); + } + + @override + void registerSuperInitializer( + ir.Constructor source, + ir.Constructor target, + int positionalArguments, + List namedArguments, + List typeArguments) { + _data._superInitializers ??= []; + _data._superInitializers.add(new _SuperInitializer( + source, + target, + new _CallStructure( + positionalArguments, namedArguments, typeArguments))); + } + + @override + void registerSuperSet(ir.Name name) { + _data._superSets ??= []; + _data._superSets.add(name); + } + + @override + void registerSuperGet(ir.Name name) { + _data._superGets ??= []; + _data._superGets.add(name); + } + + @override + void registerSuperInvocation(ir.Name name, int positionalArguments, + List namedArguments, List typeArguments) { + _data._superInvocations ??= []; + _data._superInvocations.add(new _SuperInvocation( + name, + new _CallStructure( + positionalArguments, namedArguments, typeArguments))); + } + + @override + void registerInstanceSet( + ir.DartType receiverType, ClassRelation relation, ir.Member target) { + _data._instanceSets ??= []; + _data._instanceSets + .add(new _InstanceAccess(receiverType, relation, target)); + } + + @override + void registerDynamicSet( + ir.DartType receiverType, ClassRelation relation, ir.Name name) { + _data._dynamicSets ??= []; + _data._dynamicSets.add(new _DynamicAccess(receiverType, relation, name)); + } + + @override + void registerInstanceGet( + ir.DartType receiverType, ClassRelation relation, ir.Member target) { + _data._instanceGets ??= []; + _data._instanceGets + .add(new _InstanceAccess(receiverType, relation, target)); + } + + @override + void registerDynamicGet( + ir.DartType receiverType, ClassRelation relation, ir.Name name) { + _data._dynamicGets ??= []; + _data._dynamicGets.add(new _DynamicAccess(receiverType, relation, name)); + } + + @override + void registerFunctionInvocation( + ir.DartType receiverType, + int positionalArguments, + List namedArguments, + List typeArguments) { + _data._functionInvocations ??= []; + _data._functionInvocations.add(new _FunctionInvocation( + receiverType, + new _CallStructure( + positionalArguments, namedArguments, typeArguments))); + } + + @override + void registerInstanceInvocation( + ir.DartType receiverType, + ClassRelation relation, + ir.Member target, + int positionalArguments, + List namedArguments, + List typeArguments) { + _data._instanceInvocations ??= []; + _data._instanceInvocations.add(new _InstanceInvocation( + receiverType, + relation, + target, + new _CallStructure( + positionalArguments, namedArguments, typeArguments))); + } + + @override + void registerDynamicInvocation( + ir.DartType receiverType, + ClassRelation relation, + ir.Name name, + int positionalArguments, + List namedArguments, + List typeArguments) { + _data._dynamicInvocations ??= []; + _data._dynamicInvocations.add(new _DynamicInvocation( + receiverType, + relation, + name, + new _CallStructure( + positionalArguments, namedArguments, typeArguments))); + } + + @override + void registerLocalFunctionInvocation( + ir.FunctionDeclaration localFunction, + int positionalArguments, + List namedArguments, + List typeArguments) { + _data._localFunctionInvocations ??= []; + _data._localFunctionInvocations.add(new _LocalFunctionInvocation( + localFunction, + new _CallStructure( + positionalArguments, namedArguments, typeArguments))); + } + + @override + void registerStaticInvocation( + ir.Procedure target, + int positionalArguments, + List namedArguments, + List typeArguments, + ir.LibraryDependency import) { + _data._staticInvocations ??= []; + _data._staticInvocations.add(new _StaticInvocation( + target, + new _CallStructure(positionalArguments, namedArguments, typeArguments), + import)); + } + + @override + void registerNew( + ir.Member constructor, + ir.InterfaceType type, + int positionalArguments, + List namedArguments, + List typeArguments, + ir.LibraryDependency import, + {bool isConst}) { + _data._constructorInvocations ??= []; + _data._constructorInvocations.add(new _ConstructorInvocation( + constructor, + type, + new _CallStructure(positionalArguments, namedArguments, typeArguments), + import, + isConst: isConst)); + } + + @override + void registerLazyField() { + _registerFeature(_Feature.lazyField); + } + + @override + void registerParameterCheck(ir.DartType type) { + _registerTypeUse(type, _TypeUseKind.parameterCheck); + } + + @override + void registerRedirectingInitializer( + ir.Constructor constructor, + int positionalArguments, + List namedArguments, + List typeArguments) { + _data._redirectingInitializers ??= []; + _data._redirectingInitializers.add(new _RedirectingInitializer( + constructor, + new _CallStructure( + positionalArguments, namedArguments, typeArguments))); + } + + @override + void registerLoadLibrary() { + _registerFeature(_Feature.loadLibrary); + } + + @override + void registerFieldInitializer(ir.Field node) { + _data._fieldInitializers ??= []; + _data._fieldInitializers.add(node); + } + + @override + void registerTypeLiteral(ir.DartType type, ir.LibraryDependency import) { + _data._typeLiterals ??= []; + _data._typeLiterals.add(new _TypeLiteral(type, import)); + } + + @override + void registerCatchType(ir.DartType type) { + _registerTypeUse(type, _TypeUseKind.catchType); + } + + @override + void registerStackTrace() { + _registerFeature(_Feature.stackTrace); + } + + @override + void registerCatch() { + _registerFeature(_Feature.catchClause); + } + + @override + void registerAsyncForIn(ir.DartType iterableType) { + _registerTypeUse(iterableType, _TypeUseKind.asyncForIn); + } + + @override + void registerSyncForIn(ir.DartType iterableType) { + _registerTypeUse(iterableType, _TypeUseKind.syncForIn); + } + + @override + void registerThrow() { + _registerFeature(_Feature.throwExpression); + } + + @override + void registerAsCast(ir.DartType type) { + _registerTypeUse(type, _TypeUseKind.asCast); + } + + @override + void registerImplicitCast(ir.DartType type) { + _registerTypeUse(type, _TypeUseKind.implicitCast); + } + + @override + void registerIsCheck(ir.DartType type) { + _registerTypeUse(type, _TypeUseKind.isCheck); + } + + @override + void registerLocalWithoutInitializer() { + _registerFeature(_Feature.localWithoutInitializer); + } + + @override + void registerLocalFunction(ir.TreeNode node) { + _data._localFunctions ??= []; + _data._localFunctions.add(node); + } + + @override + void registerStringConcatenation() { + _registerFeature(_Feature.stringConcatenation); + } + + @override + void registerAsyncStar(ir.DartType elementType) { + _registerTypeUse(elementType, _TypeUseKind.asyncStarMarker); + } + + @override + void registerAsync(ir.DartType elementType) { + _registerTypeUse(elementType, _TypeUseKind.asyncMarker); + } + + @override + void registerSyncStar(ir.DartType elementType) { + _registerTypeUse(elementType, _TypeUseKind.syncStarMarker); + } + + @override + void registerGenericInstantiation( + ir.FunctionType expressionType, List typeArguments) { + _data._genericInstantiations ??= []; + _data._genericInstantiations + .add(new _GenericInstantiation(expressionType, typeArguments)); + } + + @override + void registerAssert({bool withMessage}) { + _registerFeature(withMessage + ? _Feature.assertWithMessage + : _Feature.assertWithoutMessage); + } + + @override + void registerStaticSet(ir.Member member, ir.LibraryDependency import) { + _data._staticSets ??= []; + _data._staticSets.add(new _StaticAccess(member, import)); + } + + @override + void registerStaticGet(ir.Member member, ir.LibraryDependency import) { + _data._staticGets ??= []; + _data._staticGets.add(new _StaticAccess(member, import)); + } + + @override + void registerStaticTearOff( + ir.Procedure procedure, ir.LibraryDependency import) { + _data._staticTearOffs ??= []; + _data._staticTearOffs.add(new _StaticAccess(procedure, import)); + } + + @override + void registerMapLiteral(ir.DartType keyType, ir.DartType valueType, + {bool isConst, bool isEmpty}) { + _data._mapLiterals ??= []; + _data._mapLiterals.add(new _MapLiteral(keyType, valueType, + isConst: isConst, isEmpty: isEmpty)); + } + + @override + void registerListLiteral(ir.DartType elementType, + {bool isConst, bool isEmpty}) { + _data._listLiterals ??= []; + _data._listLiterals.add( + new _ContainerLiteral(elementType, isConst: isConst, isEmpty: isEmpty)); + } + + @override + void registerSetLiteral(ir.DartType elementType, + {bool isConst, bool isEmpty}) { + _data._setLiterals ??= []; + _data._setLiterals.add( + new _ContainerLiteral(elementType, isConst: isConst, isEmpty: isEmpty)); + } + + @override + void registerNullLiteral() { + _registerFeature(_Feature.nullLiteral); + } + + @override + void registerSymbolLiteral(String value) { + _data._symbolLiterals ??= []; + _data._symbolLiterals.add(value); + } + + @override + void registerStringLiteral(String value) { + _data._stringLiterals ??= []; + _data._stringLiterals.add(value); + } + + @override + void registerBoolLiteral(bool value) { + _data._boolLiterals ??= []; + _data._boolLiterals.add(value); + } + + @override + void registerDoubleLiteral(double value) { + _data._doubleLiterals ??= []; + _data._doubleLiterals.add(value); + } + + @override + void registerIntLiteral(int value) { + _data._intLiterals ??= []; + _data._intLiterals.add(value); + } + + @override + void registerRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind, + ir.DartType receiverType, ir.DartType argumentType) { + _data._runtimeTypeUses ??= []; + _data._runtimeTypeUses + .add(new _RuntimeTypeUse(node, kind, receiverType, argumentType)); + } + + @override + void registerConstructorNode(ir.Constructor node) { + _data._constructorNodes ??= []; + _data._constructorNodes.add(node); + } + + @override + void registerFieldNode(ir.Field node) { + _data._fieldNodes ??= []; + _data._fieldNodes.add(node); + } + + @override + void registerProcedureNode(ir.Procedure node) { + _data._procedureNodes ??= []; + _data._procedureNodes.add(node); + } + + @override + void registerStaticInvocationNode(ir.StaticInvocation node) { + _data._staticInvocationNodes ??= []; + _data._staticInvocationNodes.add(node); + } + + @override + void registerSwitchStatementNode(ir.SwitchStatement node) { + _data._switchStatementNodes ??= []; + _data._switchStatementNodes.add(node); + } + + @override + void registerConstConstructorInvocationNode(ir.ConstructorInvocation node) { + _data._constConstructorInvocationNodes ??= []; + _data._constConstructorInvocationNodes.add(node); + } +} + +/// Data object that contains the world impact data derived purely from kernel. +abstract class ImpactData { + factory ImpactData.fromDataSource(DataSource source) = + ImpactDataImpl.fromDataSource; + + void toDataSink(DataSink sink); + + /// Registers the impact data with [registry]. + void apply(ImpactRegistry registry); +} + +class ImpactDataImpl implements ImpactData { + static const String tag = 'ImpactData'; + + List<_SuperInitializer> _superInitializers; + List _superSets; + List _superGets; + List<_SuperInvocation> _superInvocations; + List<_InstanceAccess> _instanceSets; + List<_DynamicAccess> _dynamicSets; + List<_InstanceAccess> _instanceGets; + List<_DynamicAccess> _dynamicGets; + List<_FunctionInvocation> _functionInvocations; + List<_InstanceInvocation> _instanceInvocations; + List<_DynamicInvocation> _dynamicInvocations; + List<_LocalFunctionInvocation> _localFunctionInvocations; + List<_StaticInvocation> _staticInvocations; + List<_ConstructorInvocation> _constructorInvocations; + EnumSet<_Feature> _features; + List<_TypeUse> _typeUses; + List<_RedirectingInitializer> _redirectingInitializers; + List _fieldInitializers; + List<_TypeLiteral> _typeLiterals; + List _localFunctions; + List<_GenericInstantiation> _genericInstantiations; + List<_StaticAccess> _staticSets; + List<_StaticAccess> _staticGets; + List<_StaticAccess> _staticTearOffs; + List<_MapLiteral> _mapLiterals; + List<_ContainerLiteral> _listLiterals; + List<_ContainerLiteral> _setLiterals; + List _symbolLiterals; + List _stringLiterals; + List _boolLiterals; + List _doubleLiterals; + List _intLiterals; + List<_RuntimeTypeUse> _runtimeTypeUses; + + // TODO(johnniwinther): Remove these when CFE provides constants. + List _constructorNodes; + List _fieldNodes; + List _procedureNodes; + List _switchStatementNodes; + List _staticInvocationNodes; + List _constConstructorInvocationNodes; + + ImpactDataImpl(); + + ImpactDataImpl.fromDataSource(DataSource source) { + source.begin(tag); + _superInitializers = source.readList( + () => new _SuperInitializer.fromDataSource(source), + emptyAsNull: true); + _superSets = source.readList(() => source.readName(), emptyAsNull: true); + _superGets = source.readList(() => source.readName(), emptyAsNull: true); + _superInvocations = source.readList( + () => new _SuperInvocation.fromDataSource(source), + emptyAsNull: true); + _instanceSets = source.readList( + () => new _InstanceAccess.fromDataSource(source), + emptyAsNull: true); + _dynamicSets = source.readList( + () => new _DynamicAccess.fromDataSource(source), + emptyAsNull: true); + _instanceGets = source.readList( + () => new _InstanceAccess.fromDataSource(source), + emptyAsNull: true); + _dynamicGets = source.readList( + () => new _DynamicAccess.fromDataSource(source), + emptyAsNull: true); + _functionInvocations = source.readList( + () => new _FunctionInvocation.fromDataSource(source), + emptyAsNull: true); + _instanceInvocations = source.readList( + () => new _InstanceInvocation.fromDataSource(source), + emptyAsNull: true); + _dynamicInvocations = source.readList( + () => new _DynamicInvocation.fromDataSource(source), + emptyAsNull: true); + _localFunctionInvocations = source.readList( + () => new _LocalFunctionInvocation.fromDataSource(source), + emptyAsNull: true); + _staticInvocations = source.readList( + () => new _StaticInvocation.fromDataSource(source), + emptyAsNull: true); + _constructorInvocations = source.readList( + () => new _ConstructorInvocation.fromDataSource(source), + emptyAsNull: true); + _features = new EnumSet<_Feature>.fromValue(source.readInt()); + _typeUses = source.readList(() => new _TypeUse.fromDataSource(source), + emptyAsNull: true); + _redirectingInitializers = source.readList( + () => new _RedirectingInitializer.fromDataSource(source), + emptyAsNull: true); + _fieldInitializers = source.readMemberNodes(emptyAsNull: true); + _typeLiterals = source.readList( + () => new _TypeLiteral.fromDataSource(source), + emptyAsNull: true); + _localFunctions = source.readTreeNodes(emptyAsNull: true); + _genericInstantiations = source.readList( + () => new _GenericInstantiation.fromDataSource(source), + emptyAsNull: true); + _staticSets = source.readList( + () => new _StaticAccess.fromDataSource(source), + emptyAsNull: true); + _staticGets = source.readList( + () => new _StaticAccess.fromDataSource(source), + emptyAsNull: true); + _staticTearOffs = source.readList( + () => new _StaticAccess.fromDataSource(source), + emptyAsNull: true); + _mapLiterals = source.readList(() => new _MapLiteral.fromDataSource(source), + emptyAsNull: true); + _listLiterals = source.readList( + () => new _ContainerLiteral.fromDataSource(source), + emptyAsNull: true); + _setLiterals = source.readList( + () => new _ContainerLiteral.fromDataSource(source), + emptyAsNull: true); + _symbolLiterals = source.readStrings(emptyAsNull: true); + _stringLiterals = source.readStrings(emptyAsNull: true); + _boolLiterals = source.readList(() => source.readBool(), emptyAsNull: true); + _doubleLiterals = + source.readList(() => source.readDoubleValue(), emptyAsNull: true); + _intLiterals = + source.readList(() => source.readIntegerValue(), emptyAsNull: true); + _runtimeTypeUses = source.readList( + () => new _RuntimeTypeUse.fromDataSource(source), + emptyAsNull: true); + + // TODO(johnniwinther): Remove these when CFE provides constants. + _constructorNodes = + source.readMemberNodes(emptyAsNull: true); + _fieldNodes = source.readMemberNodes(emptyAsNull: true); + _procedureNodes = source.readMemberNodes(emptyAsNull: true); + _switchStatementNodes = + source.readTreeNodes(emptyAsNull: true); + _staticInvocationNodes = + source.readTreeNodes(emptyAsNull: true); + _constConstructorInvocationNodes = + source.readTreeNodes(emptyAsNull: true); + source.end(tag); + } + + @override + void toDataSink(DataSink sink) { + sink.begin(tag); + + sink.writeList( + _superInitializers, (_SuperInitializer o) => o.toDataSink(sink), + allowNull: true); + sink.writeList(_superSets, sink.writeName, allowNull: true); + sink.writeList(_superGets, sink.writeName, allowNull: true); + sink.writeList( + _superInvocations, (_SuperInvocation o) => o.toDataSink(sink), + allowNull: true); + sink.writeList(_instanceSets, (_InstanceAccess o) => o.toDataSink(sink), + allowNull: true); + sink.writeList(_dynamicSets, (_DynamicAccess o) => o.toDataSink(sink), + allowNull: true); + sink.writeList(_instanceGets, (_InstanceAccess o) => o.toDataSink(sink), + allowNull: true); + sink.writeList(_dynamicGets, (_DynamicAccess o) => o.toDataSink(sink), + allowNull: true); + sink.writeList( + _functionInvocations, (_FunctionInvocation o) => o.toDataSink(sink), + allowNull: true); + sink.writeList( + _instanceInvocations, (_InstanceInvocation o) => o.toDataSink(sink), + allowNull: true); + sink.writeList( + _dynamicInvocations, (_DynamicInvocation o) => o.toDataSink(sink), + allowNull: true); + sink.writeList(_localFunctionInvocations, + (_LocalFunctionInvocation o) => o.toDataSink(sink), + allowNull: true); + sink.writeList( + _staticInvocations, (_StaticInvocation o) => o.toDataSink(sink), + allowNull: true); + sink.writeList(_constructorInvocations, + (_ConstructorInvocation o) => o.toDataSink(sink), + allowNull: true); + sink.writeInt(_features?.value ?? 0); + sink.writeList(_typeUses, (_TypeUse o) => o.toDataSink(sink), + allowNull: true); + sink.writeList(_redirectingInitializers, + (_RedirectingInitializer o) => o.toDataSink(sink), + allowNull: true); + sink.writeMemberNodes(_fieldInitializers, allowNull: true); + sink.writeList(_typeLiterals, (_TypeLiteral o) => o.toDataSink(sink), + allowNull: true); + sink.writeTreeNodes(_localFunctions, allowNull: true); + sink.writeList( + _genericInstantiations, (_GenericInstantiation o) => o.toDataSink(sink), + allowNull: true); + sink.writeList(_staticSets, (_StaticAccess o) => o.toDataSink(sink), + allowNull: true); + sink.writeList(_staticGets, (_StaticAccess o) => o.toDataSink(sink), + allowNull: true); + sink.writeList(_staticTearOffs, (_StaticAccess o) => o.toDataSink(sink), + allowNull: true); + sink.writeList(_mapLiterals, (_MapLiteral o) => o.toDataSink(sink), + allowNull: true); + sink.writeList(_listLiterals, (_ContainerLiteral o) => o.toDataSink(sink), + allowNull: true); + sink.writeList(_setLiterals, (_ContainerLiteral o) => o.toDataSink(sink), + allowNull: true); + sink.writeStrings(_symbolLiterals, allowNull: true); + sink.writeStrings(_stringLiterals, allowNull: true); + sink.writeList(_boolLiterals, sink.writeBool, allowNull: true); + sink.writeList(_doubleLiterals, sink.writeDoubleValue, allowNull: true); + sink.writeList(_intLiterals, sink.writeIntegerValue, allowNull: true); + sink.writeList(_runtimeTypeUses, (_RuntimeTypeUse o) => o.toDataSink(sink), + allowNull: true); + + // TODO(johnniwinther): Remove these when CFE provides constants. + sink.writeMemberNodes(_constructorNodes, allowNull: true); + sink.writeMemberNodes(_fieldNodes, allowNull: true); + sink.writeMemberNodes(_procedureNodes, allowNull: true); + sink.writeTreeNodes(_switchStatementNodes, allowNull: true); + sink.writeTreeNodes(_staticInvocationNodes, allowNull: true); + sink.writeTreeNodes(_constConstructorInvocationNodes, allowNull: true); + + sink.end(tag); + } + + @override + void apply(ImpactRegistry registry) { + if (_superInitializers != null) { + for (_SuperInitializer data in _superInitializers) { + registry.registerSuperInitializer( + data.source, + data.target, + data.callStructure.positionalArguments, + data.callStructure.namedArguments, + data.callStructure.typeArguments); + } + } + if (_superSets != null) { + for (ir.Name data in _superSets) { + registry.registerSuperSet(data); + } + } + if (_superGets != null) { + for (ir.Name data in _superGets) { + registry.registerSuperGet(data); + } + } + if (_superInvocations != null) { + for (_SuperInvocation data in _superInvocations) { + registry.registerSuperInvocation( + data.name, + data.callStructure.positionalArguments, + data.callStructure.namedArguments, + data.callStructure.typeArguments); + } + } + if (_instanceSets != null) { + for (_InstanceAccess data in _instanceSets) { + registry.registerInstanceSet( + data.receiverType, data.classRelation, data.target); + } + } + if (_dynamicSets != null) { + for (_DynamicAccess data in _dynamicSets) { + registry.registerDynamicSet( + data.receiverType, data.classRelation, data.name); + } + } + if (_instanceGets != null) { + for (_InstanceAccess data in _instanceGets) { + registry.registerInstanceGet( + data.receiverType, data.classRelation, data.target); + } + } + if (_dynamicGets != null) { + for (_DynamicAccess data in _dynamicGets) { + registry.registerDynamicGet( + data.receiverType, data.classRelation, data.name); + } + } + if (_functionInvocations != null) { + for (_FunctionInvocation data in _functionInvocations) { + registry.registerFunctionInvocation( + data.receiverType, + data.callStructure.positionalArguments, + data.callStructure.namedArguments, + data.callStructure.typeArguments); + } + } + if (_instanceInvocations != null) { + for (_InstanceInvocation data in _instanceInvocations) { + registry.registerInstanceInvocation( + data.receiverType, + data.classRelation, + data.target, + data.callStructure.positionalArguments, + data.callStructure.namedArguments, + data.callStructure.typeArguments); + } + } + if (_dynamicInvocations != null) { + for (_DynamicInvocation data in _dynamicInvocations) { + registry.registerDynamicInvocation( + data.receiverType, + data.classRelation, + data.name, + data.callStructure.positionalArguments, + data.callStructure.namedArguments, + data.callStructure.typeArguments); + } + } + if (_localFunctionInvocations != null) { + for (_LocalFunctionInvocation data in _localFunctionInvocations) { + registry.registerLocalFunctionInvocation( + data.localFunction, + data.callStructure.positionalArguments, + data.callStructure.namedArguments, + data.callStructure.typeArguments); + } + } + if (_staticInvocations != null) { + for (_StaticInvocation data in _staticInvocations) { + registry.registerStaticInvocation( + data.target, + data.callStructure.positionalArguments, + data.callStructure.namedArguments, + data.callStructure.typeArguments, + data.import); + ; + } + } + if (_constructorInvocations != null) { + for (_ConstructorInvocation data in _constructorInvocations) { + registry.registerNew( + data.constructor, + data.type, + data.callStructure.positionalArguments, + data.callStructure.namedArguments, + data.callStructure.typeArguments, + data.import, + isConst: data.isConst); + } + } + if (_features != null) { + for (_Feature data in _features.iterable(_Feature.values)) { + switch (data) { + case _Feature.lazyField: + registry.registerLazyField(); + break; + case _Feature.loadLibrary: + registry.registerLoadLibrary(); + break; + case _Feature.stackTrace: + registry.registerStackTrace(); + break; + case _Feature.catchClause: + registry.registerCatch(); + break; + case _Feature.throwExpression: + registry.registerThrow(); + break; + case _Feature.localWithoutInitializer: + registry.registerLocalWithoutInitializer(); + break; + case _Feature.stringConcatenation: + registry.registerStringConcatenation(); + break; + case _Feature.assertWithMessage: + registry.registerAssert(withMessage: true); + break; + case _Feature.assertWithoutMessage: + registry.registerAssert(withMessage: false); + break; + case _Feature.nullLiteral: + registry.registerNullLiteral(); + break; + } + } + } + if (_typeUses != null) { + for (_TypeUse data in _typeUses) { + switch (data.kind) { + case _TypeUseKind.parameterCheck: + registry.registerParameterCheck(data.type); + break; + case _TypeUseKind.catchType: + registry.registerCatchType(data.type); + break; + case _TypeUseKind.asyncForIn: + registry.registerAsyncForIn(data.type); + break; + case _TypeUseKind.syncForIn: + registry.registerSyncForIn(data.type); + break; + case _TypeUseKind.asCast: + registry.registerAsCast(data.type); + break; + case _TypeUseKind.implicitCast: + registry.registerImplicitCast(data.type); + break; + case _TypeUseKind.isCheck: + registry.registerIsCheck(data.type); + break; + case _TypeUseKind.asyncStarMarker: + registry.registerAsyncStar(data.type); + break; + case _TypeUseKind.asyncMarker: + registry.registerAsync(data.type); + break; + case _TypeUseKind.syncStarMarker: + registry.registerSyncStar(data.type); + break; + } + } + } + if (_redirectingInitializers != null) { + for (_RedirectingInitializer data in _redirectingInitializers) { + registry.registerRedirectingInitializer( + data.constructor, + data.callStructure.positionalArguments, + data.callStructure.namedArguments, + data.callStructure.typeArguments); + } + } + if (_fieldInitializers != null) { + for (ir.Field data in _fieldInitializers) { + registry.registerFieldInitializer(data); + } + } + if (_typeLiterals != null) { + for (_TypeLiteral data in _typeLiterals) { + registry.registerTypeLiteral(data.type, data.import); + } + } + if (_localFunctions != null) { + for (ir.TreeNode data in _localFunctions) { + registry.registerLocalFunction(data); + } + } + if (_genericInstantiations != null) { + for (_GenericInstantiation data in _genericInstantiations) { + registry.registerGenericInstantiation( + data.expressionType, data.typeArguments); + } + } + if (_staticSets != null) { + for (_StaticAccess data in _staticSets) { + registry.registerStaticSet(data.target, data.import); + } + } + if (_staticGets != null) { + for (_StaticAccess data in _staticGets) { + registry.registerStaticGet(data.target, data.import); + } + } + if (_staticTearOffs != null) { + for (_StaticAccess data in _staticTearOffs) { + registry.registerStaticTearOff(data.target, data.import); + } + } + if (_mapLiterals != null) { + for (_MapLiteral data in _mapLiterals) { + registry.registerMapLiteral(data.keyType, data.valueType, + isConst: data.isConst, isEmpty: data.isEmpty); + } + } + if (_listLiterals != null) { + for (_ContainerLiteral data in _listLiterals) { + registry.registerListLiteral(data.elementType, + isConst: data.isConst, isEmpty: data.isEmpty); + } + } + if (_setLiterals != null) { + for (_ContainerLiteral data in _setLiterals) { + registry.registerSetLiteral(data.elementType, + isConst: data.isConst, isEmpty: data.isEmpty); + } + } + if (_symbolLiterals != null) { + for (String data in _symbolLiterals) { + registry.registerSymbolLiteral(data); + } + } + if (_stringLiterals != null) { + for (String data in _stringLiterals) { + registry.registerStringLiteral(data); + } + } + if (_boolLiterals != null) { + for (bool data in _boolLiterals) { + registry.registerBoolLiteral(data); + } + } + if (_doubleLiterals != null) { + for (double data in _doubleLiterals) { + registry.registerDoubleLiteral(data); + } + } + if (_intLiterals != null) { + for (int data in _intLiterals) { + registry.registerIntLiteral(data); + } + } + if (_runtimeTypeUses != null) { + for (_RuntimeTypeUse data in _runtimeTypeUses) { + registry.registerRuntimeTypeUse( + data.node, data.kind, data.receiverType, data.argumentType); + } + } + + // TODO(johnniwinther): Remove these when CFE provides constants. + if (_constructorNodes != null) { + for (ir.Constructor data in _constructorNodes) { + registry.registerConstructorNode(data); + } + } + if (_fieldNodes != null) { + for (ir.Field data in _fieldNodes) { + registry.registerFieldNode(data); + } + } + if (_procedureNodes != null) { + for (ir.Procedure data in _procedureNodes) { + registry.registerProcedureNode(data); + } + } + if (_switchStatementNodes != null) { + for (ir.SwitchStatement data in _switchStatementNodes) { + registry.registerSwitchStatementNode(data); + } + } + if (_staticInvocationNodes != null) { + for (ir.StaticInvocation data in _staticInvocationNodes) { + registry.registerStaticInvocationNode(data); + } + } + if (_constConstructorInvocationNodes != null) { + for (ir.ConstructorInvocation data in _constConstructorInvocationNodes) { + registry.registerConstConstructorInvocationNode(data); + } + } + } +} + +class _CallStructure { + static const String tag = '_CallStructure'; + + final List typeArguments; + final int positionalArguments; + final List namedArguments; + + _CallStructure.internal( + this.typeArguments, this.positionalArguments, this.namedArguments); + + factory _CallStructure(int positionalArguments, List namedArguments, + List typeArguments) { + return new _CallStructure.internal( + typeArguments, positionalArguments, namedArguments); + } + + factory _CallStructure.fromDataSource(DataSource source) { + source.begin(tag); + List typeArguments = source.readDartTypeNodes(); + int positionalArguments = source.readInt(); + List namedArguments = source.readStrings(); + source.end(tag); + return new _CallStructure.internal( + typeArguments, positionalArguments, namedArguments); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeDartTypeNodes(typeArguments); + sink.writeInt(positionalArguments); + sink.writeStrings(namedArguments); + sink.end(tag); + } +} + +class _SuperInitializer { + static const String tag = '_SuperInitializer'; + + final ir.Constructor source; + final ir.Constructor target; + final _CallStructure callStructure; + + _SuperInitializer(this.source, this.target, this.callStructure); + + factory _SuperInitializer.fromDataSource(DataSource source) { + source.begin(tag); + ir.Constructor sourceConstructor = source.readMemberNode(); + ir.Constructor targetConstructor = source.readMemberNode(); + _CallStructure callStructure = new _CallStructure.fromDataSource(source); + source.end(tag); + return new _SuperInitializer( + sourceConstructor, targetConstructor, callStructure); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeMemberNode(source); + sink.writeMemberNode(target); + callStructure.toDataSink(sink); + sink.end(tag); + } +} + +class _SuperInvocation { + static const String tag = '_SuperInvocation'; + + final ir.Name name; + final _CallStructure callStructure; + + _SuperInvocation(this.name, this.callStructure); + + factory _SuperInvocation.fromDataSource(DataSource source) { + source.begin(tag); + ir.Name name = source.readName(); + _CallStructure callStructure = new _CallStructure.fromDataSource(source); + source.end(tag); + return new _SuperInvocation(name, callStructure); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeName(name); + callStructure.toDataSink(sink); + sink.end(tag); + } +} + +class _InstanceAccess { + static const String tag = '_InstanceAccess'; + + final ir.DartType receiverType; + final ClassRelation classRelation; + final ir.Member target; + + _InstanceAccess(this.receiverType, this.classRelation, this.target); + + factory _InstanceAccess.fromDataSource(DataSource source) { + source.begin(tag); + ir.DartType receiverType = source.readDartTypeNode(); + ClassRelation classRelation = source.readEnum(ClassRelation.values); + ir.Member target = source.readMemberNode(); + source.end(tag); + return new _InstanceAccess(receiverType, classRelation, target); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeDartTypeNode(receiverType); + sink.writeEnum(classRelation); + sink.writeMemberNode(target); + sink.end(tag); + } +} + +class _DynamicAccess { + static const String tag = '_DynamicAccess'; + + final ir.DartType receiverType; + final ClassRelation classRelation; + final ir.Name name; + + _DynamicAccess(this.receiverType, this.classRelation, this.name); + + factory _DynamicAccess.fromDataSource(DataSource source) { + source.begin(tag); + ir.DartType receiverType = source.readDartTypeNode(); + ClassRelation classRelation = source.readEnum(ClassRelation.values); + ir.Name name = source.readName(); + source.end(tag); + return new _DynamicAccess(receiverType, classRelation, name); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeDartTypeNode(receiverType); + sink.writeEnum(classRelation); + sink.writeName(name); + sink.end(tag); + } +} + +class _FunctionInvocation { + static const String tag = '_FunctionInvocation'; + + final ir.DartType receiverType; + final _CallStructure callStructure; + + _FunctionInvocation(this.receiverType, this.callStructure); + + factory _FunctionInvocation.fromDataSource(DataSource source) { + source.begin(tag); + ir.DartType receiverType = source.readDartTypeNode(); + _CallStructure callStructure = new _CallStructure.fromDataSource(source); + source.end(tag); + return new _FunctionInvocation(receiverType, callStructure); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeDartTypeNode(receiverType); + callStructure.toDataSink(sink); + sink.end(tag); + } +} + +class _InstanceInvocation { + static const String tag = '_InstanceInvocation'; + + final ir.DartType receiverType; + final ClassRelation classRelation; + final ir.Member target; + final _CallStructure callStructure; + + _InstanceInvocation( + this.receiverType, this.classRelation, this.target, this.callStructure); + + factory _InstanceInvocation.fromDataSource(DataSource source) { + source.begin(tag); + ir.DartType receiverType = source.readDartTypeNode(); + ClassRelation classRelation = source.readEnum(ClassRelation.values); + ir.Member target = source.readMemberNode(); + _CallStructure callStructure = new _CallStructure.fromDataSource(source); + source.end(tag); + return new _InstanceInvocation( + receiverType, classRelation, target, callStructure); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeDartTypeNode(receiverType); + sink.writeEnum(classRelation); + sink.writeMemberNode(target); + callStructure.toDataSink(sink); + sink.end(tag); + } +} + +class _DynamicInvocation { + static const String tag = '_DynamicInvocation'; + + final ir.DartType receiverType; + final ClassRelation classRelation; + final ir.Name name; + final _CallStructure callStructure; + + _DynamicInvocation( + this.receiverType, this.classRelation, this.name, this.callStructure); + + factory _DynamicInvocation.fromDataSource(DataSource source) { + source.begin(tag); + ir.DartType receiverType = source.readDartTypeNode(); + ClassRelation classRelation = source.readEnum(ClassRelation.values); + ir.Name name = source.readName(); + _CallStructure callStructure = new _CallStructure.fromDataSource(source); + source.end(tag); + return new _DynamicInvocation( + receiverType, classRelation, name, callStructure); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeDartTypeNode(receiverType); + sink.writeEnum(classRelation); + sink.writeName(name); + callStructure.toDataSink(sink); + sink.end(tag); + } +} + +class _LocalFunctionInvocation { + static const String tag = '_LocalFunctionInvocation'; + + final ir.FunctionDeclaration localFunction; + final _CallStructure callStructure; + + _LocalFunctionInvocation(this.localFunction, this.callStructure); + + factory _LocalFunctionInvocation.fromDataSource(DataSource source) { + source.begin(tag); + ir.FunctionDeclaration localFunction = source.readTreeNode(); + _CallStructure callStructure = new _CallStructure.fromDataSource(source); + source.end(tag); + return new _LocalFunctionInvocation(localFunction, callStructure); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeTreeNode(localFunction); + callStructure.toDataSink(sink); + sink.end(tag); + } +} + +class _StaticInvocation { + static const String tag = '_StaticInvocation'; + + final ir.Procedure target; + final _CallStructure callStructure; + final ir.LibraryDependency import; + + _StaticInvocation(this.target, this.callStructure, this.import); + + factory _StaticInvocation.fromDataSource(DataSource source) { + source.begin(tag); + ir.Procedure target = source.readMemberNode(); + _CallStructure callStructure = new _CallStructure.fromDataSource(source); + ir.LibraryDependency import = source.readLibraryDependencyNodeOrNull(); + source.end(tag); + return new _StaticInvocation(target, callStructure, import); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeMemberNode(target); + callStructure.toDataSink(sink); + sink.writeLibraryDependencyNodeOrNull(import); + sink.end(tag); + } +} + +class _ConstructorInvocation { + static const String tag = '_ConstructorInvocation'; + + final ir.Member constructor; + final ir.InterfaceType type; + final _CallStructure callStructure; + final ir.LibraryDependency import; + final bool isConst; + + _ConstructorInvocation( + this.constructor, this.type, this.callStructure, this.import, + {this.isConst}); + + factory _ConstructorInvocation.fromDataSource(DataSource source) { + source.begin(tag); + ir.Member constructor = source.readMemberNode(); + ir.InterfaceType type = source.readDartTypeNode(); + _CallStructure callStructure = new _CallStructure.fromDataSource(source); + ir.LibraryDependency import = source.readLibraryDependencyNodeOrNull(); + bool isConst = source.readBool(); + source.end(tag); + return new _ConstructorInvocation(constructor, type, callStructure, import, + isConst: isConst); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeMemberNode(constructor); + sink.writeDartTypeNode(type); + callStructure.toDataSink(sink); + sink.writeLibraryDependencyNodeOrNull(import); + sink.writeBool(isConst); + sink.end(tag); + } +} + +enum _Feature { + lazyField, + loadLibrary, + stackTrace, + catchClause, + throwExpression, + localWithoutInitializer, + stringConcatenation, + assertWithMessage, + assertWithoutMessage, + nullLiteral, +} + +class _TypeUse { + static const String tag = '_TypeUse'; + + final ir.DartType type; + final _TypeUseKind kind; + + _TypeUse(this.type, this.kind); + + factory _TypeUse.fromDataSource(DataSource source) { + source.begin(tag); + ir.DartType type = source.readDartTypeNode(); + _TypeUseKind kind = source.readEnum(_TypeUseKind.values); + source.end(tag); + return new _TypeUse(type, kind); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeDartTypeNode(type); + sink.writeEnum(kind); + sink.end(tag); + } +} + +enum _TypeUseKind { + parameterCheck, + catchType, + asyncForIn, + syncForIn, + asCast, + implicitCast, + isCheck, + asyncStarMarker, + asyncMarker, + syncStarMarker, +} + +class _RedirectingInitializer { + static const String tag = '_RedirectingInitializer'; + + final ir.Constructor constructor; + final _CallStructure callStructure; + + _RedirectingInitializer(this.constructor, this.callStructure); + + factory _RedirectingInitializer.fromDataSource(DataSource source) { + source.begin(tag); + ir.Constructor constructor = source.readMemberNode(); + _CallStructure callStructure = new _CallStructure.fromDataSource(source); + source.end(tag); + return new _RedirectingInitializer(constructor, callStructure); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeMemberNode(constructor); + callStructure.toDataSink(sink); + sink.end(tag); + } +} + +class _TypeLiteral { + static const String tag = '_TypeLiteral'; + + final ir.DartType type; + final ir.LibraryDependency import; + + _TypeLiteral(this.type, this.import); + + factory _TypeLiteral.fromDataSource(DataSource source) { + source.begin(tag); + ir.DartType type = source.readDartTypeNode(); + ir.LibraryDependency import = source.readLibraryDependencyNodeOrNull(); + source.end(tag); + return new _TypeLiteral(type, import); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeDartTypeNode(type); + sink.writeLibraryDependencyNodeOrNull(import); + sink.end(tag); + } +} + +class _GenericInstantiation { + static const String tag = '_GenericInstantiation'; + + final ir.FunctionType expressionType; + final List typeArguments; + + _GenericInstantiation(this.expressionType, this.typeArguments); + + factory _GenericInstantiation.fromDataSource(DataSource source) { + source.begin(tag); + ir.FunctionType expressionType = source.readDartTypeNode(); + List typeArguments = source.readDartTypeNodes(); + source.end(tag); + return new _GenericInstantiation(expressionType, typeArguments); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeDartTypeNode(expressionType); + sink.writeDartTypeNodes(typeArguments); + sink.end(tag); + } +} + +class _StaticAccess { + static const String tag = '_StaticAccess'; + + final ir.Member target; + final ir.LibraryDependency import; + + _StaticAccess(this.target, this.import); + + factory _StaticAccess.fromDataSource(DataSource source) { + source.begin(tag); + ir.Member target = source.readMemberNode(); + ir.LibraryDependency import = source.readLibraryDependencyNodeOrNull(); + source.end(tag); + return new _StaticAccess(target, import); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeMemberNode(target); + sink.writeLibraryDependencyNodeOrNull(import); + sink.end(tag); + } +} + +class _MapLiteral { + static const String tag = '_MapLiteral'; + + final ir.DartType keyType; + final ir.DartType valueType; + final bool isConst; + final bool isEmpty; + + _MapLiteral(this.keyType, this.valueType, {this.isConst, this.isEmpty}); + + factory _MapLiteral.fromDataSource(DataSource source) { + source.begin(tag); + ir.DartType keyType = source.readDartTypeNode(); + ir.DartType valueType = source.readDartTypeNode(); + bool isConst = source.readBool(); + bool isEmpty = source.readBool(); + source.end(tag); + return _MapLiteral(keyType, valueType, isConst: isConst, isEmpty: isEmpty); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeDartTypeNode(keyType); + sink.writeDartTypeNode(valueType); + sink.writeBool(isConst); + sink.writeBool(isEmpty); + sink.end(tag); + } +} + +class _ContainerLiteral { + static const String tag = '_ContainerLiteral'; + + final ir.DartType elementType; + final bool isConst; + final bool isEmpty; + + _ContainerLiteral(this.elementType, {this.isConst, this.isEmpty}); + + factory _ContainerLiteral.fromDataSource(DataSource source) { + source.begin(tag); + ir.DartType elementType = source.readDartTypeNode(); + bool isConst = source.readBool(); + bool isEmpty = source.readBool(); + return new _ContainerLiteral(elementType, + isConst: isConst, isEmpty: isEmpty); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeDartTypeNode(elementType); + sink.writeBool(isConst); + sink.writeBool(isEmpty); + sink.end(tag); + } +} + +class _RuntimeTypeUse { + static const String tag = '_RuntimeTypeUse'; + + final ir.PropertyGet node; + final RuntimeTypeUseKind kind; + final ir.DartType receiverType; + final ir.DartType argumentType; + + _RuntimeTypeUse(this.node, this.kind, this.receiverType, this.argumentType); + + factory _RuntimeTypeUse.fromDataSource(DataSource source) { + source.begin(tag); + ir.TreeNode node = source.readTreeNode(); + RuntimeTypeUseKind kind = source.readEnum(RuntimeTypeUseKind.values); + ir.DartType receiverType = source.readDartTypeNode(); + ir.DartType argumentType = source.readDartTypeNode(allowNull: true); + return new _RuntimeTypeUse(node, kind, receiverType, argumentType); + } + + void toDataSink(DataSink sink) { + sink.begin(tag); + sink.writeTreeNode(node); + sink.writeEnum(kind); + sink.writeDartTypeNode(receiverType); + sink.writeDartTypeNode(argumentType, allowNull: true); + sink.end(tag); + } +} diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart index 9ddc39029c6..8ec8bad82cf 100644 --- a/pkg/compiler/lib/src/ir/static_type.dart +++ b/pkg/compiler/lib/src/ir/static_type.dart @@ -903,6 +903,15 @@ abstract class StaticTypeVisitor extends StaticTypeBase { return super.visitListLiteral(node); } + void handleSetLiteral(ir.SetLiteral node) {} + + @override + ir.DartType visitSetLiteral(ir.SetLiteral node) { + visitNodes(node.expressions); + handleSetLiteral(node); + return super.visitSetLiteral(node); + } + void handleMapLiteral(ir.MapLiteral node) {} @override diff --git a/pkg/compiler/lib/src/ir/static_type_base.dart b/pkg/compiler/lib/src/ir/static_type_base.dart index 20cf00c1656..5cd80012723 100644 --- a/pkg/compiler/lib/src/ir/static_type_base.dart +++ b/pkg/compiler/lib/src/ir/static_type_base.dart @@ -128,6 +128,11 @@ abstract class StaticTypeBase extends ir.Visitor { return typeEnvironment.literalListType(node.typeArgument); } + @override + ir.DartType visitSetLiteral(ir.SetLiteral node) { + return typeEnvironment.literalSetType(node.typeArgument); + } + @override ir.DartType visitMapLiteral(ir.MapLiteral node) { return typeEnvironment.literalMapType(node.keyType, node.valueType); diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart index b6fe60916a9..8fd2d173609 100644 --- a/pkg/compiler/lib/src/kernel/element_map.dart +++ b/pkg/compiler/lib/src/kernel/element_map.dart @@ -56,13 +56,10 @@ abstract class KernelToElementMap { /// Returns the [CallStructure] corresponding to the [arguments]. CallStructure getCallStructure(ir.Arguments arguments); - /// Returns the [Selector] corresponding to the invocation or getter/setter - /// access of [node]. - Selector getSelector(ir.Expression node); - /// Returns the [Selector] corresponding to the invocation of [name] with /// [arguments]. - Selector getInvocationSelector(ir.Name name, ir.Arguments arguments); + Selector getInvocationSelector(ir.Name name, int positionalArguments, + List namedArguments, int typeArguments); /// Returns the [MemberEntity] corresponding to the member [node]. MemberEntity getMember(ir.Member node); diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart index 9a8c1d1d6e5..343e4848946 100644 --- a/pkg/compiler/lib/src/kernel/element_map_impl.dart +++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart @@ -30,6 +30,8 @@ import '../environment.dart'; import '../frontend_strategy.dart'; import '../ir/debug.dart'; import '../ir/element_map.dart'; +import '../ir/impact.dart'; +import '../ir/impact_data.dart'; import '../ir/static_type.dart'; import '../ir/scope.dart'; import '../ir/types.dart'; @@ -60,6 +62,11 @@ import 'kernel_impact.dart'; part 'native_basic_data.dart'; part 'no_such_method_resolver.dart'; +/// If `true` kernel impacts are computed as [ImpactData] directly on kernel +/// and converted to the K model afterwards. This is a pre-step to modularizing +/// the world impact computation. +bool useImpactDataForTesting = false; + /// Implementation of [KernelToElementMap] that only supports world /// impact computation. class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap { @@ -760,32 +767,8 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap { namedParameters, includeTypeParameters ? typeParameters : 0); } - Selector getSelector(ir.Expression node) { - // TODO(efortuna): This is screaming for a common interface between - // PropertyGet and SuperPropertyGet (and same for *Get). Talk to kernel - // folks. - if (node is ir.PropertyGet) { - return getGetterSelector(node.name); - } - if (node is ir.SuperPropertyGet) { - return getGetterSelector(node.name); - } - if (node is ir.PropertySet) { - return getSetterSelector(node.name); - } - if (node is ir.SuperPropertySet) { - return getSetterSelector(node.name); - } - if (node is ir.InvocationExpression) { - return getInvocationSelector(node.name, node.arguments); - } - throw failedAt( - CURRENT_ELEMENT_SPANNABLE, - "Can only get the selector for a property get or an invocation: " - "${node}"); - } - - Selector getInvocationSelector(ir.Name irName, ir.Arguments arguments) { + Selector getInvocationSelector(ir.Name irName, int positionalArguments, + List namedArguments, int typeArguments) { Name name = getName(irName); SelectorKind kind; if (Selector.isOperatorName(name.text)) { @@ -798,7 +781,10 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap { kind = SelectorKind.CALL; } - CallStructure callStructure = getCallStructure(arguments); + CallStructure callStructure = new CallStructure( + positionalArguments + namedArguments.length, + namedArguments, + typeArguments); return new Selector(kind, name, callStructure); } @@ -1339,15 +1325,34 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap { Set annotations) { KMemberData memberData = members.getData(member); ir.Member node = memberData.node; - KernelImpactBuilder builder = new KernelImpactBuilder( - this, member, reporter, options, variableScopeModel, annotations); - if (retainDataForTesting) { - typeMapsForTesting ??= {}; - typeMapsForTesting[member] = builder.typeMapsForTesting = {}; + + if (useImpactDataForTesting) { + ImpactBuilder builder = new ImpactBuilder( + typeEnvironment, classHierarchy, variableScopeModel, + useAsserts: options.enableUserAssertions, + inferEffectivelyFinalVariableTypes: + !annotations.contains(PragmaAnnotation.disableFinal)); + if (retainDataForTesting) { + typeMapsForTesting ??= {}; + typeMapsForTesting[member] = builder.typeMapsForTesting = {}; + } + node.accept(builder); + ImpactData impactData = builder.impactData; + memberData.staticTypes = builder.cachedStaticTypes; + KernelImpactConverter converter = + new KernelImpactConverter(this, member, reporter, options); + return converter.convert(impactData); + } else { + KernelImpactBuilder builder = new KernelImpactBuilder( + this, member, reporter, options, variableScopeModel, annotations); + if (retainDataForTesting) { + typeMapsForTesting ??= {}; + typeMapsForTesting[member] = builder.typeMapsForTesting = {}; + } + node.accept(builder); + memberData.staticTypes = builder.cachedStaticTypes; + return builder.impactBuilder; } - node.accept(builder); - memberData.staticTypes = builder.cachedStaticTypes; - return builder.impactBuilder; } ScopeModel computeScopeModel(KMember member) { diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart index c3b43069c70..4853aabaa32 100644 --- a/pkg/compiler/lib/src/kernel/kernel_impact.dart +++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart @@ -3,9 +3,11 @@ // BSD-style license that can be found in the LICENSE file. import 'package:kernel/ast.dart' as ir; +import 'package:kernel/type_environment.dart' as ir; import '../common.dart'; import '../common/names.dart'; +import '../common/resolution.dart'; import '../common_elements.dart'; import '../constants/expressions.dart'; import '../constants/values.dart'; @@ -15,6 +17,7 @@ import '../ir/runtime_type_analysis.dart'; import '../ir/scope.dart'; import '../ir/static_type.dart'; import '../ir/impact.dart'; +import '../ir/impact_data.dart'; import '../ir/util.dart'; import '../js_backend/annotations.dart'; import '../js_backend/native_data.dart'; @@ -27,7 +30,9 @@ import '../universe/use.dart'; import '../universe/world_builder.dart'; import 'element_map.dart'; -class KernelImpactBuilder extends ImpactBuilder { +/// Visitor that computes the world impact of a member. +class KernelImpactBuilder extends ImpactBuilderBase + with KernelImpactRegistryMixin { final ResolutionWorldImpactBuilder impactBuilder; final KernelToElementMap elementMap; final DiagnosticReporter reporter; @@ -50,6 +55,47 @@ class KernelImpactBuilder extends ImpactBuilder { bool get inferEffectivelyFinalVariableTypes => !_annotations.contains(PragmaAnnotation.disableFinal); +} + +/// Converts a [ImpactData] object based on kernel to the corresponding +/// [ResolutionImpact] based on the K model. +class KernelImpactConverter extends KernelImpactRegistryMixin { + final ResolutionWorldImpactBuilder impactBuilder; + final KernelToElementMap elementMap; + final DiagnosticReporter reporter; + final CompilerOptions _options; + final MemberEntity currentMember; + + KernelImpactConverter( + this.elementMap, this.currentMember, this.reporter, this._options) + : this.impactBuilder = + new ResolutionWorldImpactBuilder('${currentMember}'); + + ir.TypeEnvironment get typeEnvironment => elementMap.typeEnvironment; + + CommonElements get commonElements => elementMap.commonElements; + + NativeBasicData get _nativeBasicData => elementMap.nativeBasicData; + + /// Converts a [ImpactData] object based on kernel to the corresponding + /// [ResolutionImpact] based on the K model. + ResolutionImpact convert(ImpactData impactData) { + impactData.apply(this); + return impactBuilder; + } +} + +/// [ImpactRegistry] that converts kernel based impact data to world impact +/// object based on the K model. +abstract class KernelImpactRegistryMixin implements ImpactRegistry { + CompilerOptions get _options; + DiagnosticReporter get reporter; + KernelToElementMap get elementMap; + MemberEntity get currentMember; + ResolutionWorldImpactBuilder get impactBuilder; + ir.TypeEnvironment get typeEnvironment; + CommonElements get commonElements; + NativeBasicData get _nativeBasicData; Object _computeReceiverConstraint( ir.DartType receiverType, ClassRelation relation) { @@ -72,9 +118,9 @@ class KernelImpactBuilder extends ImpactBuilder { } } - List _getTypeArguments(ir.Arguments arguments) { - if (arguments.types.isEmpty) return null; - return arguments.types.map(elementMap.getDartType).toList(); + List _getTypeArguments(List types) { + if (types.isEmpty) return null; + return types.map(elementMap.getDartType).toList(); } @override @@ -83,9 +129,7 @@ class KernelImpactBuilder extends ImpactBuilder { } @override - void handleField(ir.Field field) { - super.handleField(field); - + void registerFieldNode(ir.Field field) { if (field.isInstanceMember && elementMap.isNativeClass(field.enclosingClass)) { MemberEntity member = elementMap.getMember(field); @@ -98,7 +142,7 @@ class KernelImpactBuilder extends ImpactBuilder { } @override - void handleConstructor(ir.Constructor constructor) { + void registerConstructorNode(ir.Constructor constructor) { MemberEntity member = elementMap.getMember(constructor); if (constructor.isExternal && !commonElements.isForeignHelper(member)) { bool isJsInterop = _nativeBasicData.isJsInteropMember(member); @@ -135,9 +179,7 @@ class KernelImpactBuilder extends ImpactBuilder { } @override - void handleProcedure(ir.Procedure procedure) { - super.handleProcedure(procedure); - + void registerProcedureNode(ir.Procedure procedure) { MemberEntity member = elementMap.getMember(procedure); if (procedure.isExternal && !commonElements.isForeignHelper(member)) { bool isJsInterop = _nativeBasicData.isJsInteropMember(member); @@ -179,29 +221,43 @@ class KernelImpactBuilder extends ImpactBuilder { @override void registerListLiteral(ir.DartType elementType, - {bool isConstant, bool isEmpty}) { + {bool isConst, bool isEmpty}) { impactBuilder.registerListLiteral(new ListLiteralUse( commonElements.listType(elementMap.getDartType(elementType)), - isConstant: isConstant, + isConstant: isConst, isEmpty: isEmpty)); } + @override + void registerSetLiteral(ir.DartType elementType, + {bool isConst, bool isEmpty}) { + // TODO(johnniwinther,fishythefish): Register set literals. + } + @override void registerMapLiteral(ir.DartType keyType, ir.DartType valueType, - {bool isConstant, bool isEmpty}) { + {bool isConst, bool isEmpty}) { impactBuilder.registerMapLiteral(new MapLiteralUse( commonElements.mapType( elementMap.getDartType(keyType), elementMap.getDartType(valueType)), - isConstant: isConstant, + isConstant: isConst, isEmpty: isEmpty)); } @override - void registerNew(ir.Member target, ir.InterfaceType type, - ir.Arguments arguments, ir.LibraryDependency import, + void registerNew( + ir.Member target, + ir.InterfaceType type, + int positionalArguments, + List namedArguments, + List typeArguments, + ir.LibraryDependency import, {bool isConst}) { ConstructorEntity constructor = elementMap.getConstructor(target); - CallStructure callStructure = elementMap.getCallStructure(arguments); + CallStructure callStructure = new CallStructure( + positionalArguments + namedArguments.length, + namedArguments, + typeArguments.length); ImportEntity deferredImport = elementMap.getImport(import); impactBuilder.registerStaticUse(isConst ? new StaticUse.constConstructorInvoke(constructor, callStructure, @@ -223,10 +279,14 @@ class KernelImpactBuilder extends ImpactBuilder { // We need to register the external constructor as live below, so don't // return here. } + } - if (isConst && commonElements.isSymbolConstructor(constructor)) { + void registerConstConstructorInvocationNode(ir.ConstructorInvocation node) { + assert(node.isConst); + ConstructorEntity constructor = elementMap.getConstructor(node.target); + if (commonElements.isSymbolConstructor(constructor)) { ConstantValue value = - elementMap.getConstantValue(arguments.positional.first); + elementMap.getConstantValue(node.arguments.positional.first); if (!value.isString) { // TODO(het): Get the actual span for the Symbol constructor argument reporter.reportErrorMessage( @@ -242,7 +302,11 @@ class KernelImpactBuilder extends ImpactBuilder { @override void registerSuperInitializer( - ir.Constructor source, ir.Constructor target, ir.Arguments arguments) { + ir.Constructor source, + ir.Constructor target, + int positionalArguments, + List namedArguments, + List typeArguments) { // TODO(johnniwinther): Maybe rewrite `node.target` to point to a // synthesized unnamed mixin constructor when needed. This would require us // to consider impact building a required pre-step for inference and @@ -250,29 +314,36 @@ class KernelImpactBuilder extends ImpactBuilder { ConstructorEntity constructor = elementMap.getSuperConstructor(source, target); impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke( - constructor, elementMap.getCallStructure(arguments))); + constructor, + new CallStructure(positionalArguments + namedArguments.length, + namedArguments, typeArguments.length))); } @override - void registerStaticInvocation(ir.Procedure procedure, ir.Arguments arguments, + void registerStaticInvocation( + ir.Procedure procedure, + int positionalArguments, + List namedArguments, + List typeArguments, ir.LibraryDependency import) { FunctionEntity target = elementMap.getMethod(procedure); - CallStructure callStructure = elementMap.getCallStructure(arguments); - List typeArguments = _getTypeArguments(arguments); + CallStructure callStructure = new CallStructure( + positionalArguments + namedArguments.length, + namedArguments, + typeArguments.length); + List dartTypeArguments = _getTypeArguments(typeArguments); if (commonElements.isExtractTypeArguments(target)) { - _handleExtractTypeArguments(target, typeArguments, callStructure); + _handleExtractTypeArguments(target, dartTypeArguments, callStructure); return; } else { ImportEntity deferredImport = elementMap.getImport(import); impactBuilder.registerStaticUse(new StaticUse.staticInvoke( - target, callStructure, typeArguments, deferredImport)); + target, callStructure, dartTypeArguments, deferredImport)); } } - void handleStaticInvocation(ir.StaticInvocation node, - ArgumentTypes argumentTypes, ir.DartType returnType) { - super.handleStaticInvocation(node, argumentTypes, returnType); - + @override + void registerStaticInvocationNode(ir.StaticInvocation node) { switch (elementMap.getForeignKind(node)) { case ForeignKind.JS: impactBuilder @@ -346,13 +417,17 @@ class KernelImpactBuilder extends ImpactBuilder { } @override - void registerSuperInvocation(ir.Name name, ir.Arguments arguments) { + void registerSuperInvocation(ir.Name name, int positionalArguments, + List namedArguments, List typeArguments) { FunctionEntity method = elementMap.getSuperMember(currentMember, name, setter: false); - List typeArguments = _getTypeArguments(arguments); + List dartTypeArguments = _getTypeArguments(typeArguments); if (method != null) { impactBuilder.registerStaticUse(new StaticUse.superInvoke( - method, elementMap.getCallStructure(arguments), typeArguments)); + method, + new CallStructure(positionalArguments + namedArguments.length, + namedArguments, typeArguments.length), + dartTypeArguments)); } else { impactBuilder.registerStaticUse(new StaticUse.superInvoke( elementMap.getSuperNoSuchMethod(currentMember.enclosingClass), @@ -399,50 +474,74 @@ class KernelImpactBuilder extends ImpactBuilder { @override void registerLocalFunctionInvocation( - ir.FunctionDeclaration localFunction, ir.Arguments arguments) { - CallStructure callStructure = elementMap.getCallStructure(arguments); - List typeArguments = _getTypeArguments(arguments); + ir.FunctionDeclaration localFunction, + int positionalArguments, + List namedArguments, + List typeArguments) { + CallStructure callStructure = new CallStructure( + positionalArguments + namedArguments.length, + namedArguments, + typeArguments.length); + List dartTypeArguments = _getTypeArguments(typeArguments); // Invocation of a local function. No need for dynamic use, but // we need to track the type arguments. impactBuilder.registerStaticUse(new StaticUse.closureCall( elementMap.getLocalFunction(localFunction), callStructure, - typeArguments)); + dartTypeArguments)); // TODO(johnniwinther): Yet, alas, we need the dynamic use for now. Remove // this when kernel adds an `isFunctionCall` flag to // [ir.MethodInvocation]. impactBuilder.registerDynamicUse(new ConstrainedDynamicUse( - callStructure.callSelector, null, typeArguments)); + callStructure.callSelector, null, dartTypeArguments)); } @override - void registerDynamicInvocation(ir.DartType receiverType, - ClassRelation relation, ir.Name name, ir.Arguments arguments) { - Selector selector = elementMap.getInvocationSelector(name, arguments); - List typeArguments = _getTypeArguments(arguments); + void registerDynamicInvocation( + ir.DartType receiverType, + ClassRelation relation, + ir.Name name, + int positionalArguments, + List namedArguments, + List typeArguments) { + Selector selector = elementMap.getInvocationSelector( + name, positionalArguments, namedArguments, typeArguments.length); + List dartTypeArguments = _getTypeArguments(typeArguments); impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(selector, - _computeReceiverConstraint(receiverType, relation), typeArguments)); + _computeReceiverConstraint(receiverType, relation), dartTypeArguments)); } @override void registerFunctionInvocation( - ir.DartType receiverType, ir.Arguments arguments) { - CallStructure callStructure = elementMap.getCallStructure(arguments); - List typeArguments = _getTypeArguments(arguments); + ir.DartType receiverType, + int positionalArguments, + List namedArguments, + List typeArguments) { + CallStructure callStructure = new CallStructure( + positionalArguments + namedArguments.length, + namedArguments, + typeArguments.length); + List dartTypeArguments = _getTypeArguments(typeArguments); impactBuilder.registerDynamicUse(new ConstrainedDynamicUse( callStructure.callSelector, _computeReceiverConstraint(receiverType, ClassRelation.subtype), - typeArguments)); + dartTypeArguments)); } @override - void registerInstanceInvocation(ir.DartType receiverType, - ClassRelation relation, ir.Member target, ir.Arguments arguments) { - List typeArguments = _getTypeArguments(arguments); + void registerInstanceInvocation( + ir.DartType receiverType, + ClassRelation relation, + ir.Member target, + int positionalArguments, + List namedArguments, + List typeArguments) { + List dartTypeArguments = _getTypeArguments(typeArguments); impactBuilder.registerDynamicUse(new ConstrainedDynamicUse( - elementMap.getInvocationSelector(target.name, arguments), + elementMap.getInvocationSelector(target.name, positionalArguments, + namedArguments, typeArguments.length), _computeReceiverConstraint(receiverType, relation), - typeArguments)); + dartTypeArguments)); } @override @@ -481,7 +580,8 @@ class KernelImpactBuilder extends ImpactBuilder { const [])); } - void handleRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind, + @override + void registerRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind, ir.DartType receiverType, ir.DartType argumentType) { DartType receiverDartType = elementMap.getDartType(receiverType); DartType argumentDartType = @@ -561,7 +661,6 @@ class KernelImpactBuilder extends ImpactBuilder { .registerTypeUse(new TypeUse.asCast(elementMap.getDartType(type))); } - @override @override void registerThrow() { impactBuilder.registerFeature(Feature.THROW_EXPRESSION); @@ -619,10 +718,15 @@ class KernelImpactBuilder extends ImpactBuilder { @override void registerRedirectingInitializer( - ir.Constructor constructor, ir.Arguments arguments) { + ir.Constructor constructor, + int positionalArguments, + List namedArguments, + List typeArguments) { ConstructorEntity target = elementMap.getConstructor(constructor); impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke( - target, elementMap.getCallStructure(arguments))); + target, + new CallStructure(positionalArguments + namedArguments.length, + namedArguments, typeArguments.length))); } @override @@ -633,7 +737,7 @@ class KernelImpactBuilder extends ImpactBuilder { } @override - void handleSwitchStatement(ir.SwitchStatement node) { + void registerSwitchStatementNode(ir.SwitchStatement node) { // TODO(32557): Remove this when issue 32557 is fixed. ir.TreeNode firstCase; DartType firstCaseType; diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart index 07116be4115..d63db8f0f4c 100644 --- a/pkg/compiler/lib/src/serialization/abstract_sink.dart +++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart @@ -203,7 +203,7 @@ abstract class AbstractDataSink extends DataSinkMixin implements DataSink { void writeInt(int value) { assert(value != null); assert(value >= 0 && value >> 30 == 0); - _writeDataKind(DataKind.int); + _writeDataKind(DataKind.uint30); _writeIntInternal(value); } @@ -338,6 +338,31 @@ abstract class AbstractDataSink extends DataSinkMixin implements DataSink { _writeConstant(value); } + @override + void writeDoubleValue(double value) { + _writeDataKind(DataKind.double); + _writeDoubleValue(value); + } + + void _writeDoubleValue(double value) { + ByteData data = new ByteData(8); + data.setFloat64(0, value); + writeInt(data.getUint16(0)); + writeInt(data.getUint16(2)); + writeInt(data.getUint16(4)); + writeInt(data.getUint16(6)); + } + + @override + void writeIntegerValue(int value) { + _writeDataKind(DataKind.int); + _writeBigInt(new BigInt.from(value)); + } + + void _writeBigInt(BigInt value) { + writeString(value.toString()); + } + void _writeConstant(ConstantValue value) { _writeEnumInternal(value.kind); switch (value.kind) { @@ -347,16 +372,11 @@ abstract class AbstractDataSink extends DataSinkMixin implements DataSink { break; case ConstantValueKind.INT: IntConstantValue constant = value; - writeString(constant.intValue.toString()); + _writeBigInt(constant.intValue); break; case ConstantValueKind.DOUBLE: DoubleConstantValue constant = value; - ByteData data = new ByteData(8); - data.setFloat64(0, constant.doubleValue); - writeInt(data.getUint16(0)); - writeInt(data.getUint16(2)); - writeInt(data.getUint16(4)); - writeInt(data.getUint16(6)); + _writeDoubleValue(constant.doubleValue); break; case ConstantValueKind.STRING: StringConstantValue constant = value; diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart index 28fdf8accd6..792ae23f096 100644 --- a/pkg/compiler/lib/src/serialization/abstract_source.dart +++ b/pkg/compiler/lib/src/serialization/abstract_source.dart @@ -393,7 +393,7 @@ abstract class AbstractDataSource extends DataSourceMixin @override int readInt() { - _checkDataKind(DataKind.int); + _checkDataKind(DataKind.uint30); return _readIntInternal(); } @@ -409,6 +409,29 @@ abstract class AbstractDataSource extends DataSourceMixin return _readConstant(); } + double readDoubleValue() { + _checkDataKind(DataKind.double); + return _readDoubleValue(); + } + + double _readDoubleValue() { + ByteData data = new ByteData(8); + data.setUint16(0, readInt()); + data.setUint16(2, readInt()); + data.setUint16(4, readInt()); + data.setUint16(6, readInt()); + return data.getFloat64(0); + } + + int readIntegerValue() { + _checkDataKind(DataKind.int); + return _readBigInt().toInt(); + } + + BigInt _readBigInt() { + return BigInt.parse(readString()); + } + ConstantValue _readConstant() { ConstantValueKind kind = _readEnumInternal(ConstantValueKind.values); switch (kind) { @@ -416,15 +439,10 @@ abstract class AbstractDataSource extends DataSourceMixin bool value = readBool(); return new BoolConstantValue(value); case ConstantValueKind.INT: - BigInt value = BigInt.parse(readString()); + BigInt value = _readBigInt(); return new IntConstantValue(value); case ConstantValueKind.DOUBLE: - ByteData data = new ByteData(8); - data.setUint16(0, readInt()); - data.setUint16(2, readInt()); - data.setUint16(4, readInt()); - data.setUint16(6, readInt()); - double value = data.getFloat64(0); + double value = _readDoubleValue(); return new DoubleConstantValue(value); case ConstantValueKind.STRING: String value = readString(); diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart index a75b7e3cf32..d6db5f27c49 100644 --- a/pkg/compiler/lib/src/serialization/helpers.dart +++ b/pkg/compiler/lib/src/serialization/helpers.dart @@ -10,7 +10,7 @@ part of 'serialization.dart'; /// and deserialization. enum DataKind { bool, - int, + uint30, string, enumValue, uri, @@ -25,6 +25,8 @@ enum DataKind { sourceSpan, constant, import, + double, + int, } /// Enum used for identifying the enclosing entity of a member in serialization. diff --git a/pkg/compiler/lib/src/serialization/mixins.dart b/pkg/compiler/lib/src/serialization/mixins.dart index eb86a2a96c9..be891a16335 100644 --- a/pkg/compiler/lib/src/serialization/mixins.dart +++ b/pkg/compiler/lib/src/serialization/mixins.dart @@ -313,6 +313,36 @@ abstract class DataSourceMixin implements DataSource { } return map; } + + @override + List readDartTypeNodes({bool emptyAsNull: false}) { + int count = readInt(); + if (count == 0 && emptyAsNull) return null; + List list = new List(count); + for (int i = 0; i < count; i++) { + list[i] = readDartTypeNode(); + } + return list; + } + + @override + ir.Name readName() { + String text = readString(); + ir.Library library = readValueOrNull(readLibraryNode); + return new ir.Name(text, library); + } + + @override + ir.LibraryDependency readLibraryDependencyNode() { + ir.Library library = readLibraryNode(); + int index = readInt(); + return library.dependencies[index]; + } + + @override + ir.LibraryDependency readLibraryDependencyNodeOrNull() { + return readValueOrNull(readLibraryDependencyNode); + } } /// Mixin that implements all convenience methods of [DataSink]. @@ -643,4 +673,36 @@ abstract class DataSinkMixin implements DataSink { }); } } + + @override + void writeDartTypeNodes(Iterable values, + {bool allowNull: false}) { + if (values == null) { + assert(allowNull); + writeInt(0); + } else { + writeInt(values.length); + for (ir.DartType value in values) { + writeDartTypeNode(value); + } + } + } + + @override + void writeName(ir.Name value) { + writeString(value.name); + writeValueOrNull(value.library, writeLibraryNode); + } + + @override + void writeLibraryDependencyNode(ir.LibraryDependency value) { + ir.Library library = value.parent; + writeLibraryNode(library); + writeInt(library.dependencies.indexOf(value)); + } + + @override + void writeLibraryDependencyNodeOrNull(ir.LibraryDependency value) { + writeValueOrNull(value, writeLibraryDependencyNode); + } } diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart index 3348eddd927..c4dab5a1363 100644 --- a/pkg/compiler/lib/src/serialization/serialization.dart +++ b/pkg/compiler/lib/src/serialization/serialization.dart @@ -75,7 +75,7 @@ abstract class DataSink { /// Writes the boolean [value] to this data sink. void writeBool(bool value); - /// Writes the non-negative integer [value] to this data sink. + /// Writes the non-negative 30 bit integer [value] to this data sink. void writeInt(int value); /// Writes the potentially `null` non-negative [value] to this data sink. @@ -137,6 +137,16 @@ abstract class DataSink { /// [DataSource.readMemberNodes]. void writeMemberNodes(Iterable values, {bool allowNull: false}); + /// Writes a kernel name node to this data sink. + void writeName(ir.Name value); + + /// Writes a kernel library dependency node [value] to this data sink. + void writeLibraryDependencyNode(ir.LibraryDependency value); + + /// Writes a potentially `null` kernel library dependency node [value] to + /// this data sink. + void writeLibraryDependencyNodeOrNull(ir.LibraryDependency value); + /// Writes a reference to the kernel tree node [value] to this data sink. void writeTreeNode(ir.TreeNode value); @@ -191,6 +201,14 @@ abstract class DataSink { /// `true`, [value] is allowed to be `null`. void writeDartTypeNode(ir.DartType value, {bool allowNull: false}); + /// Writes the kernel type node [values] to this data sink. If [allowNull] is + /// `true`, [values] is allowed to be `null`. + /// + /// This is a convenience method to be used together with + /// [DataSource.readDartTypeNodes]. + void writeDartTypeNodes(Iterable values, + {bool allowNull: false}); + /// Writes the source span [value] to this data sink. void writeSourceSpan(SourceSpan value); @@ -313,6 +331,15 @@ abstract class DataSink { void writeConstantMap(Map map, void f(V value), {bool allowNull: false}); + /// Writes a double value to this data sink. + void writeDoubleValue(double value); + + /// Writes an integer of arbitrary value to this data sink. + /// + /// This is should only when the value is not known to be a non-negative + /// 30 bit integer. Otherwise [writeInt] should be used. + void writeIntegerValue(int value); + /// Writes the import [value] to this data sink. void writeImport(ImportEntity value); @@ -380,7 +407,7 @@ abstract class DataSource { /// Reads a boolean value from this data source. bool readBool(); - /// Reads a non-negative integer value from this data source. + /// Reads a non-negative 30 bit integer value from this data source. int readInt(); /// Reads a potentially `null` non-negative integer value from this data @@ -448,6 +475,16 @@ abstract class DataSource { List readMemberNodes( {bool emptyAsNull: false}); + /// Reads a kernel name node from this data source. + ir.Name readName(); + + /// Reads a kernel library dependency node from this data source. + ir.LibraryDependency readLibraryDependencyNode(); + + /// Reads a potentially `null` kernel library dependency node from this data + /// source. + ir.LibraryDependency readLibraryDependencyNodeOrNull(); + /// Reads a reference to a kernel tree node from this data source. ir.TreeNode readTreeNode(); @@ -497,6 +534,13 @@ abstract class DataSource { /// returned type is allowed to be `null`. ir.DartType readDartTypeNode({bool allowNull: false}); + /// Reads a list of kernel type nodes from this data source. If [emptyAsNull] + /// is `true`, `null` is returned instead of an empty list. + /// + /// This is a convenience method to be used together with + /// [DataSink.writeDartTypeNodes]. + List readDartTypeNodes({bool emptyAsNull: false}); + /// Reads a source span from this data source. SourceSpan readSourceSpan(); @@ -582,6 +626,15 @@ abstract class DataSource { /// Reads a constant value from this data source. ConstantValue readConstant(); + /// Reads a double value from this data source. + double readDoubleValue(); + + /// Reads an integer of arbitrary value from this data source. + /// + /// This is should only when the value is not known to be a non-negative + /// 30 bit integer. Otherwise [readInt] should be used. + int readIntegerValue(); + /// Reads a list of constant values from this data source. If [emptyAsNull] is /// `true`, `null` is returned instead of an empty list. /// diff --git a/tests/compiler/dart2js/impact/impact_test.dart b/tests/compiler/dart2js/impact/impact_test.dart index e59b077e2f9..2dc7d401c9b 100644 --- a/tests/compiler/dart2js/impact/impact_test.dart +++ b/tests/compiler/dart2js/impact/impact_test.dart @@ -9,6 +9,7 @@ import 'package:compiler/src/compiler.dart'; import 'package:compiler/src/elements/entities.dart'; import 'package:compiler/src/ir/util.dart'; import 'package:compiler/src/kernel/kernel_strategy.dart'; +import 'package:compiler/src/kernel/element_map_impl.dart'; import 'package:compiler/src/universe/feature.dart'; import 'package:compiler/src/universe/use.dart'; import 'package:compiler/src/universe/world_impact.dart'; @@ -20,6 +21,15 @@ import '../equivalence/id_equivalence_helper.dart'; main(List args) { asyncTest(() async { Directory dataDir = new Directory.fromUri(Platform.script.resolve('data')); + print('Testing direct computation of ResolutionImpact'); + print('=================================================================='); + useImpactDataForTesting = false; + await checkTests(dataDir, const ImpactDataComputer(), + args: args, testOmit: false, testFrontend: true); + + print('Testing computation of ResolutionImpact through ImpactData'); + print('=================================================================='); + useImpactDataForTesting = true; await checkTests(dataDir, const ImpactDataComputer(), args: args, testOmit: false, testFrontend: true); });