Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Unified Diff: sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart

Issue 22947008: Refine the type of a local after it has been used as the receiver of a call. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
===================================================================
--- sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart (revision 26339)
+++ sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart (working copy)
@@ -122,6 +122,15 @@
TypeMask simplifyPhi(Node node, Element element, TypeMask phiType) {
return phiType;
}
+
+ TypeMask refineReceiver(Selector selector, TypeMask receiverType) {
+ // If the receiver is based on an element, we let the type
+ // inferrer handle it. Otherwise, we might prevent it from finding
+ // one-level cycles in the inference graph.
+ if (receiverType.isElement) return receiverType;
+ TypeMask newType = compiler.world.allFunctions.receiverType(selector);
+ return receiverType.intersection(newType, compiler);
+ }
}
/**
@@ -1582,6 +1591,7 @@
SideEffects sideEffects = new SideEffects.empty();
final Element outermostElement;
final InferrerEngine<T> inferrer;
+ final Set<Element> capturedVariables = new Set<Element>();
SimpleTypeInferrerVisitor.internal(analyzedElement,
this.outermostElement,
@@ -1735,11 +1745,14 @@
// same as [newType].
ClosureClassMap nestedClosureData =
compiler.closureToClassMapper.getMappingForNestedFunction(node);
- nestedClosureData.forEachNonBoxedCapturedVariable((variable, field) {
- // The type may be null for instance contexts: the 'this'
- // variable and type parameters.
- if (locals.locals[variable] == null) return;
- inferrer.recordType(field, locals.locals[variable]);
+ nestedClosureData.forEachCapturedVariable((variable, field) {
+ if (!nestedClosureData.isVariableBoxed(variable)) {
+ // The type may be null for instance contexts: the 'this'
+ // variable and type parameters.
+ if (locals.locals[variable] == null) return;
+ inferrer.recordType(field, locals.locals[variable]);
+ }
+ capturedVariables.add(variable);
});
return types.functionType;
@@ -2164,17 +2177,32 @@
T handleDynamicSend(Node node,
Selector selector,
- T receiver,
+ T receiverType,
ArgumentsTypes arguments,
[CallSite constraint]) {
- if (selector.mask != receiver) {
- selector = (receiver == types.dynamicType)
+ if (selector.mask != receiverType) {
+ selector = (receiverType == types.dynamicType)
? selector.asUntyped
- : types.newTypedSelector(receiver, selector);
+ : types.newTypedSelector(receiverType, selector);
updateSelectorInTree(node, selector);
}
+
+ // If the receiver of the call is a local, we may know more about
+ // its type by refining it with the potential targets of the
+ // calls.
+ if (node.asSend() != null) {
+ Node receiver = node.asSend().receiver;
+ if (receiver != null) {
+ Element element = elements[receiver];
+ if (Elements.isLocal(element) && !capturedVariables.contains(element)) {
+ T refinedType = types.refineReceiver(selector, receiverType);
+ locals.update(element, refinedType, node);
+ }
+ }
+ }
+
return inferrer.registerCalledSelector(
- node, selector, receiver, outermostElement, arguments,
+ node, selector, receiverType, outermostElement, arguments,
constraint, sideEffects, inLoop);
}

Powered by Google App Engine
This is Rietveld 408576698