| Index: pkg/compiler/lib/src/inferrer/node_tracer.dart
|
| diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
|
| index 174ae56847196aa705c4c15e42924db8d49ba5d4..c50929d01ba803a9b5bbf5fa890206c7a3617254 100644
|
| --- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
|
| +++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
|
| @@ -16,63 +16,61 @@ import 'debug.dart' as debug;
|
|
|
| // A set of selectors we know do not escape the elements inside the
|
| // list.
|
| -Set<String> doesNotEscapeListSet = new Set<String>.from(
|
| - const <String>[
|
| - // From Object.
|
| - '==',
|
| - 'hashCode',
|
| - 'toString',
|
| - 'noSuchMethod',
|
| - 'runtimeType',
|
| -
|
| - // From Iterable.
|
| - 'isEmpty',
|
| - 'isNotEmpty',
|
| - 'length',
|
| - 'contains',
|
| - 'join',
|
| -
|
| - // From List.
|
| - 'add',
|
| - 'addAll',
|
| - 'clear',
|
| - 'fillRange',
|
| - 'indexOf',
|
| - 'insert',
|
| - 'insertAll',
|
| - 'lastIndexOf',
|
| - 'remove',
|
| - 'removeRange',
|
| - 'replaceRange',
|
| - 'setAll',
|
| - 'setRange',
|
| - 'shuffle',
|
| - '[]=',
|
| -
|
| - // From JSArray.
|
| - 'checkMutable',
|
| - 'checkGrowable',
|
| - ]);
|
| -
|
| -Set<String> doesNotEscapeMapSet = new Set<String>.from(
|
| - const <String>[
|
| - // From Object.
|
| - '==',
|
| - 'hashCode',
|
| - 'toString',
|
| - 'noSuchMethod',
|
| - 'runtimeType',
|
| - // from Map.
|
| - 'isEmpty',
|
| - 'isNotEmpty',
|
| - 'length',
|
| - 'clear',
|
| - 'containsKey',
|
| - 'containsValue',
|
| - '[]=',
|
| - // [keys] only allows key values to escape, which we do not track.
|
| - 'keys'
|
| - ]);
|
| +Set<String> doesNotEscapeListSet = new Set<String>.from(const <String>[
|
| + // From Object.
|
| + '==',
|
| + 'hashCode',
|
| + 'toString',
|
| + 'noSuchMethod',
|
| + 'runtimeType',
|
| +
|
| + // From Iterable.
|
| + 'isEmpty',
|
| + 'isNotEmpty',
|
| + 'length',
|
| + 'contains',
|
| + 'join',
|
| +
|
| + // From List.
|
| + 'add',
|
| + 'addAll',
|
| + 'clear',
|
| + 'fillRange',
|
| + 'indexOf',
|
| + 'insert',
|
| + 'insertAll',
|
| + 'lastIndexOf',
|
| + 'remove',
|
| + 'removeRange',
|
| + 'replaceRange',
|
| + 'setAll',
|
| + 'setRange',
|
| + 'shuffle',
|
| + '[]=',
|
| +
|
| + // From JSArray.
|
| + 'checkMutable',
|
| + 'checkGrowable',
|
| +]);
|
| +
|
| +Set<String> doesNotEscapeMapSet = new Set<String>.from(const <String>[
|
| + // From Object.
|
| + '==',
|
| + 'hashCode',
|
| + 'toString',
|
| + 'noSuchMethod',
|
| + 'runtimeType',
|
| + // from Map.
|
| + 'isEmpty',
|
| + 'isNotEmpty',
|
| + 'length',
|
| + 'clear',
|
| + 'containsKey',
|
| + 'containsValue',
|
| + '[]=',
|
| + // [keys] only allows key values to escape, which we do not track.
|
| + 'keys'
|
| +]);
|
|
|
| /// Common logic to trace a value through the type inference graph nodes.
|
| abstract class TracerVisitor<T extends TypeInformation>
|
| @@ -85,7 +83,8 @@ abstract class TracerVisitor<T extends TypeInformation>
|
| final Setlet<Element> analyzedElements = new Setlet<Element>();
|
|
|
| TracerVisitor(this.tracedType, TypeGraphInferrerEngine inferrer)
|
| - : this.inferrer = inferrer, this.compiler = inferrer.compiler;
|
| + : this.inferrer = inferrer,
|
| + this.compiler = inferrer.compiler;
|
|
|
| // Work list that gets populated with [TypeInformation] that could
|
| // contain the container.
|
| @@ -94,8 +93,7 @@ abstract class TracerVisitor<T extends TypeInformation>
|
| // Work list of lists to analyze after analyzing the users of a
|
| // [TypeInformation]. We know the [tracedType] has been stored in these
|
| // lists and we must check how it escapes from these lists.
|
| - final List<ListTypeInformation> listsToAnalyze =
|
| - <ListTypeInformation>[];
|
| + final List<ListTypeInformation> listsToAnalyze = <ListTypeInformation>[];
|
| // Work list of maps to analyze after analyzing the users of a
|
| // [TypeInformation]. We know the [tracedType] has been stored in these
|
| // maps and we must check how it escapes from these maps.
|
| @@ -186,6 +184,7 @@ abstract class TracerVisitor<T extends TypeInformation>
|
| void visitMapTypeInformation(MapTypeInformation info) {
|
| mapsToAnalyze.add(info);
|
| }
|
| +
|
| void visitConcreteTypeInformation(ConcreteTypeInformation info) {}
|
|
|
| void visitStringLiteralTypeInformation(StringLiteralTypeInformation info) {}
|
| @@ -211,7 +210,7 @@ abstract class TracerVisitor<T extends TypeInformation>
|
| } else {
|
| list.flowsInto.forEach((flow) {
|
| flow.users.forEach((user) {
|
| - if (user is !DynamicCallSiteTypeInformation) return;
|
| + if (user is! DynamicCallSiteTypeInformation) return;
|
| if (user.receiver != flow) return;
|
| if (inferrer.returnsListElementTypeSet.contains(user.selector)) {
|
| addNewEscapeInformation(user);
|
| @@ -230,7 +229,7 @@ abstract class TracerVisitor<T extends TypeInformation>
|
| } else {
|
| map.flowsInto.forEach((flow) {
|
| flow.users.forEach((user) {
|
| - if (user is !DynamicCallSiteTypeInformation) return;
|
| + if (user is! DynamicCallSiteTypeInformation) return;
|
| if (user.receiver != flow) return;
|
| if (user.selector.isIndex) {
|
| addNewEscapeInformation(user);
|
| @@ -253,9 +252,9 @@ abstract class TracerVisitor<T extends TypeInformation>
|
| if (!receiverType.isContainer) return false;
|
| String selectorName = info.selector.name;
|
| List<TypeInformation> arguments = info.arguments.positional;
|
| - return (selectorName == '[]=' && currentUser == arguments[1])
|
| - || (selectorName == 'insert' && currentUser == arguments[1])
|
| - || (selectorName == 'add' && currentUser == arguments[0]);
|
| + return (selectorName == '[]=' && currentUser == arguments[1]) ||
|
| + (selectorName == 'insert' && currentUser == arguments[1]) ||
|
| + (selectorName == 'add' && currentUser == arguments[0]);
|
| }
|
|
|
| bool isIndexSetOnMap(DynamicCallSiteTypeInformation info) {
|
| @@ -271,8 +270,7 @@ abstract class TracerVisitor<T extends TypeInformation>
|
| * [isParameterOfMapAddingMethod].
|
| */
|
| bool isValueAddedToMap(DynamicCallSiteTypeInformation info) {
|
| - return isIndexSetOnMap(info) &&
|
| - currentUser == info.arguments.positional[1];
|
| + return isIndexSetOnMap(info) && currentUser == info.arguments.positional[1];
|
| }
|
|
|
| /**
|
| @@ -281,8 +279,7 @@ abstract class TracerVisitor<T extends TypeInformation>
|
| * [isParameterOfMapAddingMethod].
|
| */
|
| bool isKeyAddedToMap(DynamicCallSiteTypeInformation info) {
|
| - return isIndexSetOnMap(info) &&
|
| - currentUser == info.arguments.positional[0];
|
| + return isIndexSetOnMap(info) && currentUser == info.arguments.positional[0];
|
| }
|
|
|
| void visitDynamicCallSiteTypeInformation(
|
| @@ -341,9 +338,9 @@ abstract class TracerVisitor<T extends TypeInformation>
|
| return false;
|
| }
|
| Element method = element.enclosingElement;
|
| - return (method.name == '[]=')
|
| - || (method.name == 'add')
|
| - || (method.name == 'insert');
|
| + return (method.name == '[]=') ||
|
| + (method.name == 'add') ||
|
| + (method.name == 'insert');
|
| }
|
|
|
| /**
|
| @@ -362,13 +359,13 @@ abstract class TracerVisitor<T extends TypeInformation>
|
|
|
| bool isClosure(Element element) {
|
| if (!element.isFunction) return false;
|
| +
|
| /// Creating an instance of a class that implements [Function] also
|
| /// closurizes the corresponding [call] member. We do not currently
|
| /// track these, thus the check for [isClosurized] on such a method will
|
| /// return false. Instead we catch that case here for now.
|
| // TODO(herhut): Handle creation of closures from instances of Function.
|
| - if (element.isInstanceMember &&
|
| - element.name == Identifiers.call) {
|
| + if (element.isInstanceMember && element.name == Identifiers.call) {
|
| return true;
|
| }
|
| Element outermost = element.outermostEnclosingMemberOrTopLevel;
|
|
|