Index: pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart |
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart |
index c25d8d7ad4c292832168b1f559c97bc0c2c19534..4ed931d169fb3ad79ae4af14df1259badeadf684 100644 |
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart |
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart |
@@ -683,6 +683,7 @@ class TypeGraphInferrerEngine |
// Trace closures to potentially infer argument types. |
types.allocatedClosures.forEach((info) { |
+ |
void trace(Iterable<FunctionElement> elements, |
ClosureTracerVisitor tracer) { |
tracer.run(); |
@@ -716,16 +717,32 @@ class TypeGraphInferrerEngine |
} |
}); |
} |
+ |
if (info is ClosureTypeInformation) { |
Iterable<FunctionElement> elements = [info.element]; |
trace(elements, new ClosureTracerVisitor(elements, info, this)); |
} else if (info is CallSiteTypeInformation) { |
- // We only are interested in functions here, as other targets |
- // of this closure call are not a root to trace but an intermediate |
- // for some other function. |
- Iterable<FunctionElement> elements = info.callees |
- .where((e) => e.isFunction); |
- trace(elements, new ClosureTracerVisitor(elements, info, this)); |
+ if (info is StaticCallSiteTypeInformation && |
+ info.selector != null && |
+ info.selector.isCall) { |
+ // This is a constructor call to a class with a call method. So we |
+ // need to trace the call method here. |
+ assert(info.calledElement.isConstructor); |
+ ClassElement cls = info.calledElement.enclosingClass; |
+ FunctionElement callMethod = |
+ cls.lookupMember(Compiler.CALL_OPERATOR_NAME); |
+ assert(invariant(cls, callMethod != null)); |
+ Iterable<FunctionElement> elements = [callMethod]; |
+ trace(elements, new ClosureTracerVisitor(elements, info, this)); |
+ } else { |
+ // We only are interested in functions here, as other targets |
+ // of this closure call are not a root to trace but an intermediate |
+ // for some other function. |
+ Iterable<FunctionElement> elements = |
+ new List<FunctionElement>.from( |
+ info.callees.where((e) => e.isFunction)); |
+ trace(elements, new ClosureTracerVisitor(elements, info, this)); |
+ } |
} else { |
assert(info is ElementTypeInformation); |
trace([info.element], |
@@ -777,6 +794,11 @@ class TypeGraphInferrerEngine |
print('${types.getInferredTypeOf(target).type} for ${target}'); |
} |
} |
+ } else if (info is StaticCallSiteTypeInformation) { |
+ ClassElement cls = info.calledElement.enclosingClass; |
+ FunctionElement callMethod = |
+ cls.lookupMember(Compiler.CALL_OPERATOR_NAME); |
+ print('${types.getInferredSignatureOf(callMethod)} for ${cls}'); |
} else { |
print('${info.type} for some unknown kind of closure'); |
} |
@@ -1111,6 +1133,14 @@ class TypeGraphInferrerEngine |
CallSiteTypeInformation info = new StaticCallSiteTypeInformation( |
types.currentMember, node, caller, callee, selector, mask, arguments, |
inLoop); |
+ // If this class has a 'call' method then we have essentially created a |
+ // closure here. Register it as such so that it is traced. |
+ if (selector != null && selector.isCall && callee.isConstructor) { |
+ ClassElement cls = callee.enclosingClass.declaration; |
+ if (cls.callType != null) { |
+ types.allocatedClosures.add(info); |
+ } |
+ } |
info.addToGraph(this); |
allocatedCalls.add(info); |
updateSideEffects(sideEffects, selector, callee); |