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

Side by Side 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: Created 6 years, 8 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of type_graph_inferrer; 5 part of type_graph_inferrer;
6 6
7 // A set of selectors we know do not escape the elements inside the 7 // A set of selectors we know do not escape the elements inside the
8 // list. 8 // list.
9 Set<String> doesNotEscapeListSet = new Set<String>.from( 9 Set<String> doesNotEscapeListSet = new Set<String>.from(
10 const <String>[ 10 const <String>[
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 'hashCode', 53 'hashCode',
54 'toString', 54 'toString',
55 'noSuchMethod', 55 'noSuchMethod',
56 'runtimeType', 56 'runtimeType',
57 // from Map. 57 // from Map.
58 'isEmpty', 58 'isEmpty',
59 'isNotEmpty', 59 'isNotEmpty',
60 'length', 60 'length',
61 'clear', 61 'clear',
62 'containsKey', 62 'containsKey',
63 'containsValue' 63 'containsValue',
64 // [keys] only allows key values to escape, which we do not track.
65 'keys'
64 ]); 66 ]);
65 67
66 abstract class TracerVisitor implements TypeInformationVisitor { 68 abstract class TracerVisitor implements TypeInformationVisitor {
67 final TypeInformation tracedType; 69 final TypeInformation tracedType;
68 final TypeGraphInferrerEngine inferrer; 70 final TypeGraphInferrerEngine inferrer;
69 final Compiler compiler; 71 final Compiler compiler;
70 72
71 static const int MAX_ANALYSIS_COUNT = 16; 73 static const int MAX_ANALYSIS_COUNT = 16;
72 final Setlet<Element> analyzedElements = new Setlet<Element>(); 74 final Setlet<Element> analyzedElements = new Setlet<Element>();
73 75
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 if (user.selector.isIndex()) { 208 if (user.selector.isIndex()) {
207 addNewEscapeInformation(user); 209 addNewEscapeInformation(user);
208 } else if (!doesNotEscapeMapSet.contains(user.selector.name)) { 210 } else if (!doesNotEscapeMapSet.contains(user.selector.name)) {
209 bailout('Escape from a map via [${user.selector.name}]'); 211 bailout('Escape from a map via [${user.selector.name}]');
210 } 212 }
211 }); 213 });
212 }); 214 });
213 } 215 }
214 } 216 }
215 217
218 /*
219 * Checks whether this is a call to a list adding method. The definition
220 * of what list adding means has to stay in sync with
221 * [isParameterOfListAddingMethod].
222 */
216 bool isAddedToContainer(DynamicCallSiteTypeInformation info) { 223 bool isAddedToContainer(DynamicCallSiteTypeInformation info) {
217 if (info.arguments == null) return false; 224 if (info.arguments == null) return false;
218 var receiverType = info.receiver.type; 225 var receiverType = info.receiver.type;
219 if (!receiverType.isContainer) return false; 226 if (!receiverType.isContainer) return false;
220 String selectorName = info.selector.name; 227 String selectorName = info.selector.name;
221 List<TypeInformation> arguments = info.arguments.positional; 228 List<TypeInformation> arguments = info.arguments.positional;
222 return (selectorName == '[]=' && currentUser == arguments[1]) 229 return (selectorName == '[]=' && currentUser == arguments[1])
223 || (selectorName == 'insert' && currentUser == arguments[0]) 230 || (selectorName == 'insert' && currentUser == arguments[0])
224 || (selectorName == 'add' && currentUser == arguments[0]); 231 || (selectorName == 'add' && currentUser == arguments[0]);
225 } 232 }
226 233
227 bool isValueAddedToMap(DynamicCallSiteTypeInformation info) { 234 bool isIndexSetOnMap(DynamicCallSiteTypeInformation info) {
228 if (info.arguments == null) return false; 235 if (info.arguments == null) return false;
229 var receiverType = info.receiver.type; 236 var receiverType = info.receiver.type;
230 if (!receiverType.isMap) return false; 237 if (!receiverType.isMap) return false;
231 String selectorName = info.selector.name; 238 String selectorName = info.selector.name;
232 List<TypeInformation> arguments = info.arguments.positional; 239 List<TypeInformation> arguments = info.arguments.positional;
233 return selectorName == '[]=' && currentUser == arguments[1]; 240 return selectorName == '[]=';
241 }
242
243 /* Checks whether this is a call to a map adding method for values. The
karlklose 2014/03/31 14:39:27 Line break after '/*'. Consider using '///' instea
herhut 2014/04/02 13:25:53 Done.
244 * definition of map adding method has to stay in sync with
245 * [isParameterOfMapAddingMethod].
246 */
247 bool isValueAddedToMap(DynamicCallSiteTypeInformation info) {
248 return isIndexSetOnMap(info) &&
249 currentUser == info.arguments.positional[1];
250 }
251
252 /* Checks whether this is a call to a map adding method for keys. The
253 * definition of map adding method has to stay in sync with
254 * [isParameterOfMapAddingMethod].
255 */
256 bool isKeyAddedToMap(DynamicCallSiteTypeInformation info) {
257 return isIndexSetOnMap(info) &&
258 currentUser == info.arguments.positional[0];
234 } 259 }
235 260
236 void visitDynamicCallSiteTypeInformation( 261 void visitDynamicCallSiteTypeInformation(
237 DynamicCallSiteTypeInformation info) { 262 DynamicCallSiteTypeInformation info) {
238 if (isAddedToContainer(info)) { 263 if (isAddedToContainer(info)) {
239 ContainerTypeMask mask = info.receiver.type; 264 ContainerTypeMask mask = info.receiver.type;
240 265
241 if (mask.allocationNode != null) { 266 if (mask.allocationNode != null) {
242 ListTypeInformation list = 267 ListTypeInformation list =
243 inferrer.types.allocatedLists[mask.allocationNode]; 268 inferrer.types.allocatedLists[mask.allocationNode];
244 listsToAnalyze.add(list); 269 listsToAnalyze.add(list);
245 } else { 270 } else {
246 // The [ContainerTypeMask] is a union of two containers, and 271 // The [ContainerTypeMask] is a union of two containers, and
247 // we lose track of where these containers have been allocated 272 // we lose track of where these containers have been allocated
248 // at this point. 273 // at this point.
249 bailout('Stored in too many containers'); 274 bailout('Stored in too many containers');
250 } 275 }
251 } else if (isValueAddedToMap(info)) { 276 } else if (isValueAddedToMap(info)) {
252 MapTypeMask mask = info.receiver.type; 277 MapTypeMask mask = info.receiver.type;
253 if (mask.allocationNode != null) { 278 if (mask.allocationNode != null) {
254 MapTypeInformation map = 279 MapTypeInformation map =
255 inferrer.types.allocatedMaps[mask.allocationNode]; 280 inferrer.types.allocatedMaps[mask.allocationNode];
256 mapsToAnalyze.add(map); 281 mapsToAnalyze.add(map);
257 } else { 282 } else {
258 // The [MapTypeMask] is a union. See comment for 283 // The [MapTypeMask] is a union. See comment for
259 // [ContainerTypeMask] above. 284 // [ContainerTypeMask] above.
260 bailout('Stored in too many maps'); 285 bailout('Stored in too many maps');
261 } 286 }
287 } else if (isKeyAddedToMap(info)) {
288 // We do not track the use of keys from a map, so we have to bail.
289 bailout('Used as key in Map');
262 } 290 }
263 291
264 Iterable<Element> inferredTargetTypes = info.targets.map((element) { 292 Iterable<Element> inferredTargetTypes = info.targets.map((element) {
265 return inferrer.types.getInferredTypeOf(element); 293 return inferrer.types.getInferredTypeOf(element);
266 }); 294 });
267 if (inferredTargetTypes.any((user) => user == currentUser)) { 295 if (inferredTargetTypes.any((user) => user == currentUser)) {
268 addNewEscapeInformation(info); 296 addNewEscapeInformation(info);
269 } 297 }
270 } 298 }
271 299
300 /*
301 * Check whether element is the parameter of a list adding method.
302 * The definition of what a list adding method is has to stay in sync with
303 * [isAddedToContainer].
304 */
272 bool isParameterOfListAddingMethod(Element element) { 305 bool isParameterOfListAddingMethod(Element element) {
273 if (!element.isParameter()) return false; 306 if (!element.isParameter()) return false;
274 if (element.getEnclosingClass() != compiler.backend.listImplementation) { 307 if (element.getEnclosingClass() != compiler.backend.listImplementation) {
275 return false; 308 return false;
276 } 309 }
277 Element method = element.enclosingElement; 310 Element method = element.enclosingElement;
278 return (method.name == '[]=') 311 return (method.name == '[]=')
279 || (method.name == 'add') 312 || (method.name == 'add')
280 || (method.name == 'insert'); 313 || (method.name == 'insert');
281 } 314 }
282 315
316 /*
317 * Check whether element is the parameter of a list adding method.
318 * The definition of what a list adding method is has to stay in sync with
319 * [isValueAddedToMap] and [isKeyAddedToMap].
320 */
321 bool isParameterOfMapAddingMethod(Element element) {
322 if (!element.isParameter()) return false;
323 if (element.getEnclosingClass() != compiler.backend.mapImplementation) {
324 return false;
325 }
326 Element method = element.enclosingElement;
327 return (method.name == '[]=');
328 }
329
283 bool isClosure(Element element) { 330 bool isClosure(Element element) {
284 if (!element.isFunction()) return false; 331 if (!element.isFunction()) return false;
285 Element outermost = element.getOutermostEnclosingMemberOrTopLevel(); 332 Element outermost = element.getOutermostEnclosingMemberOrTopLevel();
286 return outermost.declaration != element.declaration; 333 return outermost.declaration != element.declaration;
287 } 334 }
288 335
289 void visitElementTypeInformation(ElementTypeInformation info) { 336 void visitElementTypeInformation(ElementTypeInformation info) {
290 Element element = info.element; 337 Element element = info.element;
291 if (element.isParameter() 338 if (element.isParameter()
292 && inferrer.isNativeElement(element.enclosingElement)) { 339 && inferrer.isNativeElement(element.enclosingElement)) {
293 bailout('Passed to a native method'); 340 bailout('Passed to a native method');
294 } 341 }
295 if (info.isClosurized()) { 342 if (info.isClosurized()) {
296 bailout('Returned from a closurized method'); 343 bailout('Returned from a closurized method');
297 } 344 }
298 if (isClosure(info.element)) { 345 if (isClosure(info.element)) {
299 bailout('Returned from a closure'); 346 bailout('Returned from a closure');
300 } 347 }
301 if (compiler.backend.isNeededForReflection(info.element)) { 348 if (compiler.backend.isNeededForReflection(info.element)) {
302 bailout('Escape in reflection'); 349 bailout('Escape in reflection');
303 } 350 }
304 if (isParameterOfListAddingMethod(info.element)) { 351 if (isParameterOfListAddingMethod(info.element) ||
352 isParameterOfMapAddingMethod(info.element)) {
305 // These elements are being handled in 353 // These elements are being handled in
306 // [visitDynamicCallSiteTypeInformation]. 354 // [visitDynamicCallSiteTypeInformation].
307 return; 355 return;
308 } 356 }
309 addNewEscapeInformation(info); 357 addNewEscapeInformation(info);
310 } 358 }
311 } 359 }
OLDNEW
« 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