mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 14:59:41 +00:00
Use AbstractValue in KernelToTypeInferenceMap and KernelTypeGraphBuilder
Change-Id: I0af69d10223364256852248228cdbbcbca3f83fa Reviewed-on: https://dart-review.googlesource.com/56484 Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
parent
032925c4ff
commit
aecf8e8dc4
|
@ -18,7 +18,7 @@ import '../kernel/element_map.dart';
|
|||
import '../native/behavior.dart';
|
||||
import '../options.dart';
|
||||
import '../types/constants.dart';
|
||||
import '../types/masks.dart';
|
||||
import '../types/abstract_value_domain.dart';
|
||||
import '../types/types.dart';
|
||||
import '../universe/selector.dart';
|
||||
import '../universe/side_effects.dart';
|
||||
|
@ -125,7 +125,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
/// If an instance field matched with a [selector] that is _not_ a setter, the
|
||||
/// field is considered to have been read before initialization and the field
|
||||
/// is assumed to be potentially `null`.
|
||||
void _checkIfExposesThis(Selector selector, TypeMask mask) {
|
||||
void _checkIfExposesThis(Selector selector, AbstractValue mask) {
|
||||
if (_isThisExposed) {
|
||||
// We already consider `this` to have been exposed.
|
||||
return;
|
||||
|
@ -296,7 +296,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
ArgumentsTypes arguments = analyzeArguments(node.arguments);
|
||||
Selector selector = new Selector(SelectorKind.CALL, constructor.memberName,
|
||||
_elementMap.getCallStructure(node.arguments));
|
||||
TypeMask mask = _memberData.typeOfSend(node);
|
||||
AbstractValue mask = _memberData.typeOfSend(node);
|
||||
handleConstructorInvoke(
|
||||
node, node.arguments, selector, mask, constructor, arguments);
|
||||
|
||||
|
@ -312,7 +312,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
ArgumentsTypes arguments = analyzeArguments(node.arguments);
|
||||
Selector selector = new Selector(SelectorKind.CALL, constructor.memberName,
|
||||
_elementMap.getCallStructure(node.arguments));
|
||||
TypeMask mask = _memberData.typeOfSend(node);
|
||||
AbstractValue mask = _memberData.typeOfSend(node);
|
||||
handleConstructorInvoke(
|
||||
node, node.arguments, selector, mask, constructor, arguments);
|
||||
|
||||
|
@ -725,7 +725,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
@override
|
||||
TypeInformation visitMethodInvocation(ir.MethodInvocation node) {
|
||||
Selector selector = _elementMap.getSelector(node);
|
||||
TypeMask mask = _memberData.typeOfSend(node);
|
||||
AbstractValue mask = _memberData.typeOfSend(node);
|
||||
|
||||
ir.TreeNode receiver = node.receiver;
|
||||
if (receiver is ir.VariableGet &&
|
||||
|
@ -767,7 +767,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
CallType callType,
|
||||
ir.Node node,
|
||||
Selector selector,
|
||||
TypeMask mask,
|
||||
AbstractValue mask,
|
||||
TypeInformation receiverType,
|
||||
ArgumentsTypes arguments) {
|
||||
assert(receiverType != null);
|
||||
|
@ -811,13 +811,17 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
}
|
||||
|
||||
TypeInformation handleDynamicGet(ir.Node node, Selector selector,
|
||||
TypeMask mask, TypeInformation receiverType) {
|
||||
AbstractValue mask, TypeInformation receiverType) {
|
||||
return _handleDynamic(
|
||||
CallType.access, node, selector, mask, receiverType, null);
|
||||
}
|
||||
|
||||
TypeInformation handleDynamicSet(ir.Node node, Selector selector,
|
||||
TypeMask mask, TypeInformation receiverType, TypeInformation rhsType) {
|
||||
TypeInformation handleDynamicSet(
|
||||
ir.Node node,
|
||||
Selector selector,
|
||||
AbstractValue mask,
|
||||
TypeInformation receiverType,
|
||||
TypeInformation rhsType) {
|
||||
ArgumentsTypes arguments = new ArgumentsTypes([rhsType], null);
|
||||
return _handleDynamic(
|
||||
CallType.access, node, selector, mask, receiverType, arguments);
|
||||
|
@ -827,7 +831,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
CallType callType,
|
||||
ir.Node node,
|
||||
Selector selector,
|
||||
TypeMask mask,
|
||||
AbstractValue mask,
|
||||
TypeInformation receiverType,
|
||||
ArgumentsTypes arguments) {
|
||||
return _handleDynamic(
|
||||
|
@ -896,8 +900,8 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
_markThisAsExposed();
|
||||
}
|
||||
|
||||
TypeMask currentMask;
|
||||
TypeMask moveNextMask;
|
||||
AbstractValue currentMask;
|
||||
AbstractValue moveNextMask;
|
||||
TypeInformation iteratorType;
|
||||
if (node.isAsync) {
|
||||
TypeInformation expressionType = visit(node.iterable);
|
||||
|
@ -914,7 +918,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
} else {
|
||||
TypeInformation expressionType = visit(node.iterable);
|
||||
Selector iteratorSelector = Selectors.iterator;
|
||||
TypeMask iteratorMask = _memberData.typeOfIterator(node);
|
||||
AbstractValue iteratorMask = _memberData.typeOfIterator(node);
|
||||
currentMask = _memberData.typeOfIteratorCurrent(node);
|
||||
moveNextMask = _memberData.typeOfIteratorMoveNext(node);
|
||||
|
||||
|
@ -998,7 +1002,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
ConstructorEntity constructor = _elementMap.getConstructor(node.target);
|
||||
ArgumentsTypes arguments = analyzeArguments(node.arguments);
|
||||
Selector selector = _elementMap.getSelector(node);
|
||||
TypeMask mask = _memberData.typeOfSend(node);
|
||||
AbstractValue mask = _memberData.typeOfSend(node);
|
||||
return handleConstructorInvoke(
|
||||
node, node.arguments, selector, mask, constructor, arguments);
|
||||
}
|
||||
|
@ -1038,7 +1042,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
ir.Node node,
|
||||
ir.Arguments arguments,
|
||||
Selector selector,
|
||||
TypeMask mask,
|
||||
AbstractValue mask,
|
||||
ConstructorEntity constructor,
|
||||
ArgumentsTypes argumentsTypes) {
|
||||
TypeInformation returnType =
|
||||
|
@ -1089,13 +1093,13 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
}
|
||||
|
||||
TypeInformation handleStaticInvoke(ir.Node node, Selector selector,
|
||||
TypeMask mask, MemberEntity element, ArgumentsTypes arguments) {
|
||||
AbstractValue mask, MemberEntity element, ArgumentsTypes arguments) {
|
||||
return _inferrer.registerCalledMember(node, selector, mask, _analyzedMember,
|
||||
element, arguments, _sideEffectsBuilder, inLoop);
|
||||
}
|
||||
|
||||
TypeInformation handleClosureCall(ir.Node node, Selector selector,
|
||||
TypeMask mask, MemberEntity member, ArgumentsTypes arguments) {
|
||||
AbstractValue mask, MemberEntity member, ArgumentsTypes arguments) {
|
||||
return _inferrer.registerCalledClosure(
|
||||
node,
|
||||
selector,
|
||||
|
@ -1112,7 +1116,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
FunctionEntity function,
|
||||
ArgumentsTypes arguments,
|
||||
Selector selector,
|
||||
TypeMask mask) {
|
||||
AbstractValue mask) {
|
||||
String name = function.name;
|
||||
handleStaticInvoke(node, selector, mask, function, arguments);
|
||||
if (name == JavaScriptBackend.JS) {
|
||||
|
@ -1143,7 +1147,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
MemberEntity member = _elementMap.getMember(node.target);
|
||||
ArgumentsTypes arguments = analyzeArguments(node.arguments);
|
||||
Selector selector = _elementMap.getSelector(node);
|
||||
TypeMask mask = _memberData.typeOfSend(node);
|
||||
AbstractValue mask = _memberData.typeOfSend(node);
|
||||
if (_closedWorld.commonElements.isForeign(member)) {
|
||||
return handleForeignInvoke(node, member, arguments, selector, mask);
|
||||
} else if (member.isConstructor) {
|
||||
|
@ -1165,7 +1169,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
@override
|
||||
TypeInformation visitStaticGet(ir.StaticGet node) {
|
||||
MemberEntity member = _elementMap.getMember(node.target);
|
||||
TypeMask mask = _memberData.typeOfSend(node);
|
||||
AbstractValue mask = _memberData.typeOfSend(node);
|
||||
return handleStaticInvoke(
|
||||
node, new Selector.getter(member.memberName), mask, member, null);
|
||||
}
|
||||
|
@ -1177,7 +1181,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
_markThisAsExposed();
|
||||
}
|
||||
MemberEntity member = _elementMap.getMember(node.target);
|
||||
TypeMask mask = _memberData.typeOfSend(node);
|
||||
AbstractValue mask = _memberData.typeOfSend(node);
|
||||
handleStaticInvoke(node, new Selector.setter(member.memberName), mask,
|
||||
member, new ArgumentsTypes([rhsType], null));
|
||||
return rhsType;
|
||||
|
@ -1187,7 +1191,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
TypeInformation visitPropertyGet(ir.PropertyGet node) {
|
||||
TypeInformation receiverType = visit(node.receiver);
|
||||
Selector selector = _elementMap.getSelector(node);
|
||||
TypeMask mask = _memberData.typeOfSend(node);
|
||||
AbstractValue mask = _memberData.typeOfSend(node);
|
||||
// TODO(johnniwinther): Use `node.interfaceTarget` to narrow the receiver
|
||||
// type for --trust-type-annotations/strong-mode.
|
||||
if (node.receiver is ir.ThisExpression) {
|
||||
|
@ -1201,7 +1205,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
TypeInformation visitDirectPropertyGet(ir.DirectPropertyGet node) {
|
||||
TypeInformation receiverType = thisType;
|
||||
MemberEntity member = _elementMap.getMember(node.target);
|
||||
TypeMask mask = _memberData.typeOfSend(node);
|
||||
AbstractValue mask = _memberData.typeOfSend(node);
|
||||
// TODO(johnniwinther): Use `node.target` to narrow the receiver type.
|
||||
Selector selector = new Selector.getter(member.memberName);
|
||||
_checkIfExposesThis(selector, _types.newTypedSelector(receiverType, mask));
|
||||
|
@ -1212,7 +1216,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
TypeInformation visitPropertySet(ir.PropertySet node) {
|
||||
TypeInformation receiverType = visit(node.receiver);
|
||||
Selector selector = _elementMap.getSelector(node);
|
||||
TypeMask mask = _memberData.typeOfSend(node);
|
||||
AbstractValue mask = _memberData.typeOfSend(node);
|
||||
|
||||
TypeInformation rhsType = visit(node.value);
|
||||
if (node.value is ir.ThisExpression) {
|
||||
|
@ -1220,7 +1224,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
}
|
||||
|
||||
if (_inGenerativeConstructor && node.receiver is ir.ThisExpression) {
|
||||
TypeMask typedMask = _types.newTypedSelector(receiverType, mask);
|
||||
AbstractValue typedMask = _types.newTypedSelector(receiverType, mask);
|
||||
if (!_closedWorld.includesClosureCall(selector, typedMask)) {
|
||||
Iterable<MemberEntity> targets =
|
||||
_closedWorld.locateMembers(selector, typedMask);
|
||||
|
@ -1608,7 +1612,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
}
|
||||
|
||||
TypeInformation handleSuperNoSuchMethod(ir.Node node, Selector selector,
|
||||
TypeMask mask, ArgumentsTypes arguments) {
|
||||
AbstractValue mask, ArgumentsTypes arguments) {
|
||||
// Ensure we create a node, to make explicit the call to the
|
||||
// `noSuchMethod` handler.
|
||||
FunctionEntity noSuchMethod =
|
||||
|
@ -1624,7 +1628,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
|
||||
MemberEntity member = _elementMap.getSuperMember(
|
||||
_analyzedMember, node.name, node.interfaceTarget);
|
||||
TypeMask mask = _memberData.typeOfSend(node);
|
||||
AbstractValue mask = _memberData.typeOfSend(node);
|
||||
Selector selector = new Selector.getter(_elementMap.getName(node.name));
|
||||
if (member == null) {
|
||||
return handleSuperNoSuchMethod(node, selector, mask, null);
|
||||
|
@ -1643,7 +1647,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
MemberEntity member = _elementMap.getSuperMember(
|
||||
_analyzedMember, node.name, node.interfaceTarget,
|
||||
setter: true);
|
||||
TypeMask mask = _memberData.typeOfSend(node);
|
||||
AbstractValue mask = _memberData.typeOfSend(node);
|
||||
Selector selector = new Selector.setter(_elementMap.getName(node.name));
|
||||
ArgumentsTypes arguments = new ArgumentsTypes([rhsType], null);
|
||||
if (member == null) {
|
||||
|
@ -1664,7 +1668,7 @@ class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> {
|
|||
_analyzedMember, node.name, node.interfaceTarget);
|
||||
ArgumentsTypes arguments = analyzeArguments(node.arguments);
|
||||
Selector selector = _elementMap.getSelector(node);
|
||||
TypeMask mask = _memberData.typeOfSend(node);
|
||||
AbstractValue mask = _memberData.typeOfSend(node);
|
||||
if (member == null) {
|
||||
return handleSuperNoSuchMethod(node, selector, mask, arguments);
|
||||
} else if (member.isFunction) {
|
||||
|
@ -1720,7 +1724,7 @@ class IsCheck {
|
|||
|
||||
class Refinement {
|
||||
final Selector selector;
|
||||
final TypeMask mask;
|
||||
final AbstractValue mask;
|
||||
|
||||
Refinement(this.selector, this.mask);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import '../js_model/closure.dart' show JRecordField, KernelScopeInfo;
|
|||
import '../js_model/elements.dart' show JGeneratorBody;
|
||||
import '../native/native.dart' as native;
|
||||
import '../ssa/type_builder.dart';
|
||||
import '../types/masks.dart';
|
||||
import '../types/abstract_value_domain.dart';
|
||||
import '../universe/call_structure.dart';
|
||||
import '../universe/selector.dart';
|
||||
import '../world.dart';
|
||||
|
@ -369,58 +369,55 @@ enum ForeignKind {
|
|||
/// Interface for type inference results for kernel IR nodes.
|
||||
abstract class KernelToTypeInferenceMap {
|
||||
/// Returns the inferred return type of [function].
|
||||
TypeMask getReturnTypeOf(FunctionEntity function);
|
||||
AbstractValue getReturnTypeOf(FunctionEntity function);
|
||||
|
||||
/// Returns the inferred receiver type of the dynamic [invocation].
|
||||
TypeMask receiverTypeOfInvocation(
|
||||
ir.MethodInvocation invocation, ClosedWorld closedWorld);
|
||||
AbstractValue receiverTypeOfInvocation(
|
||||
ir.MethodInvocation invocation, AbstractValueDomain abstractValueDomain);
|
||||
|
||||
/// Returns the inferred receiver type of the dynamic [read].
|
||||
TypeMask receiverTypeOfGet(ir.PropertyGet read);
|
||||
AbstractValue receiverTypeOfGet(ir.PropertyGet read);
|
||||
|
||||
/// Returns the inferred receiver type of the direct [read].
|
||||
TypeMask receiverTypeOfDirectGet(ir.DirectPropertyGet read);
|
||||
AbstractValue receiverTypeOfDirectGet(ir.DirectPropertyGet read);
|
||||
|
||||
/// Returns the inferred receiver type of the dynamic [write].
|
||||
TypeMask receiverTypeOfSet(ir.PropertySet write, ClosedWorld closedWorld);
|
||||
AbstractValue receiverTypeOfSet(
|
||||
ir.PropertySet write, AbstractValueDomain abstractValueDomain);
|
||||
|
||||
/// Returns the inferred type of [listLiteral].
|
||||
TypeMask typeOfListLiteral(covariant MemberEntity owner,
|
||||
ir.ListLiteral listLiteral, ClosedWorld closedWorld);
|
||||
AbstractValue typeOfListLiteral(MemberEntity owner,
|
||||
ir.ListLiteral listLiteral, AbstractValueDomain abstractValueDomain);
|
||||
|
||||
/// Returns the inferred type of iterator in [forInStatement].
|
||||
TypeMask typeOfIterator(ir.ForInStatement forInStatement);
|
||||
AbstractValue typeOfIterator(ir.ForInStatement forInStatement);
|
||||
|
||||
/// Returns the inferred type of `current` in [forInStatement].
|
||||
TypeMask typeOfIteratorCurrent(ir.ForInStatement forInStatement);
|
||||
AbstractValue typeOfIteratorCurrent(ir.ForInStatement forInStatement);
|
||||
|
||||
/// Returns the inferred type of `moveNext` in [forInStatement].
|
||||
TypeMask typeOfIteratorMoveNext(ir.ForInStatement forInStatement);
|
||||
AbstractValue typeOfIteratorMoveNext(ir.ForInStatement forInStatement);
|
||||
|
||||
/// Returns `true` if [forInStatement] is inferred to be a JavaScript
|
||||
/// indexable iterator.
|
||||
bool isJsIndexableIterator(
|
||||
ir.ForInStatement forInStatement, ClosedWorld closedWorld);
|
||||
|
||||
/// Returns `true` if [mask] is inferred to have a JavaScript `length`
|
||||
/// property.
|
||||
bool isFixedLength(TypeMask mask, ClosedWorld closedWorld);
|
||||
bool isJsIndexableIterator(ir.ForInStatement forInStatement,
|
||||
AbstractValueDomain abstractValueDomain);
|
||||
|
||||
/// Returns the inferred index type of [forInStatement].
|
||||
TypeMask inferredIndexType(ir.ForInStatement forInStatement);
|
||||
AbstractValue inferredIndexType(ir.ForInStatement forInStatement);
|
||||
|
||||
/// Returns the inferred type of [member].
|
||||
TypeMask getInferredTypeOf(MemberEntity member);
|
||||
AbstractValue getInferredTypeOf(MemberEntity member);
|
||||
|
||||
/// Returns the inferred type of the [parameter].
|
||||
TypeMask getInferredTypeOfParameter(Local parameter);
|
||||
AbstractValue getInferredTypeOfParameter(Local parameter);
|
||||
|
||||
/// Returns the inferred type of a dynamic [selector] access on a receiver of
|
||||
/// type [mask].
|
||||
TypeMask selectorTypeOf(Selector selector, TypeMask mask);
|
||||
/// Returns the inferred type of a dynamic [selector] access on the
|
||||
/// [receiver].
|
||||
AbstractValue selectorTypeOf(Selector selector, AbstractValue receiver);
|
||||
|
||||
/// Returns the returned type annotation in the [nativeBehavior].
|
||||
TypeMask typeFromNativeBehavior(
|
||||
AbstractValue typeFromNativeBehavior(
|
||||
native.NativeBehavior nativeBehavior, ClosedWorld closedWorld);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ import '../ssa/builder_kernel.dart';
|
|||
import '../ssa/nodes.dart';
|
||||
import '../ssa/ssa.dart';
|
||||
import '../ssa/types.dart';
|
||||
import '../types/masks.dart';
|
||||
import '../types/abstract_value_domain.dart';
|
||||
import '../types/types.dart';
|
||||
import '../universe/selector.dart';
|
||||
import '../universe/world_impact.dart';
|
||||
|
@ -125,92 +125,74 @@ class KernelToTypeInferenceMapImpl implements KernelToTypeInferenceMap {
|
|||
_globalInferenceResults
|
||||
.resultOfMember(e is ConstructorBodyEntity ? e.constructor : e);
|
||||
|
||||
TypeMask getReturnTypeOf(FunctionEntity function) {
|
||||
AbstractValue getReturnTypeOf(FunctionEntity function) {
|
||||
return TypeMaskFactory.inferredReturnTypeForElement(
|
||||
function, _globalInferenceResults);
|
||||
}
|
||||
|
||||
TypeMask receiverTypeOfInvocation(
|
||||
ir.MethodInvocation node, ClosedWorld closedWorld) {
|
||||
AbstractValue receiverTypeOfInvocation(
|
||||
ir.MethodInvocation node, AbstractValueDomain abstractValueDomain) {
|
||||
return _targetResults.typeOfSend(node);
|
||||
}
|
||||
|
||||
TypeMask receiverTypeOfGet(ir.PropertyGet node) {
|
||||
AbstractValue receiverTypeOfGet(ir.PropertyGet node) {
|
||||
return _targetResults.typeOfSend(node);
|
||||
}
|
||||
|
||||
TypeMask receiverTypeOfDirectGet(ir.DirectPropertyGet node) {
|
||||
AbstractValue receiverTypeOfDirectGet(ir.DirectPropertyGet node) {
|
||||
return _targetResults.typeOfSend(node);
|
||||
}
|
||||
|
||||
TypeMask receiverTypeOfSet(ir.PropertySet node, ClosedWorld closedWorld) {
|
||||
AbstractValue receiverTypeOfSet(
|
||||
ir.PropertySet node, AbstractValueDomain abstractValueDomain) {
|
||||
return _targetResults.typeOfSend(node);
|
||||
}
|
||||
|
||||
TypeMask typeOfListLiteral(
|
||||
MemberEntity owner, ir.ListLiteral listLiteral, ClosedWorld closedWorld) {
|
||||
AbstractValue typeOfListLiteral(MemberEntity owner,
|
||||
ir.ListLiteral listLiteral, AbstractValueDomain abstractValueDomain) {
|
||||
return _resultOf(owner).typeOfListLiteral(listLiteral) ??
|
||||
closedWorld.abstractValueDomain.dynamicType;
|
||||
abstractValueDomain.dynamicType;
|
||||
}
|
||||
|
||||
TypeMask typeOfIterator(ir.ForInStatement node) {
|
||||
AbstractValue typeOfIterator(ir.ForInStatement node) {
|
||||
return _targetResults.typeOfIterator(node);
|
||||
}
|
||||
|
||||
TypeMask typeOfIteratorCurrent(ir.ForInStatement node) {
|
||||
AbstractValue typeOfIteratorCurrent(ir.ForInStatement node) {
|
||||
return _targetResults.typeOfIteratorCurrent(node);
|
||||
}
|
||||
|
||||
TypeMask typeOfIteratorMoveNext(ir.ForInStatement node) {
|
||||
AbstractValue typeOfIteratorMoveNext(ir.ForInStatement node) {
|
||||
return _targetResults.typeOfIteratorMoveNext(node);
|
||||
}
|
||||
|
||||
bool isJsIndexableIterator(ir.ForInStatement node, ClosedWorld closedWorld) {
|
||||
TypeMask mask = typeOfIterator(node);
|
||||
return mask != null &&
|
||||
mask.satisfies(
|
||||
closedWorld.commonElements.jsIndexableClass, closedWorld) &&
|
||||
// String is indexable but not iterable.
|
||||
!mask.satisfies(closedWorld.commonElements.jsStringClass, closedWorld);
|
||||
bool isJsIndexableIterator(
|
||||
ir.ForInStatement node, AbstractValueDomain abstractValueDomain) {
|
||||
AbstractValue mask = typeOfIterator(node);
|
||||
return abstractValueDomain.isJsIndexableAndIterable(mask);
|
||||
}
|
||||
|
||||
bool isFixedLength(covariant TypeMask mask, ClosedWorld closedWorld) {
|
||||
if (mask.isContainer && (mask as ContainerTypeMask).length != null) {
|
||||
// A container on which we have inferred the length.
|
||||
return true;
|
||||
}
|
||||
// TODO(sra): Recognize any combination of fixed length indexables.
|
||||
if (mask.containsOnly(closedWorld.commonElements.jsFixedArrayClass) ||
|
||||
mask.containsOnly(
|
||||
closedWorld.commonElements.jsUnmodifiableArrayClass) ||
|
||||
mask.containsOnlyString(closedWorld) ||
|
||||
closedWorld.abstractValueDomain.isTypedArray(mask)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
TypeMask inferredIndexType(ir.ForInStatement node) {
|
||||
AbstractValue inferredIndexType(ir.ForInStatement node) {
|
||||
return TypeMaskFactory.inferredTypeForSelector(
|
||||
new Selector.index(), typeOfIterator(node), _globalInferenceResults);
|
||||
}
|
||||
|
||||
TypeMask getInferredTypeOf(MemberEntity member) {
|
||||
AbstractValue getInferredTypeOf(MemberEntity member) {
|
||||
return TypeMaskFactory.inferredTypeForMember(
|
||||
member, _globalInferenceResults);
|
||||
}
|
||||
|
||||
TypeMask getInferredTypeOfParameter(Local parameter) {
|
||||
AbstractValue getInferredTypeOfParameter(Local parameter) {
|
||||
return TypeMaskFactory.inferredTypeForParameter(
|
||||
parameter, _globalInferenceResults);
|
||||
}
|
||||
|
||||
TypeMask selectorTypeOf(Selector selector, covariant TypeMask mask) {
|
||||
AbstractValue selectorTypeOf(Selector selector, AbstractValue mask) {
|
||||
return TypeMaskFactory.inferredTypeForSelector(
|
||||
selector, mask, _globalInferenceResults);
|
||||
}
|
||||
|
||||
TypeMask typeFromNativeBehavior(
|
||||
AbstractValue typeFromNativeBehavior(
|
||||
NativeBehavior nativeBehavior, ClosedWorld closedWorld) {
|
||||
return TypeMaskFactory.fromNativeBehavior(nativeBehavior, closedWorld);
|
||||
}
|
||||
|
|
|
@ -1494,7 +1494,8 @@ class KernelSsaGraphBuilder extends ir.Visitor
|
|||
void visitForInStatement(ir.ForInStatement node) {
|
||||
if (node.isAsync) {
|
||||
_buildAsyncForIn(node);
|
||||
} else if (_typeInferenceMap.isJsIndexableIterator(node, closedWorld)) {
|
||||
} else if (_typeInferenceMap.isJsIndexableIterator(
|
||||
node, abstractValueDomain)) {
|
||||
// If the expression being iterated over is a JS indexable type, we can
|
||||
// generate an optimized version of for-in that uses indexing.
|
||||
_buildForInIndexable(node);
|
||||
|
@ -1561,7 +1562,7 @@ class KernelSsaGraphBuilder extends ir.Visitor
|
|||
node.iterable.accept(this);
|
||||
array = pop();
|
||||
isFixed =
|
||||
_typeInferenceMap.isFixedLength(array.instructionType, closedWorld);
|
||||
abstractValueDomain.isFixedLengthJsIndexable(array.instructionType);
|
||||
localsHandler.updateLocal(
|
||||
indexVariable, graph.addConstantInt(0, closedWorld),
|
||||
sourceInformation: sourceInformation);
|
||||
|
@ -2686,8 +2687,8 @@ class KernelSsaGraphBuilder extends ir.Visitor
|
|||
listInstruction, type, sourceInformation);
|
||||
}
|
||||
|
||||
TypeMask type =
|
||||
_typeInferenceMap.typeOfListLiteral(targetElement, node, closedWorld);
|
||||
TypeMask type = _typeInferenceMap.typeOfListLiteral(
|
||||
targetElement, node, abstractValueDomain);
|
||||
if (!type.containsAll(closedWorld)) {
|
||||
listInstruction.instructionType = type;
|
||||
}
|
||||
|
@ -2926,7 +2927,7 @@ class KernelSsaGraphBuilder extends ir.Visitor
|
|||
|
||||
_pushDynamicInvocation(
|
||||
node,
|
||||
_typeInferenceMap.receiverTypeOfSet(node, closedWorld),
|
||||
_typeInferenceMap.receiverTypeOfSet(node, abstractValueDomain),
|
||||
new Selector.setter(_elementMap.getName(node.name)),
|
||||
<HInstruction>[receiver, value],
|
||||
const <DartType>[],
|
||||
|
@ -4234,7 +4235,7 @@ class KernelSsaGraphBuilder extends ir.Visitor
|
|||
_fillDynamicTypeArguments(selector, node.arguments, typeArguments);
|
||||
_pushDynamicInvocation(
|
||||
node,
|
||||
_typeInferenceMap.receiverTypeOfInvocation(node, closedWorld),
|
||||
_typeInferenceMap.receiverTypeOfInvocation(node, abstractValueDomain),
|
||||
selector,
|
||||
<HInstruction>[receiver]..addAll(_visitArgumentsForDynamicTarget(
|
||||
selector, node.arguments, typeArguments)),
|
||||
|
|
|
@ -278,4 +278,14 @@ abstract class AbstractValueDomain {
|
|||
///
|
||||
/// Returns `null` if 0 or more than 1 member can be hit at runtime.
|
||||
MemberEntity locateSingleMember(AbstractValue receiver, Selector selector);
|
||||
|
||||
/// Returns `true` if [value] is a indexable and iterable JavaScript value at
|
||||
/// runtime.
|
||||
///
|
||||
/// JavaScript arrays are both indexable and iterable whereas JavaScript
|
||||
/// strings are indexable but not iterable.
|
||||
bool isJsIndexableAndIterable(AbstractValue value);
|
||||
|
||||
/// Returns `true` if [value] is an JavaScript indexable of fixed length.
|
||||
bool isFixedLengthJsIndexable(AbstractValue value);
|
||||
}
|
||||
|
|
|
@ -453,4 +453,31 @@ class CommonMasks implements AbstractValueDomain {
|
|||
covariant TypeMask receiver, Selector selector) {
|
||||
return receiver.locateSingleMember(selector, _closedWorld);
|
||||
}
|
||||
|
||||
@override
|
||||
bool isJsIndexableAndIterable(covariant TypeMask mask) {
|
||||
return mask != null &&
|
||||
mask.satisfies(
|
||||
_closedWorld.commonElements.jsIndexableClass, _closedWorld) &&
|
||||
// String is indexable but not iterable.
|
||||
!mask.satisfies(
|
||||
_closedWorld.commonElements.jsStringClass, _closedWorld);
|
||||
}
|
||||
|
||||
@override
|
||||
bool isFixedLengthJsIndexable(covariant TypeMask mask) {
|
||||
if (mask.isContainer && (mask as ContainerTypeMask).length != null) {
|
||||
// A container on which we have inferred the length.
|
||||
return true;
|
||||
}
|
||||
// TODO(sra): Recognize any combination of fixed length indexables.
|
||||
if (mask.containsOnly(_closedWorld.commonElements.jsFixedArrayClass) ||
|
||||
mask.containsOnly(
|
||||
_closedWorld.commonElements.jsUnmodifiableArrayClass) ||
|
||||
mask.containsOnlyString(_closedWorld) ||
|
||||
_closedWorld.abstractValueDomain.isTypedArray(mask)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -461,7 +461,7 @@ abstract class ClosedWorldBase implements ClosedWorld, ClosedWorldRefiner {
|
|||
final Set<FunctionEntity> _functionsThatMightBePassedToApply =
|
||||
new Set<FunctionEntity>();
|
||||
|
||||
CommonMasks _commonMasks;
|
||||
AbstractValueDomain _abstractValueDomain;
|
||||
|
||||
final ElementEnvironment elementEnvironment;
|
||||
final DartTypes dartTypes;
|
||||
|
@ -500,14 +500,14 @@ abstract class ClosedWorldBase implements ClosedWorld, ClosedWorldRefiner {
|
|||
: this._implementedClasses = implementedClasses,
|
||||
this._classHierarchyNodes = classHierarchyNodes,
|
||||
this._classSets = classSets {
|
||||
_commonMasks = new CommonMasks(this);
|
||||
_abstractValueDomain = new CommonMasks(this);
|
||||
}
|
||||
|
||||
@override
|
||||
ClosedWorld get closedWorld => this;
|
||||
|
||||
CommonMasks get abstractValueDomain {
|
||||
return _commonMasks;
|
||||
AbstractValueDomain get abstractValueDomain {
|
||||
return _abstractValueDomain;
|
||||
}
|
||||
|
||||
bool checkEntity(covariant Entity element);
|
||||
|
|
Loading…
Reference in a new issue