Chromium Code Reviews| 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..d8bb12ebe0d64359b7f1382d71d7925d346e5d47 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,42 @@ 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) { |
| + compiler.world.registerMightBePassedToApply(e); |
| + if (_VERBOSE) print("traced closure $e as ${true} (bail)"); |
| + }); |
| + return; |
| + } |
| + elements.forEach((FunctionElement e) { |
| + e.functionSignature.forEachParameter((parameter) { |
| + workQueue.add(types.getInferredTypeOf(parameter)); |
| + }); |
| + if (tracer.tracedType.mightBePassedToFunctionApply) { |
| + compiler.world.registerMightBePassedToApply(e); |
| + }; |
| + if (_VERBOSE) { |
| + print("traced closure $e as " |
| + "${compiler.world.getMightBePassedToApply(e)}"); |
| + } |
| + }); |
| + } |
| + 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); |
|
floitsch
2014/04/14 15:39:37
You probably want to cache the computation (unless
herhut
2014/04/15 10:50:39
Done.
|
| + trace(elements, new ClosureTracerVisitor(elements, info, this)); |
|
floitsch
2014/04/14 15:39:37
Can it happen (frequently) that the elements list
herhut
2014/04/15 10:50:39
The situation where the target is not a function i
|
| + } else { |
| + trace([info.element], |
|
floitsch
2014/04/14 15:39:37
add assert to make sure you have the right type.
A
herhut
2014/04/15 10:50:39
Done.
|
| + new StaticTearOffClosureTracerVisitor(info.element, info, this)); |
| + } |
| }); |
| // Reset all nodes that use lists/maps that have been inferred, as well |
| @@ -596,7 +623,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 +779,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. |
|
floitsch
2014/04/14 15:39:37
also add assert for that.
assert(callee.isMethod()
herhut
2014/04/15 10:50:39
Done.
|
| ElementTypeInformation info = types.getInferredTypeOf(callee); |
| if (remove) { |
| info.closurizedCount--; |
| @@ -759,6 +787,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; |