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

Unified Diff: sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.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_nodes.dart
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
index a7e9501072b383fe69b2bf639a294b1072314590..46d9c59912d05c8c5e9e30624c11ad311c0f628f 100644
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
@@ -28,9 +28,13 @@ abstract class TypeInformation {
/// Initially empty.
TypeMask type = const TypeMask.nonNullEmpty();
- /// We give up on inferencing for special elements, as well as for
- /// complicated cyclic dependencies.
+ /// We abandon inference in certain cases (complex cyclic flow, native
+ /// behaviours, etc.). In some case, we might resume inference in the
+ /// closure tracer, which is handled by checking whether [assignments] has
+ /// been set to [STOP_TRACKING_ASSIGNMENTS_MARKER].
bool abandonInferencing = false;
+ bool get mightResume =>
+ !identical(assignments, STOP_TRACKING_ASSIGNMENTS_MARKER);
/// Number of times this [TypeInformation] has changed type.
int refineCount = 0;
@@ -55,18 +59,18 @@ abstract class TypeInformation {
void addUser(TypeInformation user) {
- if (isStable) return;
assert(!user.isConcrete);
users.add(user);
}
void removeUser(TypeInformation user) {
- if (isStable) return;
assert(!user.isConcrete);
users.remove(user);
}
- static final STOP_TRACKING_ASSIGNMENTS_MARKER = const <TypeInformation>[];
+ // The below is not a compile time constant to make it differentiable
+ // from other empty lists of [TypeInformation].
+ static final STOP_TRACKING_ASSIGNMENTS_MARKER = new List<TypeInformation>(0);
bool areAssignmentsTracked() {
return assignments != STOP_TRACKING_ASSIGNMENTS_MARKER;
@@ -85,7 +89,7 @@ abstract class TypeInformation {
}
void removeAssignment(TypeInformation assignment) {
- if (!abandonInferencing) {
+ if (!abandonInferencing || mightResume) {
assignments.remove(assignment);
}
// We can have multiple assignments of the same [TypeInformation].
@@ -104,7 +108,7 @@ abstract class TypeInformation {
// Do not remove [this] as a user of nodes in [assignments],
// because our tracing analysis could be interested in tracing
// this node.
- if (clearAssignments) assignments = const <TypeInformation>[];
+ if (clearAssignments) assignments = STOP_TRACKING_ASSIGNMENTS_MARKER;
// Do not remove users because our tracing analysis could be
// interested in tracing the users of this node.
}
@@ -131,7 +135,7 @@ abstract class TypeInformation {
/// Returns whether the type cannot change after it has been
/// inferred.
bool hasStableType(TypeGraphInferrerEngine inferrer) {
- return !abandonInferencing && assignments.every((e) => e.isStable);
+ return !mightResume && assignments.every((e) => e.isStable);
}
void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
@@ -140,13 +144,20 @@ abstract class TypeInformation {
void stabilize(TypeGraphInferrerEngine inferrer) {
removeAndClearReferences(inferrer);
- users = const <TypeInformation>[];
+ // Do not remove users because the tracing analysis could be interested
+ // in tracing the users of this node.
assignments = STOP_TRACKING_ASSIGNMENTS_MARKER;
abandonInferencing = true;
isStable = true;
}
}
+abstract class ApplyableTypeInformation extends TypeInformation {
+ bool mightBePassedToFunctionApply = false;
+
+ ApplyableTypeInformation([users, assignments]) : super(users, assignments);
+}
+
/**
* Parameters of instance functions behave differently than other
* elements because the inferrer may remove assignments. This happens
@@ -212,7 +223,7 @@ class ParameterAssignments extends IterableBase<TypeInformation> {
* trust their type annotation.
*
*/
-class ElementTypeInformation extends TypeInformation {
+class ElementTypeInformation extends ApplyableTypeInformation {
final Element element;
// Marker to disable [handleSpecialCases]. For example, parameters
@@ -272,7 +283,13 @@ class ElementTypeInformation extends TypeInformation {
return count == 1;
}
- bool isClosurized() => closurizedCount > 0;
+ bool get isClosurized => closurizedCount > 0;
+
+ // Closurized methods never become stable to ensure that the information in
+ // [users] is accurate. The inference stops tracking users for stable types.
+ // Note that we only override the getter, the setter will still modify the
+ // state of the [isStable] field inhertied from [TypeInformation].
+ bool get isStable => super.isStable && !isClosurized;
TypeMask handleSpecialCases(TypeGraphInferrerEngine inferrer) {
if (abandonInferencing) return type;
@@ -389,15 +406,15 @@ class ElementTypeInformation extends TypeInformation {
if (element.isParameter() && element.enclosingElement.isInstanceMember()) {
return false;
}
+
// The number of assignments of non-final fields is
// not stable. Therefore such a field cannot be stable.
if (element.isField() &&
!(element.modifiers.isConst() || element.modifiers.isFinal())) {
return false;
}
- // If the method is closurized, the closure tracing phase will go
- // through the users.
- if (closurizedCount != 0) return false;
+
+ if (element.isFunction()) return false;
return super.hasStableType(inferrer);
}
@@ -413,7 +430,7 @@ class ElementTypeInformation extends TypeInformation {
* any assignment. They rely on the [caller] field for static calls,
* and [selector] and [receiver] fields for dynamic calls.
*/
-abstract class CallSiteTypeInformation extends TypeInformation {
+abstract class CallSiteTypeInformation extends ApplyableTypeInformation {
final Spannable call;
final Element caller;
final Selector selector;
@@ -1226,7 +1243,7 @@ class PhiElementTypeInformation extends TypeInformation {
}
}
-class ClosureTypeInformation extends TypeInformation {
+class ClosureTypeInformation extends ApplyableTypeInformation {
final ast.Node node;
final Element element;

Powered by Google App Engine
This is Rietveld 408576698