Skip to content

Commit 4815671

Browse files
natebiggsCommit Queue
authored and
Commit Queue
committed
[dart2js] Move parameter narrowing from NarrowTypeInformation into field on ParameterTypeInformation.
Change-Id: I1715e47e73c2d45fbe6e4f8bfc9a336224f53bc3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/304161 Reviewed-by: Mayank Patke <[email protected]> Commit-Queue: Nate Biggs <[email protected]>
1 parent a8e7db5 commit 4815671

File tree

4 files changed

+77
-62
lines changed

4 files changed

+77
-62
lines changed

pkg/compiler/lib/src/inferrer/builder.dart

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,8 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation?>
282282
void handleParameter(ir.VariableDeclaration node,
283283
{required bool isOptional}) {
284284
Local local = _localsMap.getLocalVariable(node);
285-
DartType type = _localsMap.getLocalType(_elementMap, local);
286-
_state.updateLocal(_inferrer, _capturedAndBoxed, local,
287-
_inferrer.typeOfParameter(local), type);
285+
_state.setLocal(
286+
_inferrer, _capturedAndBoxed, local, _inferrer.typeOfParameter(local));
288287
if (isOptional) {
289288
TypeInformation type;
290289
if (node.initializer != null) {
@@ -2502,11 +2501,21 @@ class LocalState {
25022501
{isCast = true,
25032502
excludeNull = false,
25042503
excludeLateSentinel = false}) {
2505-
type = inferrer.types.narrowType(type, staticType,
2506-
isCast: isCast,
2507-
excludeNull: excludeNull,
2508-
excludeLateSentinel: excludeLateSentinel);
2504+
setLocal(
2505+
inferrer,
2506+
capturedAndBoxed,
2507+
local,
2508+
inferrer.types.narrowType(type, staticType,
2509+
isCast: isCast,
2510+
excludeNull: excludeNull,
2511+
excludeLateSentinel: excludeLateSentinel));
2512+
}
25092513

2514+
void setLocal(
2515+
InferrerEngine inferrer,
2516+
Map<Local, FieldEntity> capturedAndBoxed,
2517+
Local local,
2518+
TypeInformation type) {
25102519
final field = capturedAndBoxed[local];
25112520
if (field != null) {
25122521
inferrer.recordTypeOfField(field, type);

pkg/compiler/lib/src/inferrer/engine.dart

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -791,21 +791,7 @@ class InferrerEngine {
791791
info.type = info.refine(this);
792792
info.doNotEnqueue = true;
793793
}
794-
for (final user in info.users) {
795-
_workQueue.add(user);
796-
// Virtual parameters that are part of a cycle can end up stuck in
797-
// a refinement pattern that prevents the members of the cycle from
798-
// converging. We avoid this by adding the concrete parameter and
799-
// corresponding narrowing type to the queue before other members of
800-
// the cycle.
801-
if (user is ParameterTypeInformation) {
802-
final concreteParameterType = user.concreteParameterType;
803-
if (concreteParameterType != null) {
804-
_workQueue.add(concreteParameterType);
805-
_workQueue.addAll(concreteParameterType.users);
806-
}
807-
}
808-
}
794+
_workQueue.addAll(info.users);
809795
if (info.hasStableType(this)) {
810796
info.stabilize(this);
811797
}

pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,10 @@ class TypeGraphInferrer implements TypesInferrer {
121121

122122
inferrer.types.forEachParameterType(
123123
(Local parameter, ParameterTypeInformation typeInformation) {
124-
AbstractValue type = typeInformation.type;
124+
// We need to get the correct type based on the parameter's check policy.
125+
// This will be used to determine if the parameter needs a check at the
126+
// beginning of the associated function.
127+
AbstractValue type = typeInformation.checkedType(inferrer);
125128
parameterResults[parameter] = type;
126129
});
127130

pkg/compiler/lib/src/inferrer/type_graph_nodes.dart

Lines changed: 56 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -795,19 +795,26 @@ class ParameterTypeInformation extends ElementTypeInformation {
795795
final Local _parameter;
796796
final AbstractValue _type;
797797
final FunctionEntity _method;
798+
799+
/// The input type is calculated directly from the union of this node's
800+
/// inputs (i.e. the actual arguments for this parameter). When this
801+
/// parameter's static type is not trusted, an implicit check will be added
802+
/// based on this type. [type] on the other hand is the type of this parameter
803+
/// within the function body so it is narrowed using the static type.
804+
AbstractValue _inputType;
798805
bool get _isInstanceMemberParameter =>
799806
_hasFlag(_Flag.isInstanceMemberParameter);
800807
bool get _isClosureParameter => _hasFlag(_Flag.isClosureParameter);
801808
bool get _isInitializingFormal => _hasFlag(_Flag.isInitializingFormal);
802809
bool _isTearOffClosureParameter = false;
803-
TypeInformation? get concreteParameterType =>
804-
_hasFlag(_Flag.isVirtual) ? users.first : null;
810+
bool get _isVirtual => _hasFlag(_Flag.isVirtual);
805811

806812
ParameterTypeInformation.localFunction(super.abstractValueDomain,
807813
super.context, this._parameter, DartType type, this._method)
808814
: _type = abstractValueDomain
809815
.createFromStaticType(type, nullable: true)
810816
.abstractValue,
817+
_inputType = abstractValueDomain.uncomputedType,
811818
super._internal() {
812819
_setFlag(_Flag.isClosureParameter);
813820
}
@@ -822,6 +829,7 @@ class ParameterTypeInformation extends ElementTypeInformation {
822829
: _type = abstractValueDomain
823830
.createFromStaticType(type, nullable: true)
824831
.abstractValue,
832+
_inputType = abstractValueDomain.uncomputedType,
825833
super._internal() {
826834
_setFlagTo(_Flag.isInitializingFormal, isInitializingFormal);
827835
}
@@ -831,6 +839,7 @@ class ParameterTypeInformation extends ElementTypeInformation {
831839
{required bool isVirtual})
832840
: _type =
833841
_createInstanceMemberStaticType(abstractValueDomain, type, _method),
842+
_inputType = abstractValueDomain.uncomputedType,
834843
super._withInputs() {
835844
_setFlag(_Flag.isInstanceMemberParameter);
836845
_setFlagTo(_Flag.isVirtual, isVirtual);
@@ -916,53 +925,61 @@ class ParameterTypeInformation extends ElementTypeInformation {
916925

917926
AbstractValue potentiallyNarrowType(
918927
AbstractValue mask, InferrerEngine inferrer) {
919-
if (inferrer.closedWorld.annotationsData
920-
.getParameterCheckPolicy(method)
921-
.isTrusted) {
922-
// In checked or strong mode we don't trust the types of the arguments
923-
// passed to a parameter. The means that the checking of a parameter is
924-
// based on the actual arguments.
925-
//
926-
// With --trust-type-annotations or --omit-implicit-checks we _do_ trust
927-
// the arguments passed to a parameter - and we never check them.
928-
//
929-
// In all these cases we _do_ trust the static type of a parameter within
930-
// the method itself. For instance:
931-
//
932-
// method(int i) => i;
933-
// main() {
934-
// dynamic f = method;
935-
// f(0); // valid call
936-
// f(''); // invalid call
937-
// }
938-
//
939-
// Here, in all cases, we infer the returned value of `method` to be an
940-
// `int`. In checked and strong mode we infer the parameter of `method` to
941-
// be either `int` or `String` and therefore insert a check at the entry
942-
// of 'method'. With --trust-type-annotations or --omit-implicit-checks we
943-
// (unsoundly) infer the parameter to be `int` and leave the parameter
944-
// unchecked, and `method` will at runtime actually return a `String` from
945-
// the second invocation.
946-
//
947-
// The trusting of the parameter types within the body of the method is
948-
// is done through `LocalsHandler.update` called in
949-
// `KernelTypeGraphBuilder.handleParameter`.
950-
return _narrowType(inferrer.abstractValueDomain, mask, _type);
951-
}
952-
return mask;
928+
return _narrowType(inferrer.abstractValueDomain, mask, _type);
929+
}
930+
931+
AbstractValue checkedType(InferrerEngine inferrer) {
932+
// By default we don't trust the types of the arguments passed to a
933+
// parameter. This means that the checking of a parameter is based on the
934+
// actual arguments.
935+
//
936+
// With --omit-implicit-checks we _do_ trust the arguments passed to a
937+
// parameter - and we never check them.
938+
//
939+
// In all these cases we _do_ trust the static type of a parameter within
940+
// the method itself. For instance:
941+
//
942+
// method(int i) => i;
943+
// main() {
944+
// dynamic f = method;
945+
// f(0); // valid call
946+
// f(''); // invalid call
947+
// }
948+
//
949+
// Here, in all cases, we infer the returned value of `method` to be an
950+
// `int`. By default we infer the parameter of `method` to be either
951+
// `int` or `String` and therefore insert a check at the entry of 'method'.
952+
// With --omit-implicit-checks we (unsoundly) infer the parameter to be
953+
// `int` and leave the parameter unchecked, and `method` will at runtime
954+
// actually return a `String` from the second invocation.
955+
//
956+
// The trusting of the parameter types within the body of the method is
957+
// handled by `potentiallyNarrowType` on each call to `computeType`.
958+
return inferrer.closedWorld.annotationsData
959+
.getParameterCheckPolicy(method)
960+
.isTrusted
961+
? type
962+
: _inputType;
953963
}
954964

955965
@override
956966
AbstractValue computeType(InferrerEngine inferrer) {
957967
final special = handleSpecialCases(inferrer);
958968
if (special != null) return special;
959-
return potentiallyNarrowType(
960-
inferrer.types.computeTypeMask(inputs), inferrer);
969+
final inputType = _inputType = inferrer.types.computeTypeMask(inputs);
970+
// Virtual parameters are only inputs to other parameters (virtual or
971+
// concrete) and not function bodies. The user parameters need to know the
972+
// full set of inputs passed to the virtual parameter.
973+
return _isVirtual ? inputType : potentiallyNarrowType(inputType, inferrer);
961974
}
962975

963976
@override
964977
AbstractValue safeType(InferrerEngine inferrer) {
965-
return potentiallyNarrowType(super.safeType(inferrer), inferrer);
978+
final inputType = _inputType = super.safeType(inferrer);
979+
// Virtual parameters are only inputs to other parameters (virtual or
980+
// concrete) and not function bodies. The user parameters need to know the
981+
// full set of inputs passed to the virtual parameter.
982+
return _isVirtual ? inputType : potentiallyNarrowType(inputType, inferrer);
966983
}
967984

968985
@override

0 commit comments

Comments
 (0)