Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(401)

Unified Diff: sdk/lib/_internal/compiler/implementation/inferrer/node_tracer.dart

Issue 216673003: Allow use of [keys] from a map by using different bailout strategy. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Karl's comments and some further fixes Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698