| Index: sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
|
| index cfe1661b5c587ef5a65b2e33b4179fbf00db2786..d3aeaf9389d841ae344c521ef7bd8cdbe9577a16 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
|
| @@ -27,6 +27,7 @@ part 'node_tracer.dart';
|
| part 'map_tracer.dart';
|
|
|
| bool _VERBOSE = false;
|
| +bool _PRINT_SUMMARY = false;
|
|
|
| /**
|
| * A set of selector names that [List] implements, that we know return
|
| @@ -569,16 +570,41 @@ class TypeGraphInferrerEngine
|
| analyzeMapAndEnqueue(info);
|
| });
|
|
|
| + // Trace closures to potentially infer argument types.
|
| types.allocatedClosures.forEach((info) {
|
| - ClosureTracerVisitor tracer = info is ClosureTypeInformation
|
| - ? new ClosureTracerVisitor(info.element, info, this)
|
| - : new StaticTearOffClosureTracerVisitor(info.element, info, this);
|
| - tracer.run();
|
| - if (!tracer.continueAnalyzing) return;
|
| - FunctionElement element = info.element;
|
| - element.functionSignature.forEachParameter((parameter) {
|
| - workQueue.add(types.getInferredTypeOf(parameter));
|
| - });
|
| + void trace(Iterable<FunctionElement> elements,
|
| + ClosureTracerVisitor tracer) {
|
| + tracer.run();
|
| + if (!tracer.continueAnalyzing) {
|
| + elements.forEach((FunctionElement e) {
|
| + e.mightBePassedToFunctionApply = true;
|
| + if (_VERBOSE) print("traced closure $e as ${true} (bail)");
|
| + });
|
| + return;
|
| + }
|
| + elements.forEach((FunctionElement e) {
|
| + e.functionSignature.forEachParameter((parameter) {
|
| + workQueue.add(types.getInferredTypeOf(parameter));
|
| + });
|
| + e.mightBePassedToFunctionApply =
|
| + tracer.tracedType.mightBePassedToFunctionApply;
|
| + if (_VERBOSE) {
|
| + print("traced closure $e as "
|
| + "${e.mightBePassedToFunctionApply}");
|
| + }
|
| + });
|
| + }
|
| + if (info is ClosureTypeInformation) {
|
| + Iterable<FunctionElement> elements = [info.element];
|
| + trace(elements, new ClosureTracerVisitor(elements, info, this));
|
| + } else if (info is CallSiteTypeInformation) {
|
| + Iterable<FunctionElement> elements =
|
| + info.callees.where((e) => e.isFunction() && !e.isSynthesized);
|
| + trace(elements, new ClosureTracerVisitor(elements, info, this));
|
| + } else {
|
| + trace([info.element],
|
| + new StaticTearOffClosureTracerVisitor(info.element, info, this));
|
| + }
|
| });
|
|
|
| // Reset all nodes that use lists/maps that have been inferred, as well
|
| @@ -596,7 +622,7 @@ class TypeGraphInferrerEngine
|
| workQueue.addAll(seenTypes);
|
| refine();
|
|
|
| - if (_VERBOSE) {
|
| + if (_PRINT_SUMMARY) {
|
| types.allocatedLists.values.forEach((ListTypeInformation info) {
|
| print('${info.type} '
|
| 'for ${info.originalContainerType.allocationNode} '
|
| @@ -752,6 +778,7 @@ class TypeGraphInferrerEngine
|
| } else if (callee.isGetter()) {
|
| return;
|
| } else if (selector != null && selector.isGetter()) {
|
| + // We are tearing a function off and thus create a closure.
|
| ElementTypeInformation info = types.getInferredTypeOf(callee);
|
| if (remove) {
|
| info.closurizedCount--;
|
| @@ -759,6 +786,10 @@ class TypeGraphInferrerEngine
|
| info.closurizedCount++;
|
| if (Elements.isStaticOrTopLevel(callee)) {
|
| types.allocatedClosures.add(info);
|
| + } else {
|
| + // We add the call-site type information here so that we
|
| + // can benefit from further refinement of the selector.
|
| + types.allocatedClosures.add(caller);
|
| }
|
| FunctionElement function = callee.implementation;
|
| FunctionSignature signature = function.functionSignature;
|
|
|