Chromium Code Reviews| 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; |