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 '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();
|
||||||
|
|
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);
|
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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
///
|
///
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue