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

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

Issue 212693003: Fix handling of union on DictionaryTypeMask. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: improved handling of map keys 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 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'
floitsch 2014/03/28 09:53:03 Add comment.
64 ]); 65 ]);
65 66
66 abstract class TracerVisitor implements TypeInformationVisitor { 67 abstract class TracerVisitor implements TypeInformationVisitor {
67 final TypeInformation tracedType; 68 final TypeInformation tracedType;
68 final TypeGraphInferrerEngine inferrer; 69 final TypeGraphInferrerEngine inferrer;
69 final Compiler compiler; 70 final Compiler compiler;
70 71
71 static const int MAX_ANALYSIS_COUNT = 16; 72 static const int MAX_ANALYSIS_COUNT = 16;
72 final Setlet<Element> analyzedElements = new Setlet<Element>(); 73 final Setlet<Element> analyzedElements = new Setlet<Element>();
73 74
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 if (user.selector.isIndex()) { 207 if (user.selector.isIndex()) {
207 addNewEscapeInformation(user); 208 addNewEscapeInformation(user);
208 } else if (!doesNotEscapeMapSet.contains(user.selector.name)) { 209 } else if (!doesNotEscapeMapSet.contains(user.selector.name)) {
209 bailout('Escape from a map via [${user.selector.name}]'); 210 bailout('Escape from a map via [${user.selector.name}]');
210 } 211 }
211 }); 212 });
212 }); 213 });
213 } 214 }
214 } 215 }
215 216
217 /*
218 * Checks whether this is a call to a list adding method. The definition
219 * of what list adding means has to stay in sync with
220 * [isParameterOfListAddingMethod].
221 */
216 bool isAddedToContainer(DynamicCallSiteTypeInformation info) { 222 bool isAddedToContainer(DynamicCallSiteTypeInformation info) {
217 if (info.arguments == null) return false; 223 if (info.arguments == null) return false;
218 var receiverType = info.receiver.type; 224 var receiverType = info.receiver.type;
219 if (!receiverType.isContainer) return false; 225 if (!receiverType.isContainer) return false;
220 String selectorName = info.selector.name; 226 String selectorName = info.selector.name;
221 List<TypeInformation> arguments = info.arguments.positional; 227 List<TypeInformation> arguments = info.arguments.positional;
222 return (selectorName == '[]=' && currentUser == arguments[1]) 228 return (selectorName == '[]=' && currentUser == arguments[1])
223 || (selectorName == 'insert' && currentUser == arguments[0]) 229 || (selectorName == 'insert' && currentUser == arguments[0])
224 || (selectorName == 'add' && currentUser == arguments[0]); 230 || (selectorName == 'add' && currentUser == arguments[0]);
225 } 231 }
226 232
227 bool isValueAddedToMap(DynamicCallSiteTypeInformation info) { 233 bool isIndexSetOnMap(DynamicCallSiteTypeInformation info) {
228 if (info.arguments == null) return false; 234 if (info.arguments == null) return false;
229 var receiverType = info.receiver.type; 235 var receiverType = info.receiver.type;
230 if (!receiverType.isMap) return false; 236 if (!receiverType.isMap) return false;
231 String selectorName = info.selector.name; 237 String selectorName = info.selector.name;
232 List<TypeInformation> arguments = info.arguments.positional; 238 List<TypeInformation> arguments = info.arguments.positional;
233 return selectorName == '[]=' && currentUser == arguments[1]; 239 return selectorName == '[]=';
240 }
241
242 /* Checks whether this is a call to a map adding method for values. The
243 * definition of map adding method has to stay in sync with
244 * [isParameterOfMapAddingMethod].
245 */
246 bool isValueAddedToMap(DynamicCallSiteTypeInformation info) {
247 return isIndexSetOnMap(info) &&
248 currentUser == info.arguments.positional[1];
249 }
250
251 /* Checks whether this is a call to a map adding method for keys. The
252 * definition of map adding method has to stay in sync with
253 * [isParameterOfMapAddingMethod].
254 */
255 bool isKeyAddedToMap(DynamicCallSiteTypeInformation info) {
256 return isIndexSetOnMap(info) &&
257 currentUser == info.arguments.positional[0];
234 } 258 }
235 259
236 void visitDynamicCallSiteTypeInformation( 260 void visitDynamicCallSiteTypeInformation(
237 DynamicCallSiteTypeInformation info) { 261 DynamicCallSiteTypeInformation info) {
238 if (isAddedToContainer(info)) { 262 if (isAddedToContainer(info)) {
239 ContainerTypeMask mask = info.receiver.type; 263 ContainerTypeMask mask = info.receiver.type;
240 264
241 if (mask.allocationNode != null) { 265 if (mask.allocationNode != null) {
242 ListTypeInformation list = 266 ListTypeInformation list =
243 inferrer.types.allocatedLists[mask.allocationNode]; 267 inferrer.types.allocatedLists[mask.allocationNode];
244 listsToAnalyze.add(list); 268 listsToAnalyze.add(list);
245 } else { 269 } else {
246 // The [ContainerTypeMask] is a union of two containers, and 270 // The [ContainerTypeMask] is a union of two containers, and
247 // we lose track of where these containers have been allocated 271 // we lose track of where these containers have been allocated
248 // at this point. 272 // at this point.
249 bailout('Stored in too many containers'); 273 bailout('Stored in too many containers');
250 } 274 }
251 } else if (isValueAddedToMap(info)) { 275 } else if (isValueAddedToMap(info)) {
252 MapTypeMask mask = info.receiver.type; 276 MapTypeMask mask = info.receiver.type;
253 if (mask.allocationNode != null) { 277 if (mask.allocationNode != null) {
254 MapTypeInformation map = 278 MapTypeInformation map =
255 inferrer.types.allocatedMaps[mask.allocationNode]; 279 inferrer.types.allocatedMaps[mask.allocationNode];
256 mapsToAnalyze.add(map); 280 mapsToAnalyze.add(map);
257 } else { 281 } else {
258 // The [MapTypeMask] is a union. See comment for 282 // The [MapTypeMask] is a union. See comment for
259 // [ContainerTypeMask] above. 283 // [ContainerTypeMask] above.
260 bailout('Stored in too many maps'); 284 bailout('Stored in too many maps');
261 } 285 }
286 } else if (isKeyAddedToMap(info)) {
287 bailout('Used as key in Map');
262 } 288 }
263 289
264 Iterable<Element> inferredTargetTypes = info.targets.map((element) { 290 Iterable<Element> inferredTargetTypes = info.targets.map((element) {
265 return inferrer.types.getInferredTypeOf(element); 291 return inferrer.types.getInferredTypeOf(element);
266 }); 292 });
267 if (inferredTargetTypes.any((user) => user == currentUser)) { 293 if (inferredTargetTypes.any((user) => user == currentUser)) {
268 addNewEscapeInformation(info); 294 addNewEscapeInformation(info);
269 } 295 }
270 } 296 }
271 297
298 /*
299 * Check whether element is the parameter of a list adding method.
300 * The definition of what a list adding method is has to stay in sync with
301 * [isAddedToContainer].
302 */
272 bool isParameterOfListAddingMethod(Element element) { 303 bool isParameterOfListAddingMethod(Element element) {
273 if (!element.isParameter()) return false; 304 if (!element.isParameter()) return false;
274 if (element.getEnclosingClass() != compiler.backend.listImplementation) { 305 if (element.getEnclosingClass() != compiler.backend.listImplementation) {
275 return false; 306 return false;
276 } 307 }
277 Element method = element.enclosingElement; 308 Element method = element.enclosingElement;
278 return (method.name == '[]=') 309 return (method.name == '[]=')
279 || (method.name == 'add') 310 || (method.name == 'add')
280 || (method.name == 'insert'); 311 || (method.name == 'insert');
281 } 312 }
282 313
314 /*
315 * Check whether element is the parameter of a list adding method.
316 * The definition of what a list adding method is has to stay in sync with
317 * [isValueAddedToMap].
318 */
319 bool isParameterOfMapAddingMethod(Element element) {
320 if (!element.isParameter()) return false;
321 if (element.getEnclosingClass() != compiler.backend.mapImplementation) {
322 return false;
323 }
324 Element method = element.enclosingElement;
325 return (method.name == '[]=');
326 }
327
283 bool isClosure(Element element) { 328 bool isClosure(Element element) {
284 if (!element.isFunction()) return false; 329 if (!element.isFunction()) return false;
285 Element outermost = element.getOutermostEnclosingMemberOrTopLevel(); 330 Element outermost = element.getOutermostEnclosingMemberOrTopLevel();
286 return outermost.declaration != element.declaration; 331 return outermost.declaration != element.declaration;
287 } 332 }
288 333
289 void visitElementTypeInformation(ElementTypeInformation info) { 334 void visitElementTypeInformation(ElementTypeInformation info) {
290 Element element = info.element; 335 Element element = info.element;
291 if (element.isParameter() 336 if (element.isParameter()
292 && inferrer.isNativeElement(element.enclosingElement)) { 337 && inferrer.isNativeElement(element.enclosingElement)) {
293 bailout('Passed to a native method'); 338 bailout('Passed to a native method');
294 } 339 }
295 if (info.isClosurized()) { 340 if (info.isClosurized()) {
296 bailout('Returned from a closurized method'); 341 bailout('Returned from a closurized method');
297 } 342 }
298 if (isClosure(info.element)) { 343 if (isClosure(info.element)) {
299 bailout('Returned from a closure'); 344 bailout('Returned from a closure');
300 } 345 }
301 if (compiler.backend.isNeededForReflection(info.element)) { 346 if (compiler.backend.isNeededForReflection(info.element)) {
302 bailout('Escape in reflection'); 347 bailout('Escape in reflection');
303 } 348 }
304 if (isParameterOfListAddingMethod(info.element)) { 349 if (isParameterOfListAddingMethod(info.element) ||
350 isParameterOfMapAddingMethod(info.element)) {
305 // These elements are being handled in 351 // These elements are being handled in
306 // [visitDynamicCallSiteTypeInformation]. 352 // [visitDynamicCallSiteTypeInformation].
307 return; 353 return;
308 } 354 }
309 addNewEscapeInformation(info); 355 addNewEscapeInformation(info);
310 } 356 }
311 } 357 }
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