Support computation of ResolutionImpact through ImpactData based on kernel

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

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

View file

@ -10,15 +10,185 @@ import 'package:kernel/class_hierarchy.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;
import '../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();

File diff suppressed because it is too large Load diff

View file

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

View file

@ -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);

View file

@ -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);

View file

@ -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,6 +1325,24 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
Set<PragmaAnnotation> annotations) {
KMemberData memberData = members.getData(member);
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(
this, member, reporter, options, variableScopeModel, annotations);
if (retainDataForTesting) {
@ -1349,6 +1353,7 @@ class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
memberData.staticTypes = builder.cachedStaticTypes;
return builder.impactBuilder;
}
}
ScopeModel computeScopeModel(KMember member) {
ir.Member node = members.getData(member).node;

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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.

View file

@ -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);
}
}

View file

@ -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.
///

View file

@ -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);
});