| Index: pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
|
| diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
|
| index 98a9309d35567c9fd3ce8f42a27751f82b804289..4e0dd845b91a1c0e02820e32b1dbdf10828a61c0 100644
|
| --- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
|
| +++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
|
| @@ -237,6 +237,12 @@ abstract class TypeInformation {
|
| abandonInferencing = false;
|
| doNotEnqueue = false;
|
| }
|
| +
|
| + /// Destroys information not needed after type inference.
|
| + void cleanup() {
|
| + users = null;
|
| + _assignments = null;
|
| + }
|
| }
|
|
|
| abstract class ApplyableTypeInformation implements TypeInformation {
|
| @@ -385,6 +391,10 @@ class MemberTypeInformation extends ElementTypeInformation
|
| */
|
| int closurizedCount = 0;
|
|
|
| + // Strict `bool` value is computed in cleanup(). Also used as a flag to see if
|
| + // cleanup has been called.
|
| + bool _isCalledOnce = null;
|
| +
|
| /**
|
| * This map contains the callers of [element]. It stores all unique call sites
|
| * to enable counting the global number of call sites of [element].
|
| @@ -392,18 +402,23 @@ class MemberTypeInformation extends ElementTypeInformation
|
| * A call site is either an AST [ast.Node], a [cps_ir.Node] or in the case of
|
| * synthesized calls, an [Element] (see uses of [synthesizeForwardingCall]
|
| * in [SimpleTypeInferrerVisitor]).
|
| + *
|
| + * The global information is summarized in [cleanup], after which [_callers]
|
| + * is set to `null`.
|
| */
|
| - final Map<Element, Setlet<Spannable>> _callers = new Map<Element, Setlet>();
|
| + Map<Element, Setlet<Spannable>> _callers;
|
|
|
| MemberTypeInformation._internal(Element element)
|
| : super._internal(null, element);
|
|
|
| void addCall(Element caller, Spannable node) {
|
| assert(node is ast.Node || node is cps_ir.Node || node is Element);
|
| + _callers ??= <Element, Setlet>{};
|
| _callers.putIfAbsent(caller, () => new Setlet()).add(node);
|
| }
|
|
|
| void removeCall(Element caller, node) {
|
| + if (_callers == null) return;
|
| Setlet calls = _callers[caller];
|
| if (calls == null) return;
|
| calls.remove(node);
|
| @@ -412,9 +427,27 @@ class MemberTypeInformation extends ElementTypeInformation
|
| }
|
| }
|
|
|
| - Iterable<Element> get callers => _callers.keys;
|
| + Iterable<Element> get callers {
|
| + // TODO(sra): This is called only from an unused API and a test. If it
|
| + // becomes used, [cleanup] will need to copy `_caller.keys`.
|
| +
|
| + // `simple_inferrer_callers_test.dart` ensures that cleanup has not
|
| + // happened.
|
| + return _callers.keys;
|
| + }
|
|
|
| bool isCalledOnce() {
|
| + // If this assert fires it means that this MemberTypeInformation for the
|
| + // element was not part of type inference. This happens for
|
| + // ConstructorBodyElements, so guard the call with a test for
|
| + // ConstructorBodyElement. For other elements, investigate why the element
|
| + // was not present for type inference.
|
| + assert(_isCalledOnce != null);
|
| + return _isCalledOnce ?? false;
|
| + }
|
| +
|
| + bool _computeIsCalledOnce() {
|
| + if (_callers == null) return false;
|
| int count = 0;
|
| for (var set in _callers.values) {
|
| count += set.length;
|
| @@ -530,6 +563,14 @@ class MemberTypeInformation extends ElementTypeInformation
|
|
|
| return super.hasStableType(inferrer);
|
| }
|
| +
|
| + void cleanup() {
|
| + // This node is on multiple lists so cleanup() can be called twice.
|
| + if (_isCalledOnce != null) return;
|
| + _isCalledOnce = _computeIsCalledOnce();
|
| + _callers = null;
|
| + super.cleanup();
|
| + }
|
| }
|
|
|
| /**
|
| @@ -1319,6 +1360,12 @@ class ListTypeInformation extends TypeInformation
|
| }
|
|
|
| TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType;
|
| +
|
| + void cleanup() {
|
| + super.cleanup();
|
| + elementType.cleanup();
|
| + _flowsInto = null;
|
| + }
|
| }
|
|
|
| /**
|
| @@ -1482,6 +1529,16 @@ class MapTypeInformation extends TypeInformation
|
| super.hasStableType(inferrer);
|
| }
|
|
|
| + void cleanup() {
|
| + super.cleanup();
|
| + keyType.cleanup();
|
| + valueType.cleanup();
|
| + for (TypeInformation info in typeInfoMap.values) {
|
| + info.cleanup();
|
| + }
|
| + _flowsInto = null;
|
| + }
|
| +
|
| String toString() {
|
| return 'Map $type (K:$keyType, V:$valueType) contents $typeInfoMap';
|
| }
|
|
|