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

Unified Diff: sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart

Issue 223403003: Use closure tracer to identify closures that are not passed to Function.apply (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: fixed issue with failing test Created 6 years, 8 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/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 ae3bf166ac7bd7d554c6934b5bae5afa5df837ad..ca6e91a7fbb4b26a0b3c3a98859927b61c948d67 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
@@ -366,6 +367,8 @@ class TypeInformationSystem extends TypeSystem<TypeInformation> {
if (newType != null) allocatedTypes.add(newType);
}
+ // Shortcut: If we already have a first approximation of the key/value type,
+ // start propagating it early.
if (isFixed) map.markAsInferred();
allocatedMaps[node] = map;
@@ -557,28 +560,57 @@ class TypeGraphInferrerEngine
buildWorkQueue();
refine();
- // Try to infer element types of lists.
+ // Try to infer element types of lists and compute their escape information.
types.allocatedLists.values.forEach((ListTypeInformation info) {
- if (info.elementType.inferred) return;
analyzeListAndEnqueue(info);
});
- // Try to infer the key and value types for maps.
+ // Try to infer the key and value types for maps and compute the values'
+ // escape information.
types.allocatedMaps.values.forEach((MapTypeInformation info) {
- if (info.keyType.inferred && info.valueType.inferred) return;
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) {
+ // 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()).toList();
+ trace(elements, new ClosureTracerVisitor(elements, info, this));
+ } else {
+ assert(info is ElementTypeInformation);
+ trace([info.element],
+ new StaticTearOffClosureTracerVisitor(info.element, info, this));
+ }
});
// Reset all nodes that use lists/maps that have been inferred, as well
@@ -596,7 +628,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} '
@@ -640,7 +672,7 @@ class TypeGraphInferrerEngine
// If [element] is final and has an initializer, we record
// the inferred type.
if (fieldElement.initializer != null) {
- if (type is! ListTypeInformation) {
+ if (type is! ListTypeInformation && type is! MapTypeInformation) {
// For non-container types, the constant handler does
// constant folding that could give more precise results.
Constant value = compiler.backend.constants
@@ -650,7 +682,12 @@ class TypeGraphInferrerEngine
FunctionConstant functionConstant = value;
type = types.allocateClosure(node, functionConstant.element);
} else {
- type = types.getConcreteTypeFor(value.computeMask(compiler));
+ // Although we might find a better type, we have to keep
+ // the old type around to ensure that we get a complete view
+ // of the type graph and do not drop any flow edges.
+ type = new NarrowTypeInformation(type,
+ value.computeMask(compiler));
+ types.allocatedTypes.add(type);
}
}
}
@@ -752,6 +789,8 @@ class TypeGraphInferrerEngine
} else if (callee.isGetter()) {
return;
} else if (selector != null && selector.isGetter()) {
+ // We are tearing a function off and thus create a closure.
+ assert(callee.isFunction());
ElementTypeInformation info = types.getInferredTypeOf(callee);
if (remove) {
info.closurizedCount--;
@@ -759,6 +798,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;

Powered by Google App Engine
This is Rietveld 408576698