Index: sdk/lib/_internal/compiler/implementation/inferrer/node_tracer.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/node_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/node_tracer.dart |
index 73a81dc51fb9f636ac6b1b4bea8f8aa103489a80..b1ba510d50e0f7f1e3d443896b592548184b31fd 100644 |
--- a/sdk/lib/_internal/compiler/implementation/inferrer/node_tracer.dart |
+++ b/sdk/lib/_internal/compiler/implementation/inferrer/node_tracer.dart |
@@ -60,7 +60,10 @@ Set<String> doesNotEscapeMapSet = new Set<String>.from( |
'length', |
'clear', |
'containsKey', |
- 'containsValue' |
+ 'containsValue', |
+ '[]=', |
+ // [keys] only allows key values to escape, which we do not track. |
floitsch
2014/04/02 16:55:29
put this comment above the "[]=" and reformulate.
|
+ 'keys' |
]); |
abstract class TracerVisitor implements TypeInformationVisitor { |
@@ -145,7 +148,8 @@ abstract class TracerVisitor implements TypeInformationVisitor { |
} |
void visitKeyInMapTypeInformation(KeyInMapTypeInformation info) { |
- addNewEscapeInformation(info); |
+ // We do not track the use of keys from a map, so we have to bail. |
+ bailout('Used as key in Map'); |
} |
void visitValueInMapTypeInformation(ValueInMapTypeInformation info) { |
@@ -213,6 +217,11 @@ abstract class TracerVisitor implements TypeInformationVisitor { |
} |
} |
+ /** |
+ * Checks whether this is a call to a list adding method. The definition |
+ * of what list adding means has to stay in sync with |
+ * [isParameterOfListAddingMethod]. |
+ */ |
bool isAddedToContainer(DynamicCallSiteTypeInformation info) { |
if (info.arguments == null) return false; |
var receiverType = info.receiver.type; |
@@ -224,13 +233,33 @@ abstract class TracerVisitor implements TypeInformationVisitor { |
|| (selectorName == 'add' && currentUser == arguments[0]); |
} |
- bool isValueAddedToMap(DynamicCallSiteTypeInformation info) { |
+ bool isIndexSetOnMap(DynamicCallSiteTypeInformation info) { |
if (info.arguments == null) return false; |
var receiverType = info.receiver.type; |
if (!receiverType.isMap) return false; |
String selectorName = info.selector.name; |
List<TypeInformation> arguments = info.arguments.positional; |
- return selectorName == '[]=' && currentUser == arguments[1]; |
+ return selectorName == '[]='; |
+ } |
+ |
+ /** |
+ * Checks whether this is a call to a map adding method for values. The |
+ * definition of map adding method has to stay in sync with |
+ * [isParameterOfMapAddingMethod]. |
+ */ |
+ bool isValueAddedToMap(DynamicCallSiteTypeInformation info) { |
+ return isIndexSetOnMap(info) && |
+ currentUser == info.arguments.positional[1]; |
+ } |
+ |
+ /** |
+ * Checks whether this is a call to a map adding method for keys. The |
+ * definition of map adding method has to stay in sync with |
+ * [isParameterOfMapAddingMethod]. |
+ */ |
+ bool isKeyAddedToMap(DynamicCallSiteTypeInformation info) { |
+ return isIndexSetOnMap(info) && |
+ currentUser == info.arguments.positional[0]; |
} |
void visitDynamicCallSiteTypeInformation( |
@@ -259,6 +288,9 @@ abstract class TracerVisitor implements TypeInformationVisitor { |
// [ContainerTypeMask] above. |
bailout('Stored in too many maps'); |
} |
+ } else if (isKeyAddedToMap(info)) { |
+ // We do not track the use of keys from a map, so we have to bail. |
+ bailout('Used as key in Map'); |
} |
Iterable<Element> inferredTargetTypes = info.targets.map((element) { |
@@ -269,6 +301,11 @@ abstract class TracerVisitor implements TypeInformationVisitor { |
} |
} |
+ /** |
+ * Check whether element is the parameter of a list adding method. |
+ * The definition of what a list adding method is has to stay in sync with |
+ * [isAddedToContainer]. |
+ */ |
bool isParameterOfListAddingMethod(Element element) { |
if (!element.isParameter()) return false; |
if (element.getEnclosingClass() != compiler.backend.listImplementation) { |
@@ -280,6 +317,20 @@ abstract class TracerVisitor implements TypeInformationVisitor { |
|| (method.name == 'insert'); |
} |
+ /** |
+ * Check whether element is the parameter of a list adding method. |
+ * The definition of what a list adding method is has to stay in sync with |
+ * [isValueAddedToMap] and [isKeyAddedToMap]. |
+ */ |
+ bool isParameterOfMapAddingMethod(Element element) { |
+ if (!element.isParameter()) return false; |
+ if (element.getEnclosingClass() != compiler.backend.mapImplementation) { |
+ return false; |
+ } |
+ Element method = element.enclosingElement; |
+ return (method.name == '[]='); |
+ } |
+ |
bool isClosure(Element element) { |
if (!element.isFunction()) return false; |
Element outermost = element.getOutermostEnclosingMemberOrTopLevel(); |
@@ -301,7 +352,8 @@ abstract class TracerVisitor implements TypeInformationVisitor { |
if (compiler.backend.isNeededForReflection(info.element)) { |
bailout('Escape in reflection'); |
} |
- if (isParameterOfListAddingMethod(info.element)) { |
+ if (isParameterOfListAddingMethod(info.element) || |
+ isParameterOfMapAddingMethod(info.element)) { |
// These elements are being handled in |
// [visitDynamicCallSiteTypeInformation]. |
return; |