mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
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:
parent
52f5e34dbf
commit
60527d7b97
13 changed files with 2212 additions and 252 deletions
|
@ -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<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;
|
||||
|
||||
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<ir.DartType> 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<String> namedArguments = _getNamedArguments(node.arguments);
|
||||
List<ir.DartType> 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<String> namedArguments = _getNamedArguments(node.arguments);
|
||||
List<ir.DartType> 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<String> _getNamedArguments(ir.Arguments arguments) =>
|
||||
arguments.named.map((n) => n.name).toList();
|
||||
|
|
1545
pkg/compiler/lib/src/ir/impact_data.dart
Normal file
1545
pkg/compiler/lib/src/ir/impact_data.dart
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
|
@ -128,6 +128,11 @@ abstract class StaticTypeBase extends ir.Visitor<ir.DartType> {
|
|||
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);
|
||||
|
|
|
@ -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<String> namedArguments, int typeArguments);
|
||||
|
||||
/// Returns the [MemberEntity] corresponding to the member [node].
|
||||
MemberEntity getMember(ir.Member node);
|
||||
|
|
|
@ -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<String> 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<PragmaAnnotation> 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) {
|
||||
|
|
|
@ -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<DartType> _getTypeArguments(ir.Arguments arguments) {
|
||||
if (arguments.types.isEmpty) return null;
|
||||
return arguments.types.map(elementMap.getDartType).toList();
|
||||
List<DartType> _getTypeArguments(List<ir.DartType> 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<String> namedArguments,
|
||||
List<ir.DartType> 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<String> namedArguments,
|
||||
List<ir.DartType> 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<String> namedArguments,
|
||||
List<ir.DartType> typeArguments,
|
||||
ir.LibraryDependency import) {
|
||||
FunctionEntity target = elementMap.getMethod(procedure);
|
||||
CallStructure callStructure = elementMap.getCallStructure(arguments);
|
||||
List<DartType> typeArguments = _getTypeArguments(arguments);
|
||||
CallStructure callStructure = new CallStructure(
|
||||
positionalArguments + namedArguments.length,
|
||||
namedArguments,
|
||||
typeArguments.length);
|
||||
List<DartType> 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<String> namedArguments, List<ir.DartType> typeArguments) {
|
||||
FunctionEntity method =
|
||||
elementMap.getSuperMember(currentMember, name, setter: false);
|
||||
List<DartType> typeArguments = _getTypeArguments(arguments);
|
||||
List<DartType> 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<DartType> typeArguments = _getTypeArguments(arguments);
|
||||
ir.FunctionDeclaration localFunction,
|
||||
int positionalArguments,
|
||||
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
|
||||
// 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<DartType> typeArguments = _getTypeArguments(arguments);
|
||||
void registerDynamicInvocation(
|
||||
ir.DartType receiverType,
|
||||
ClassRelation relation,
|
||||
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,
|
||||
_computeReceiverConstraint(receiverType, relation), typeArguments));
|
||||
_computeReceiverConstraint(receiverType, relation), dartTypeArguments));
|
||||
}
|
||||
|
||||
@override
|
||||
void registerFunctionInvocation(
|
||||
ir.DartType receiverType, ir.Arguments arguments) {
|
||||
CallStructure callStructure = elementMap.getCallStructure(arguments);
|
||||
List<DartType> typeArguments = _getTypeArguments(arguments);
|
||||
ir.DartType receiverType,
|
||||
int positionalArguments,
|
||||
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(
|
||||
callStructure.callSelector,
|
||||
_computeReceiverConstraint(receiverType, ClassRelation.subtype),
|
||||
typeArguments));
|
||||
dartTypeArguments));
|
||||
}
|
||||
|
||||
@override
|
||||
void registerInstanceInvocation(ir.DartType receiverType,
|
||||
ClassRelation relation, ir.Member target, ir.Arguments arguments) {
|
||||
List<DartType> typeArguments = _getTypeArguments(arguments);
|
||||
void registerInstanceInvocation(
|
||||
ir.DartType receiverType,
|
||||
ClassRelation relation,
|
||||
ir.Member target,
|
||||
int positionalArguments,
|
||||
List<String> namedArguments,
|
||||
List<ir.DartType> typeArguments) {
|
||||
List<DartType> 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 <DartType>[]));
|
||||
}
|
||||
|
||||
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<String> namedArguments,
|
||||
List<ir.DartType> 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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -313,6 +313,36 @@ abstract class DataSourceMixin implements DataSource {
|
|||
}
|
||||
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].
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<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.
|
||||
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<ir.DartType> 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<V>(Map<ConstantValue, V> 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<ir.Member> readMemberNodes<E extends ir.Member>(
|
||||
{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<ir.DartType> 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.
|
||||
///
|
||||
|
|
|
@ -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<String> 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);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue