| 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 2c45b4a7cfb26310f3db12553878459ff31f7d63..b6cb9391c764f1f7afbd3827076f15bcbc5ea6ea 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;
|
| @@ -66,7 +70,10 @@ abstract class TypeInformation {
|
| 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>.from([], growable: false);
|
|
|
| bool areAssignmentsTracked() {
|
| return assignments != STOP_TRACKING_ASSIGNMENTS_MARKER;
|
| @@ -104,7 +111,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 +138,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) {
|
| @@ -147,6 +154,12 @@ abstract class TypeInformation {
|
| }
|
| }
|
|
|
| +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 +225,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 +285,9 @@ class ElementTypeInformation extends TypeInformation {
|
| return count == 1;
|
| }
|
|
|
| - bool isClosurized() => closurizedCount > 0;
|
| + bool get isClosurized => closurizedCount > 0;
|
| +
|
| + bool get isStable => super.isStable && !isClosurized;
|
|
|
| TypeMask handleSpecialCases(TypeGraphInferrerEngine inferrer) {
|
| if (abandonInferencing) return type;
|
| @@ -397,7 +412,9 @@ class ElementTypeInformation extends TypeInformation {
|
| }
|
| // If the method is closurized, the closure tracing phase will go
|
| // through the users.
|
| - if (closurizedCount != 0) return false;
|
| + if (isClosurized) 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;
|
| @@ -1233,7 +1250,7 @@ class PhiElementTypeInformation extends TypeInformation {
|
| }
|
| }
|
|
|
| -class ClosureTypeInformation extends TypeInformation {
|
| +class ClosureTypeInformation extends ApplyableTypeInformation {
|
| final ast.Node node;
|
| final Element element;
|
|
|
|
|