Support computation of ResolutionImpact through ImpactData based on kernel

This is a pre-step to modularizing the world impact computation.

Change-Id: I4f59f9767e7399fdcf9a070074864e6873b61a52
Reviewed-on: https://dart-review.googlesource.com/c/92044
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
Johnni Winther 2019-02-08 12:02:33 +00:00 committed by commit-bot@chromium.org
parent 52f5e34dbf
commit 60527d7b97
13 changed files with 2212 additions and 252 deletions

View file

@ -10,15 +10,185 @@ import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/type_environment.dart' as ir; import 'package:kernel/type_environment.dart' as ir;
import '../common.dart'; import '../common.dart';
import 'impact_data.dart';
import 'runtime_type_analysis.dart';
import 'scope.dart'; import 'scope.dart';
import 'static_type.dart'; import 'static_type.dart';
import 'static_type_base.dart'; import 'static_type_base.dart';
import 'util.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<ir.DartType> 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<String> namedArguments,
List<ir.DartType> typeArguments);
void registerParameterCheck(ir.DartType type);
void registerLazyField();
void registerNew(
ir.Member constructor,
ir.InterfaceType type,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments,
ir.LibraryDependency import,
{bool isConst});
void registerStaticInvocation(
ir.Procedure target,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments,
ir.LibraryDependency import);
void registerLocalFunctionInvocation(
ir.FunctionDeclaration localFunction,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments);
void registerDynamicInvocation(
ir.DartType receiverType,
ClassRelation relation,
ir.Name name,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments);
void registerInstanceInvocation(
ir.DartType receiverType,
ClassRelation relation,
ir.Member target,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments);
void registerFunctionInvocation(
ir.DartType receiverType,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> 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<String> namedArguments, List<ir.DartType> typeArguments);
void registerSuperGet(ir.Name name);
void registerSuperSet(ir.Name name);
void registerSuperInitializer(
ir.Constructor source,
ir.Constructor target,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> 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; final VariableScopeModel variableScopeModel;
ImpactBuilder(ir.TypeEnvironment typeEnvironment, ImpactBuilderBase(ir.TypeEnvironment typeEnvironment,
ir.ClassHierarchy classHierarchy, this.variableScopeModel) ir.ClassHierarchy classHierarchy, this.variableScopeModel)
: super(typeEnvironment, classHierarchy); : super(typeEnvironment, classHierarchy);
@ -32,71 +202,54 @@ abstract class ImpactBuilder extends StaticTypeVisitor {
} }
} }
void registerIntLiteral(int value);
@override @override
void handleIntLiteral(ir.IntLiteral node) { void handleIntLiteral(ir.IntLiteral node) {
registerIntLiteral(node.value); registerIntLiteral(node.value);
} }
void registerDoubleLiteral(double value);
@override @override
void handleDoubleLiteral(ir.DoubleLiteral node) { void handleDoubleLiteral(ir.DoubleLiteral node) {
registerDoubleLiteral(node.value); registerDoubleLiteral(node.value);
} }
void registerBoolLiteral(bool value);
@override @override
void handleBoolLiteral(ir.BoolLiteral node) { void handleBoolLiteral(ir.BoolLiteral node) {
registerBoolLiteral(node.value); registerBoolLiteral(node.value);
} }
void registerStringLiteral(String value);
@override @override
void handleStringLiteral(ir.StringLiteral node) { void handleStringLiteral(ir.StringLiteral node) {
registerStringLiteral(node.value); registerStringLiteral(node.value);
} }
void registerSymbolLiteral(String value);
@override @override
void handleSymbolLiteral(ir.SymbolLiteral node) { void handleSymbolLiteral(ir.SymbolLiteral node) {
registerSymbolLiteral(node.value); registerSymbolLiteral(node.value);
} }
void registerNullLiteral();
@override @override
void handleNullLiteral(ir.NullLiteral node) { void handleNullLiteral(ir.NullLiteral node) {
registerNullLiteral(); registerNullLiteral();
} }
void registerListLiteral(ir.DartType elementType,
{bool isConstant, bool isEmpty});
@override @override
void handleListLiteral(ir.ListLiteral node) { void handleListLiteral(ir.ListLiteral node) {
registerListLiteral(node.typeArgument, 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, @override
{bool isConstant, bool isEmpty}); void handleSetLiteral(ir.SetLiteral node) {
registerSetLiteral(node.typeArgument,
isConst: node.isConst, isEmpty: node.expressions.isEmpty);
}
@override @override
void handleMapLiteral(ir.MapLiteral node) { void handleMapLiteral(ir.MapLiteral node) {
registerMapLiteral(node.keyType, node.valueType, 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 @override
void handleStaticGet(ir.StaticGet node, ir.DartType resultType) { void handleStaticGet(ir.StaticGet node, ir.DartType resultType) {
ir.Member target = node.target; ir.Member target = node.target;
@ -107,35 +260,22 @@ abstract class ImpactBuilder extends StaticTypeVisitor {
} }
} }
void registerStaticSet(ir.Member member, ir.LibraryDependency import);
@override @override
void handleStaticSet(ir.StaticSet node, ir.DartType valueType) { void handleStaticSet(ir.StaticSet node, ir.DartType valueType) {
registerStaticSet(node.target, getDeferredImport(node)); registerStaticSet(node.target, getDeferredImport(node));
} }
void registerAssert({bool withMessage});
@override @override
void handleAssertStatement(ir.AssertStatement node) { void handleAssertStatement(ir.AssertStatement node) {
registerAssert(withMessage: node.message != null); registerAssert(withMessage: node.message != null);
} }
void registerGenericInstantiation(
ir.FunctionType expressionType, List<ir.DartType> typeArguments);
@override @override
void handleInstantiation(ir.Instantiation node, void handleInstantiation(ir.Instantiation node,
ir.FunctionType expressionType, ir.DartType resultType) { ir.FunctionType expressionType, ir.DartType resultType) {
registerGenericInstantiation(expressionType, node.typeArguments); registerGenericInstantiation(expressionType, node.typeArguments);
} }
void registerSyncStar(ir.DartType elementType);
void registerAsync(ir.DartType elementType);
void registerAsyncStar(ir.DartType elementType);
void handleAsyncMarker(ir.FunctionNode function) { void handleAsyncMarker(ir.FunctionNode function) {
ir.AsyncMarker asyncMarker = function.asyncMarker; ir.AsyncMarker asyncMarker = function.asyncMarker;
ir.DartType returnType = function.returnType; ir.DartType returnType = function.returnType;
@ -182,15 +322,11 @@ abstract class ImpactBuilder extends StaticTypeVisitor {
} }
} }
void registerStringConcatenation();
@override @override
void handleStringConcatenation(ir.StringConcatenation node) { void handleStringConcatenation(ir.StringConcatenation node) {
registerStringConcatenation(); registerStringConcatenation();
} }
void registerLocalFunction(ir.TreeNode node);
@override @override
Null handleFunctionDeclaration(ir.FunctionDeclaration node) { Null handleFunctionDeclaration(ir.FunctionDeclaration node) {
registerLocalFunction(node); registerLocalFunction(node);
@ -203,8 +339,6 @@ abstract class ImpactBuilder extends StaticTypeVisitor {
handleAsyncMarker(node.function); handleAsyncMarker(node.function);
} }
void registerLocalWithoutInitializer();
@override @override
void handleVariableDeclaration(ir.VariableDeclaration node) { void handleVariableDeclaration(ir.VariableDeclaration node) {
if (node.initializer == null) { if (node.initializer == null) {
@ -212,17 +346,11 @@ abstract class ImpactBuilder extends StaticTypeVisitor {
} }
} }
void registerIsCheck(ir.DartType type);
@override @override
void handleIsExpression(ir.IsExpression node) { void handleIsExpression(ir.IsExpression node) {
registerIsCheck(node.type); registerIsCheck(node.type);
} }
void registerImplicitCast(ir.DartType type);
void registerAsCast(ir.DartType type);
@override @override
void handleAsExpression(ir.AsExpression node, ir.DartType operandType) { void handleAsExpression(ir.AsExpression node, ir.DartType operandType) {
if (typeEnvironment.isSubtypeOf(operandType, node.type)) { if (typeEnvironment.isSubtypeOf(operandType, node.type)) {
@ -236,17 +364,11 @@ abstract class ImpactBuilder extends StaticTypeVisitor {
} }
} }
void registerThrow();
@override @override
void handleThrow(ir.Throw node) { void handleThrow(ir.Throw node) {
registerThrow(); registerThrow();
} }
void registerSyncForIn(ir.DartType iterableType);
void registerAsyncForIn(ir.DartType iterableType);
@override @override
void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType) { void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType) {
if (node.isAsync) { if (node.isAsync) {
@ -256,12 +378,6 @@ abstract class ImpactBuilder extends StaticTypeVisitor {
} }
} }
void registerCatch();
void registerStackTrace();
void registerCatchType(ir.DartType type);
@override @override
void handleCatch(ir.Catch node) { void handleCatch(ir.Catch node) {
registerCatch(); registerCatch();
@ -273,37 +389,30 @@ abstract class ImpactBuilder extends StaticTypeVisitor {
} }
} }
void registerTypeLiteral(ir.DartType type, ir.LibraryDependency import);
@override @override
void handleTypeLiteral(ir.TypeLiteral node) { void handleTypeLiteral(ir.TypeLiteral node) {
registerTypeLiteral(node.type, getDeferredImport(node)); registerTypeLiteral(node.type, getDeferredImport(node));
} }
void registerFieldInitializer(ir.Field node);
@override @override
void handleFieldInitializer(ir.FieldInitializer node) { void handleFieldInitializer(ir.FieldInitializer node) {
registerFieldInitializer(node.field); registerFieldInitializer(node.field);
} }
void registerLoadLibrary();
@override @override
void handleLoadLibrary(ir.LoadLibrary node) { void handleLoadLibrary(ir.LoadLibrary node) {
registerLoadLibrary(); registerLoadLibrary();
} }
void registerRedirectingInitializer(
ir.Constructor constructor, ir.Arguments arguments);
void handleRedirectingInitializer( void handleRedirectingInitializer(
ir.RedirectingInitializer node, ArgumentTypes argumentTypes) { 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 @override
void handleParameter(ir.VariableDeclaration parameter) { void handleParameter(ir.VariableDeclaration parameter) {
registerParameterCheck(parameter.type); registerParameterCheck(parameter.type);
@ -316,7 +425,10 @@ abstract class ImpactBuilder extends StaticTypeVisitor {
} }
} }
void registerLazyField(); @override
void handleConstructor(ir.Constructor node) {
registerConstructorNode(node);
}
@override @override
void handleField(ir.Field field) { void handleField(ir.Field field) {
@ -330,31 +442,37 @@ abstract class ImpactBuilder extends StaticTypeVisitor {
} else { } else {
registerNullLiteral(); registerNullLiteral();
} }
registerFieldNode(field);
} }
@override @override
void handleProcedure(ir.Procedure procedure) { void handleProcedure(ir.Procedure procedure) {
handleAsyncMarker(procedure.function); handleAsyncMarker(procedure.function);
registerProcedureNode(procedure);
} }
void registerNew(ir.Member constructor, ir.InterfaceType type,
ir.Arguments arguments, ir.LibraryDependency import,
{bool isConst});
@override @override
void handleConstructorInvocation(ir.ConstructorInvocation node, void handleConstructorInvocation(ir.ConstructorInvocation node,
ArgumentTypes argumentTypes, ir.DartType resultType) { 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), getDeferredImport(node),
isConst: node.isConst); isConst: node.isConst);
if (node.isConst) {
registerConstConstructorInvocationNode(node);
}
} }
void registerStaticInvocation(
ir.Procedure target, ir.Arguments arguments, ir.LibraryDependency import);
@override @override
void handleStaticInvocation(ir.StaticInvocation node, void handleStaticInvocation(ir.StaticInvocation node,
ArgumentTypes argumentTypes, ir.DartType returnType) { ArgumentTypes argumentTypes, ir.DartType returnType) {
int positionArguments = node.arguments.positional.length;
List<String> namedArguments = _getNamedArguments(node.arguments);
List<ir.DartType> typeArguments = node.arguments.types;
if (node.target.kind == ir.ProcedureKind.Factory) { if (node.target.kind == ir.ProcedureKind.Factory) {
// TODO(johnniwinther): We should not mark the type as instantiated but // TODO(johnniwinther): We should not mark the type as instantiated but
// rather follow the type arguments directly. // rather follow the type arguments directly.
@ -380,65 +498,60 @@ abstract class ImpactBuilder extends StaticTypeVisitor {
// instantiated as int and String. // instantiated as int and String.
registerNew( registerNew(
node.target, node.target,
new ir.InterfaceType( new ir.InterfaceType(node.target.enclosingClass, typeArguments),
node.target.enclosingClass, node.arguments.types), positionArguments,
node.arguments, namedArguments,
node.arguments.types,
getDeferredImport(node), getDeferredImport(node),
isConst: node.isConst); isConst: node.isConst);
} else { } else {
registerStaticInvocation( registerStaticInvocation(node.target, positionArguments, namedArguments,
node.target, node.arguments, getDeferredImport(node)); 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 @override
void handleMethodInvocation( void handleMethodInvocation(
ir.MethodInvocation node, ir.MethodInvocation node,
ir.DartType receiverType, ir.DartType receiverType,
ArgumentTypes argumentTypes, ArgumentTypes argumentTypes,
ir.DartType returnType) { ir.DartType returnType) {
int positionArguments = node.arguments.positional.length;
List<String> namedArguments = _getNamedArguments(node.arguments);
List<ir.DartType> typeArguments = node.arguments.types;
ir.Expression receiver = node.receiver; ir.Expression receiver = node.receiver;
if (receiver is ir.VariableGet && if (receiver is ir.VariableGet &&
receiver.variable.isFinal && receiver.variable.isFinal &&
receiver.variable.parent is ir.FunctionDeclaration) { receiver.variable.parent is ir.FunctionDeclaration) {
registerLocalFunctionInvocation(receiver.variable.parent, node.arguments); registerLocalFunctionInvocation(receiver.variable.parent,
positionArguments, namedArguments, typeArguments);
} else { } else {
ClassRelation relation = _computeClassRelationFromType(receiverType); ClassRelation relation = _computeClassRelationFromType(receiverType);
ir.Member interfaceTarget = node.interfaceTarget; ir.Member interfaceTarget = node.interfaceTarget;
if (interfaceTarget == null) { if (interfaceTarget == null) {
registerDynamicInvocation( registerDynamicInvocation(receiverType, relation, node.name,
receiverType, relation, node.name, node.arguments); positionArguments, namedArguments, typeArguments);
// TODO(johnniwinther): Avoid treating a known function call as a // TODO(johnniwinther): Avoid treating a known function call as a
// dynamic call when CFE provides a way to distinguish the two. // dynamic call when CFE provides a way to distinguish the two.
if (operatorFromString(node.name.name) == null && if (operatorFromString(node.name.name) == null &&
receiverType is ir.DynamicType) { receiverType is ir.DynamicType) {
// We might implicitly call a getter that returns a function. // We might implicitly call a getter that returns a function.
registerFunctionInvocation(const ir.DynamicType(), node.arguments); registerFunctionInvocation(const ir.DynamicType(), positionArguments,
namedArguments, typeArguments);
} }
} else { } else {
if (interfaceTarget is ir.Field || if (interfaceTarget is ir.Field ||
interfaceTarget is ir.Procedure && interfaceTarget is ir.Procedure &&
interfaceTarget.kind == ir.ProcedureKind.Getter) { interfaceTarget.kind == ir.ProcedureKind.Getter) {
registerInstanceInvocation( registerInstanceInvocation(receiverType, relation, interfaceTarget,
receiverType, relation, interfaceTarget, node.arguments); positionArguments, namedArguments, typeArguments);
registerFunctionInvocation( registerFunctionInvocation(interfaceTarget.getterType,
interfaceTarget.getterType, node.arguments); positionArguments, namedArguments, typeArguments);
} else { } else {
registerInstanceInvocation( registerInstanceInvocation(receiverType, relation, interfaceTarget,
receiverType, relation, interfaceTarget, node.arguments); positionArguments, namedArguments, typeArguments);
} }
} }
} }
@ -451,15 +564,14 @@ abstract class ImpactBuilder extends StaticTypeVisitor {
ArgumentTypes argumentTypes, ArgumentTypes argumentTypes,
ir.DartType returnType) { ir.DartType returnType) {
registerInstanceInvocation( 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 @override
void handlePropertyGet( void handlePropertyGet(
ir.PropertyGet node, ir.DartType receiverType, ir.DartType resultType) { ir.PropertyGet node, ir.DartType receiverType, ir.DartType resultType) {
@ -477,12 +589,6 @@ abstract class ImpactBuilder extends StaticTypeVisitor {
registerInstanceGet(receiverType, ClassRelation.exact, node.target); 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 @override
void handlePropertySet( void handlePropertySet(
ir.PropertySet node, ir.DartType receiverType, ir.DartType valueType) { ir.PropertySet node, ir.DartType receiverType, ir.DartType valueType) {
@ -500,35 +606,59 @@ abstract class ImpactBuilder extends StaticTypeVisitor {
registerInstanceSet(receiverType, ClassRelation.exact, node.target); registerInstanceSet(receiverType, ClassRelation.exact, node.target);
} }
void registerSuperInvocation(ir.Name name, ir.Arguments arguments);
@override @override
void handleSuperMethodInvocation(ir.SuperMethodInvocation node, void handleSuperMethodInvocation(ir.SuperMethodInvocation node,
ArgumentTypes argumentTypes, ir.DartType returnType) { 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 @override
void handleSuperPropertyGet( void handleSuperPropertyGet(
ir.SuperPropertyGet node, ir.DartType resultType) { ir.SuperPropertyGet node, ir.DartType resultType) {
registerSuperGet(node.name); registerSuperGet(node.name);
} }
void registerSuperSet(ir.Name name);
@override @override
void handleSuperPropertySet(ir.SuperPropertySet node, ir.DartType valueType) { void handleSuperPropertySet(ir.SuperPropertySet node, ir.DartType valueType) {
registerSuperSet(node.name); registerSuperSet(node.name);
} }
void registerSuperInitializer(
ir.Constructor source, ir.Constructor target, ir.Arguments arguments);
@override @override
void handleSuperInitializer( void handleSuperInitializer(
ir.SuperInitializer node, ArgumentTypes argumentTypes) { 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<String> _getNamedArguments(ir.Arguments arguments) =>
arguments.named.map((n) => n.name).toList();

File diff suppressed because it is too large Load diff

View file

@ -903,6 +903,15 @@ abstract class StaticTypeVisitor extends StaticTypeBase {
return super.visitListLiteral(node); 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) {} void handleMapLiteral(ir.MapLiteral node) {}
@override @override

View file

@ -128,6 +128,11 @@ abstract class StaticTypeBase extends ir.Visitor<ir.DartType> {
return typeEnvironment.literalListType(node.typeArgument); return typeEnvironment.literalListType(node.typeArgument);
} }
@override
ir.DartType visitSetLiteral(ir.SetLiteral node) {
return typeEnvironment.literalSetType(node.typeArgument);
}
@override @override
ir.DartType visitMapLiteral(ir.MapLiteral node) { ir.DartType visitMapLiteral(ir.MapLiteral node) {
return typeEnvironment.literalMapType(node.keyType, node.valueType); return typeEnvironment.literalMapType(node.keyType, node.valueType);

View file

@ -56,13 +56,10 @@ abstract class KernelToElementMap {
/// Returns the [CallStructure] corresponding to the [arguments]. /// Returns the [CallStructure] corresponding to the [arguments].
CallStructure getCallStructure(ir.Arguments 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 /// Returns the [Selector] corresponding to the invocation of [name] with
/// [arguments]. /// [arguments].
Selector getInvocationSelector(ir.Name name, ir.Arguments arguments); Selector getInvocationSelector(ir.Name name, int positionalArguments,
List<String> namedArguments, int typeArguments);
/// Returns the [MemberEntity] corresponding to the member [node]. /// Returns the [MemberEntity] corresponding to the member [node].
MemberEntity getMember(ir.Member node); MemberEntity getMember(ir.Member node);

View file

@ -30,6 +30,8 @@ import '../environment.dart';
import '../frontend_strategy.dart'; import '../frontend_strategy.dart';
import '../ir/debug.dart'; import '../ir/debug.dart';
import '../ir/element_map.dart'; import '../ir/element_map.dart';
import '../ir/impact.dart';
import '../ir/impact_data.dart';
import '../ir/static_type.dart'; import '../ir/static_type.dart';
import '../ir/scope.dart'; import '../ir/scope.dart';
import '../ir/types.dart'; import '../ir/types.dart';
@ -60,6 +62,11 @@ import 'kernel_impact.dart';
part 'native_basic_data.dart'; part 'native_basic_data.dart';
part 'no_such_method_resolver.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 /// Implementation of [KernelToElementMap] that only supports world
/// impact computation. /// impact computation.
class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap { class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
@ -760,32 +767,8 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
namedParameters, includeTypeParameters ? typeParameters : 0); namedParameters, includeTypeParameters ? typeParameters : 0);
} }
Selector getSelector(ir.Expression node) { Selector getInvocationSelector(ir.Name irName, int positionalArguments,
// TODO(efortuna): This is screaming for a common interface between List<String> namedArguments, int typeArguments) {
// 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) {
Name name = getName(irName); Name name = getName(irName);
SelectorKind kind; SelectorKind kind;
if (Selector.isOperatorName(name.text)) { if (Selector.isOperatorName(name.text)) {
@ -798,7 +781,10 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
kind = SelectorKind.CALL; kind = SelectorKind.CALL;
} }
CallStructure callStructure = getCallStructure(arguments); CallStructure callStructure = new CallStructure(
positionalArguments + namedArguments.length,
namedArguments,
typeArguments);
return new Selector(kind, name, callStructure); return new Selector(kind, name, callStructure);
} }
@ -1339,6 +1325,24 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
Set<PragmaAnnotation> annotations) { Set<PragmaAnnotation> annotations) {
KMemberData memberData = members.getData(member); KMemberData memberData = members.getData(member);
ir.Member node = memberData.node; ir.Member node = memberData.node;
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( KernelImpactBuilder builder = new KernelImpactBuilder(
this, member, reporter, options, variableScopeModel, annotations); this, member, reporter, options, variableScopeModel, annotations);
if (retainDataForTesting) { if (retainDataForTesting) {
@ -1349,6 +1353,7 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
memberData.staticTypes = builder.cachedStaticTypes; memberData.staticTypes = builder.cachedStaticTypes;
return builder.impactBuilder; return builder.impactBuilder;
} }
}
ScopeModel computeScopeModel(KMember member) { ScopeModel computeScopeModel(KMember member) {
ir.Member node = members.getData(member).node; ir.Member node = members.getData(member).node;

View file

@ -3,9 +3,11 @@
// BSD-style license that can be found in the LICENSE file. // BSD-style license that can be found in the LICENSE file.
import 'package:kernel/ast.dart' as ir; import 'package:kernel/ast.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;
import '../common.dart'; import '../common.dart';
import '../common/names.dart'; import '../common/names.dart';
import '../common/resolution.dart';
import '../common_elements.dart'; import '../common_elements.dart';
import '../constants/expressions.dart'; import '../constants/expressions.dart';
import '../constants/values.dart'; import '../constants/values.dart';
@ -15,6 +17,7 @@ import '../ir/runtime_type_analysis.dart';
import '../ir/scope.dart'; import '../ir/scope.dart';
import '../ir/static_type.dart'; import '../ir/static_type.dart';
import '../ir/impact.dart'; import '../ir/impact.dart';
import '../ir/impact_data.dart';
import '../ir/util.dart'; import '../ir/util.dart';
import '../js_backend/annotations.dart'; import '../js_backend/annotations.dart';
import '../js_backend/native_data.dart'; import '../js_backend/native_data.dart';
@ -27,7 +30,9 @@ import '../universe/use.dart';
import '../universe/world_builder.dart'; import '../universe/world_builder.dart';
import 'element_map.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 ResolutionWorldImpactBuilder impactBuilder;
final KernelToElementMap elementMap; final KernelToElementMap elementMap;
final DiagnosticReporter reporter; final DiagnosticReporter reporter;
@ -50,6 +55,47 @@ class KernelImpactBuilder extends ImpactBuilder {
bool get inferEffectivelyFinalVariableTypes => bool get inferEffectivelyFinalVariableTypes =>
!_annotations.contains(PragmaAnnotation.disableFinal); !_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( Object _computeReceiverConstraint(
ir.DartType receiverType, ClassRelation relation) { ir.DartType receiverType, ClassRelation relation) {
@ -72,9 +118,9 @@ class KernelImpactBuilder extends ImpactBuilder {
} }
} }
List<DartType> _getTypeArguments(ir.Arguments arguments) { List<DartType> _getTypeArguments(List<ir.DartType> types) {
if (arguments.types.isEmpty) return null; if (types.isEmpty) return null;
return arguments.types.map(elementMap.getDartType).toList(); return types.map(elementMap.getDartType).toList();
} }
@override @override
@ -83,9 +129,7 @@ class KernelImpactBuilder extends ImpactBuilder {
} }
@override @override
void handleField(ir.Field field) { void registerFieldNode(ir.Field field) {
super.handleField(field);
if (field.isInstanceMember && if (field.isInstanceMember &&
elementMap.isNativeClass(field.enclosingClass)) { elementMap.isNativeClass(field.enclosingClass)) {
MemberEntity member = elementMap.getMember(field); MemberEntity member = elementMap.getMember(field);
@ -98,7 +142,7 @@ class KernelImpactBuilder extends ImpactBuilder {
} }
@override @override
void handleConstructor(ir.Constructor constructor) { void registerConstructorNode(ir.Constructor constructor) {
MemberEntity member = elementMap.getMember(constructor); MemberEntity member = elementMap.getMember(constructor);
if (constructor.isExternal && !commonElements.isForeignHelper(member)) { if (constructor.isExternal && !commonElements.isForeignHelper(member)) {
bool isJsInterop = _nativeBasicData.isJsInteropMember(member); bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
@ -135,9 +179,7 @@ class KernelImpactBuilder extends ImpactBuilder {
} }
@override @override
void handleProcedure(ir.Procedure procedure) { void registerProcedureNode(ir.Procedure procedure) {
super.handleProcedure(procedure);
MemberEntity member = elementMap.getMember(procedure); MemberEntity member = elementMap.getMember(procedure);
if (procedure.isExternal && !commonElements.isForeignHelper(member)) { if (procedure.isExternal && !commonElements.isForeignHelper(member)) {
bool isJsInterop = _nativeBasicData.isJsInteropMember(member); bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
@ -179,29 +221,43 @@ class KernelImpactBuilder extends ImpactBuilder {
@override @override
void registerListLiteral(ir.DartType elementType, void registerListLiteral(ir.DartType elementType,
{bool isConstant, bool isEmpty}) { {bool isConst, bool isEmpty}) {
impactBuilder.registerListLiteral(new ListLiteralUse( impactBuilder.registerListLiteral(new ListLiteralUse(
commonElements.listType(elementMap.getDartType(elementType)), commonElements.listType(elementMap.getDartType(elementType)),
isConstant: isConstant, isConstant: isConst,
isEmpty: isEmpty)); isEmpty: isEmpty));
} }
@override
void registerSetLiteral(ir.DartType elementType,
{bool isConst, bool isEmpty}) {
// TODO(johnniwinther,fishythefish): Register set literals.
}
@override @override
void registerMapLiteral(ir.DartType keyType, ir.DartType valueType, void registerMapLiteral(ir.DartType keyType, ir.DartType valueType,
{bool isConstant, bool isEmpty}) { {bool isConst, bool isEmpty}) {
impactBuilder.registerMapLiteral(new MapLiteralUse( impactBuilder.registerMapLiteral(new MapLiteralUse(
commonElements.mapType( commonElements.mapType(
elementMap.getDartType(keyType), elementMap.getDartType(valueType)), elementMap.getDartType(keyType), elementMap.getDartType(valueType)),
isConstant: isConstant, isConstant: isConst,
isEmpty: isEmpty)); isEmpty: isEmpty));
} }
@override @override
void registerNew(ir.Member target, ir.InterfaceType type, void registerNew(
ir.Arguments arguments, ir.LibraryDependency import, ir.Member target,
ir.InterfaceType type,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments,
ir.LibraryDependency import,
{bool isConst}) { {bool isConst}) {
ConstructorEntity constructor = elementMap.getConstructor(target); 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); ImportEntity deferredImport = elementMap.getImport(import);
impactBuilder.registerStaticUse(isConst impactBuilder.registerStaticUse(isConst
? new StaticUse.constConstructorInvoke(constructor, callStructure, ? 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 // We need to register the external constructor as live below, so don't
// return here. // 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 = ConstantValue value =
elementMap.getConstantValue(arguments.positional.first); elementMap.getConstantValue(node.arguments.positional.first);
if (!value.isString) { if (!value.isString) {
// TODO(het): Get the actual span for the Symbol constructor argument // TODO(het): Get the actual span for the Symbol constructor argument
reporter.reportErrorMessage( reporter.reportErrorMessage(
@ -242,7 +302,11 @@ class KernelImpactBuilder extends ImpactBuilder {
@override @override
void registerSuperInitializer( void registerSuperInitializer(
ir.Constructor source, ir.Constructor target, ir.Arguments arguments) { ir.Constructor source,
ir.Constructor target,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments) {
// TODO(johnniwinther): Maybe rewrite `node.target` to point to a // TODO(johnniwinther): Maybe rewrite `node.target` to point to a
// synthesized unnamed mixin constructor when needed. This would require us // synthesized unnamed mixin constructor when needed. This would require us
// to consider impact building a required pre-step for inference and // to consider impact building a required pre-step for inference and
@ -250,29 +314,36 @@ class KernelImpactBuilder extends ImpactBuilder {
ConstructorEntity constructor = ConstructorEntity constructor =
elementMap.getSuperConstructor(source, target); elementMap.getSuperConstructor(source, target);
impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke( impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke(
constructor, elementMap.getCallStructure(arguments))); constructor,
new CallStructure(positionalArguments + namedArguments.length,
namedArguments, typeArguments.length)));
} }
@override @override
void registerStaticInvocation(ir.Procedure procedure, ir.Arguments arguments, void registerStaticInvocation(
ir.Procedure procedure,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments,
ir.LibraryDependency import) { ir.LibraryDependency import) {
FunctionEntity target = elementMap.getMethod(procedure); FunctionEntity target = elementMap.getMethod(procedure);
CallStructure callStructure = elementMap.getCallStructure(arguments); CallStructure callStructure = new CallStructure(
List<DartType> typeArguments = _getTypeArguments(arguments); positionalArguments + namedArguments.length,
namedArguments,
typeArguments.length);
List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
if (commonElements.isExtractTypeArguments(target)) { if (commonElements.isExtractTypeArguments(target)) {
_handleExtractTypeArguments(target, typeArguments, callStructure); _handleExtractTypeArguments(target, dartTypeArguments, callStructure);
return; return;
} else { } else {
ImportEntity deferredImport = elementMap.getImport(import); ImportEntity deferredImport = elementMap.getImport(import);
impactBuilder.registerStaticUse(new StaticUse.staticInvoke( impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
target, callStructure, typeArguments, deferredImport)); target, callStructure, dartTypeArguments, deferredImport));
} }
} }
void handleStaticInvocation(ir.StaticInvocation node, @override
ArgumentTypes argumentTypes, ir.DartType returnType) { void registerStaticInvocationNode(ir.StaticInvocation node) {
super.handleStaticInvocation(node, argumentTypes, returnType);
switch (elementMap.getForeignKind(node)) { switch (elementMap.getForeignKind(node)) {
case ForeignKind.JS: case ForeignKind.JS:
impactBuilder impactBuilder
@ -346,13 +417,17 @@ class KernelImpactBuilder extends ImpactBuilder {
} }
@override @override
void registerSuperInvocation(ir.Name name, ir.Arguments arguments) { void registerSuperInvocation(ir.Name name, int positionalArguments,
List<String> namedArguments, List<ir.DartType> typeArguments) {
FunctionEntity method = FunctionEntity method =
elementMap.getSuperMember(currentMember, name, setter: false); elementMap.getSuperMember(currentMember, name, setter: false);
List<DartType> typeArguments = _getTypeArguments(arguments); List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
if (method != null) { if (method != null) {
impactBuilder.registerStaticUse(new StaticUse.superInvoke( impactBuilder.registerStaticUse(new StaticUse.superInvoke(
method, elementMap.getCallStructure(arguments), typeArguments)); method,
new CallStructure(positionalArguments + namedArguments.length,
namedArguments, typeArguments.length),
dartTypeArguments));
} else { } else {
impactBuilder.registerStaticUse(new StaticUse.superInvoke( impactBuilder.registerStaticUse(new StaticUse.superInvoke(
elementMap.getSuperNoSuchMethod(currentMember.enclosingClass), elementMap.getSuperNoSuchMethod(currentMember.enclosingClass),
@ -399,50 +474,74 @@ class KernelImpactBuilder extends ImpactBuilder {
@override @override
void registerLocalFunctionInvocation( void registerLocalFunctionInvocation(
ir.FunctionDeclaration localFunction, ir.Arguments arguments) { ir.FunctionDeclaration localFunction,
CallStructure callStructure = elementMap.getCallStructure(arguments); int positionalArguments,
List<DartType> typeArguments = _getTypeArguments(arguments); List<String> namedArguments,
List<ir.DartType> typeArguments) {
CallStructure callStructure = new CallStructure(
positionalArguments + namedArguments.length,
namedArguments,
typeArguments.length);
List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
// Invocation of a local function. No need for dynamic use, but // Invocation of a local function. No need for dynamic use, but
// we need to track the type arguments. // we need to track the type arguments.
impactBuilder.registerStaticUse(new StaticUse.closureCall( impactBuilder.registerStaticUse(new StaticUse.closureCall(
elementMap.getLocalFunction(localFunction), elementMap.getLocalFunction(localFunction),
callStructure, callStructure,
typeArguments)); dartTypeArguments));
// TODO(johnniwinther): Yet, alas, we need the dynamic use for now. Remove // TODO(johnniwinther): Yet, alas, we need the dynamic use for now. Remove
// this when kernel adds an `isFunctionCall` flag to // this when kernel adds an `isFunctionCall` flag to
// [ir.MethodInvocation]. // [ir.MethodInvocation].
impactBuilder.registerDynamicUse(new ConstrainedDynamicUse( impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
callStructure.callSelector, null, typeArguments)); callStructure.callSelector, null, dartTypeArguments));
} }
@override @override
void registerDynamicInvocation(ir.DartType receiverType, void registerDynamicInvocation(
ClassRelation relation, ir.Name name, ir.Arguments arguments) { ir.DartType receiverType,
Selector selector = elementMap.getInvocationSelector(name, arguments); ClassRelation relation,
List<DartType> typeArguments = _getTypeArguments(arguments); ir.Name name,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments) {
Selector selector = elementMap.getInvocationSelector(
name, positionalArguments, namedArguments, typeArguments.length);
List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(selector, impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(selector,
_computeReceiverConstraint(receiverType, relation), typeArguments)); _computeReceiverConstraint(receiverType, relation), dartTypeArguments));
} }
@override @override
void registerFunctionInvocation( void registerFunctionInvocation(
ir.DartType receiverType, ir.Arguments arguments) { ir.DartType receiverType,
CallStructure callStructure = elementMap.getCallStructure(arguments); int positionalArguments,
List<DartType> typeArguments = _getTypeArguments(arguments); List<String> namedArguments,
List<ir.DartType> typeArguments) {
CallStructure callStructure = new CallStructure(
positionalArguments + namedArguments.length,
namedArguments,
typeArguments.length);
List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
impactBuilder.registerDynamicUse(new ConstrainedDynamicUse( impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
callStructure.callSelector, callStructure.callSelector,
_computeReceiverConstraint(receiverType, ClassRelation.subtype), _computeReceiverConstraint(receiverType, ClassRelation.subtype),
typeArguments)); dartTypeArguments));
} }
@override @override
void registerInstanceInvocation(ir.DartType receiverType, void registerInstanceInvocation(
ClassRelation relation, ir.Member target, ir.Arguments arguments) { ir.DartType receiverType,
List<DartType> typeArguments = _getTypeArguments(arguments); ClassRelation relation,
ir.Member target,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments) {
List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
impactBuilder.registerDynamicUse(new ConstrainedDynamicUse( impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
elementMap.getInvocationSelector(target.name, arguments), elementMap.getInvocationSelector(target.name, positionalArguments,
namedArguments, typeArguments.length),
_computeReceiverConstraint(receiverType, relation), _computeReceiverConstraint(receiverType, relation),
typeArguments)); dartTypeArguments));
} }
@override @override
@ -481,7 +580,8 @@ class KernelImpactBuilder extends ImpactBuilder {
const <DartType>[])); const <DartType>[]));
} }
void handleRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind, @override
void registerRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind,
ir.DartType receiverType, ir.DartType argumentType) { ir.DartType receiverType, ir.DartType argumentType) {
DartType receiverDartType = elementMap.getDartType(receiverType); DartType receiverDartType = elementMap.getDartType(receiverType);
DartType argumentDartType = DartType argumentDartType =
@ -561,7 +661,6 @@ class KernelImpactBuilder extends ImpactBuilder {
.registerTypeUse(new TypeUse.asCast(elementMap.getDartType(type))); .registerTypeUse(new TypeUse.asCast(elementMap.getDartType(type)));
} }
@override
@override @override
void registerThrow() { void registerThrow() {
impactBuilder.registerFeature(Feature.THROW_EXPRESSION); impactBuilder.registerFeature(Feature.THROW_EXPRESSION);
@ -619,10 +718,15 @@ class KernelImpactBuilder extends ImpactBuilder {
@override @override
void registerRedirectingInitializer( void registerRedirectingInitializer(
ir.Constructor constructor, ir.Arguments arguments) { ir.Constructor constructor,
int positionalArguments,
List<String> namedArguments,
List<ir.DartType> typeArguments) {
ConstructorEntity target = elementMap.getConstructor(constructor); ConstructorEntity target = elementMap.getConstructor(constructor);
impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke( impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke(
target, elementMap.getCallStructure(arguments))); target,
new CallStructure(positionalArguments + namedArguments.length,
namedArguments, typeArguments.length)));
} }
@override @override
@ -633,7 +737,7 @@ class KernelImpactBuilder extends ImpactBuilder {
} }
@override @override
void handleSwitchStatement(ir.SwitchStatement node) { void registerSwitchStatementNode(ir.SwitchStatement node) {
// TODO(32557): Remove this when issue 32557 is fixed. // TODO(32557): Remove this when issue 32557 is fixed.
ir.TreeNode firstCase; ir.TreeNode firstCase;
DartType firstCaseType; DartType firstCaseType;

View file

@ -203,7 +203,7 @@ abstract class AbstractDataSink extends DataSinkMixin implements DataSink {
void writeInt(int value) { void writeInt(int value) {
assert(value != null); assert(value != null);
assert(value >= 0 && value >> 30 == 0); assert(value >= 0 && value >> 30 == 0);
_writeDataKind(DataKind.int); _writeDataKind(DataKind.uint30);
_writeIntInternal(value); _writeIntInternal(value);
} }
@ -338,6 +338,31 @@ abstract class AbstractDataSink extends DataSinkMixin implements DataSink {
_writeConstant(value); _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) { void _writeConstant(ConstantValue value) {
_writeEnumInternal(value.kind); _writeEnumInternal(value.kind);
switch (value.kind) { switch (value.kind) {
@ -347,16 +372,11 @@ abstract class AbstractDataSink extends DataSinkMixin implements DataSink {
break; break;
case ConstantValueKind.INT: case ConstantValueKind.INT:
IntConstantValue constant = value; IntConstantValue constant = value;
writeString(constant.intValue.toString()); _writeBigInt(constant.intValue);
break; break;
case ConstantValueKind.DOUBLE: case ConstantValueKind.DOUBLE:
DoubleConstantValue constant = value; DoubleConstantValue constant = value;
ByteData data = new ByteData(8); _writeDoubleValue(constant.doubleValue);
data.setFloat64(0, constant.doubleValue);
writeInt(data.getUint16(0));
writeInt(data.getUint16(2));
writeInt(data.getUint16(4));
writeInt(data.getUint16(6));
break; break;
case ConstantValueKind.STRING: case ConstantValueKind.STRING:
StringConstantValue constant = value; StringConstantValue constant = value;

View file

@ -393,7 +393,7 @@ abstract class AbstractDataSource extends DataSourceMixin
@override @override
int readInt() { int readInt() {
_checkDataKind(DataKind.int); _checkDataKind(DataKind.uint30);
return _readIntInternal(); return _readIntInternal();
} }
@ -409,6 +409,29 @@ abstract class AbstractDataSource extends DataSourceMixin
return _readConstant(); 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() { ConstantValue _readConstant() {
ConstantValueKind kind = _readEnumInternal(ConstantValueKind.values); ConstantValueKind kind = _readEnumInternal(ConstantValueKind.values);
switch (kind) { switch (kind) {
@ -416,15 +439,10 @@ abstract class AbstractDataSource extends DataSourceMixin
bool value = readBool(); bool value = readBool();
return new BoolConstantValue(value); return new BoolConstantValue(value);
case ConstantValueKind.INT: case ConstantValueKind.INT:
BigInt value = BigInt.parse(readString()); BigInt value = _readBigInt();
return new IntConstantValue(value); return new IntConstantValue(value);
case ConstantValueKind.DOUBLE: case ConstantValueKind.DOUBLE:
ByteData data = new ByteData(8); double value = _readDoubleValue();
data.setUint16(0, readInt());
data.setUint16(2, readInt());
data.setUint16(4, readInt());
data.setUint16(6, readInt());
double value = data.getFloat64(0);
return new DoubleConstantValue(value); return new DoubleConstantValue(value);
case ConstantValueKind.STRING: case ConstantValueKind.STRING:
String value = readString(); String value = readString();

View file

@ -10,7 +10,7 @@ part of 'serialization.dart';
/// and deserialization. /// and deserialization.
enum DataKind { enum DataKind {
bool, bool,
int, uint30,
string, string,
enumValue, enumValue,
uri, uri,
@ -25,6 +25,8 @@ enum DataKind {
sourceSpan, sourceSpan,
constant, constant,
import, import,
double,
int,
} }
/// Enum used for identifying the enclosing entity of a member in serialization. /// Enum used for identifying the enclosing entity of a member in serialization.

View file

@ -313,6 +313,36 @@ abstract class DataSourceMixin implements DataSource {
} }
return map; return map;
} }
@override
List<ir.DartType> readDartTypeNodes({bool emptyAsNull: false}) {
int count = readInt();
if (count == 0 && emptyAsNull) return null;
List<ir.DartType> list = new List<ir.DartType>(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]. /// Mixin that implements all convenience methods of [DataSink].
@ -643,4 +673,36 @@ abstract class DataSinkMixin implements DataSink {
}); });
} }
} }
@override
void writeDartTypeNodes(Iterable<ir.DartType> 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);
}
} }

View file

@ -75,7 +75,7 @@ abstract class DataSink {
/// Writes the boolean [value] to this data sink. /// Writes the boolean [value] to this data sink.
void writeBool(bool value); 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); void writeInt(int value);
/// Writes the potentially `null` non-negative [value] to this data sink. /// Writes the potentially `null` non-negative [value] to this data sink.
@ -137,6 +137,16 @@ abstract class DataSink {
/// [DataSource.readMemberNodes]. /// [DataSource.readMemberNodes].
void writeMemberNodes(Iterable<ir.Member> values, {bool allowNull: false}); void writeMemberNodes(Iterable<ir.Member> 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. /// Writes a reference to the kernel tree node [value] to this data sink.
void writeTreeNode(ir.TreeNode value); void writeTreeNode(ir.TreeNode value);
@ -191,6 +201,14 @@ abstract class DataSink {
/// `true`, [value] is allowed to be `null`. /// `true`, [value] is allowed to be `null`.
void writeDartTypeNode(ir.DartType value, {bool allowNull: false}); 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<ir.DartType> values,
{bool allowNull: false});
/// Writes the source span [value] to this data sink. /// Writes the source span [value] to this data sink.
void writeSourceSpan(SourceSpan value); void writeSourceSpan(SourceSpan value);
@ -313,6 +331,15 @@ abstract class DataSink {
void writeConstantMap<V>(Map<ConstantValue, V> map, void f(V value), void writeConstantMap<V>(Map<ConstantValue, V> map, void f(V value),
{bool allowNull: false}); {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. /// Writes the import [value] to this data sink.
void writeImport(ImportEntity value); void writeImport(ImportEntity value);
@ -380,7 +407,7 @@ abstract class DataSource {
/// Reads a boolean value from this data source. /// Reads a boolean value from this data source.
bool readBool(); 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(); int readInt();
/// Reads a potentially `null` non-negative integer value from this data /// Reads a potentially `null` non-negative integer value from this data
@ -448,6 +475,16 @@ abstract class DataSource {
List<ir.Member> readMemberNodes<E extends ir.Member>( List<ir.Member> readMemberNodes<E extends ir.Member>(
{bool emptyAsNull: false}); {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. /// Reads a reference to a kernel tree node from this data source.
ir.TreeNode readTreeNode(); ir.TreeNode readTreeNode();
@ -497,6 +534,13 @@ abstract class DataSource {
/// returned type is allowed to be `null`. /// returned type is allowed to be `null`.
ir.DartType readDartTypeNode({bool allowNull: false}); 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<ir.DartType> readDartTypeNodes({bool emptyAsNull: false});
/// Reads a source span from this data source. /// Reads a source span from this data source.
SourceSpan readSourceSpan(); SourceSpan readSourceSpan();
@ -582,6 +626,15 @@ abstract class DataSource {
/// Reads a constant value from this data source. /// Reads a constant value from this data source.
ConstantValue readConstant(); 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 /// Reads a list of constant values from this data source. If [emptyAsNull] is
/// `true`, `null` is returned instead of an empty list. /// `true`, `null` is returned instead of an empty list.
/// ///

View file

@ -9,6 +9,7 @@ import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/entities.dart'; import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/ir/util.dart'; import 'package:compiler/src/ir/util.dart';
import 'package:compiler/src/kernel/kernel_strategy.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/feature.dart';
import 'package:compiler/src/universe/use.dart'; import 'package:compiler/src/universe/use.dart';
import 'package:compiler/src/universe/world_impact.dart'; import 'package:compiler/src/universe/world_impact.dart';
@ -20,6 +21,15 @@ import '../equivalence/id_equivalence_helper.dart';
main(List<String> args) { main(List<String> args) {
asyncTest(() async { asyncTest(() async {
Directory dataDir = new Directory.fromUri(Platform.script.resolve('data')); 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(), await checkTests(dataDir, const ImpactDataComputer(),
args: args, testOmit: false, testFrontend: true); args: args, testOmit: false, testFrontend: true);
}); });