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

Side by Side Diff: pkg/compiler/lib/src/inferrer/node_tracer.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 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
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 library compiler.src.inferrer.node_tracer; 5 library compiler.src.inferrer.node_tracer;
6 6
7 import '../common/names.dart' show Identifiers; 7 import '../common/names.dart' show Identifiers;
8 import '../compiler.dart' show Compiler; 8 import '../compiler.dart' show Compiler;
9 import '../elements/elements.dart'; 9 import '../elements/elements.dart';
10 import '../types/types.dart' show ContainerTypeMask, MapTypeMask; 10 import '../types/types.dart' show ContainerTypeMask, MapTypeMask;
11 import '../util/util.dart' show Setlet; 11 import '../util/util.dart' show Setlet;
12 12
13 import 'type_graph_inferrer.dart' show TypeGraphInferrerEngine; 13 import 'type_graph_inferrer.dart' show TypeGraphInferrerEngine;
14 import 'type_graph_nodes.dart'; 14 import 'type_graph_nodes.dart';
15 import 'debug.dart' as debug; 15 import 'debug.dart' as debug;
16 16
17 // A set of selectors we know do not escape the elements inside the 17 // A set of selectors we know do not escape the elements inside the
18 // list. 18 // list.
19 Set<String> doesNotEscapeListSet = new Set<String>.from( 19 Set<String> doesNotEscapeListSet = new Set<String>.from(const <String>[
20 const <String>[ 20 // From Object.
21 // From Object. 21 '==',
22 '==', 22 'hashCode',
23 'hashCode', 23 'toString',
24 'toString', 24 'noSuchMethod',
25 'noSuchMethod', 25 'runtimeType',
26 'runtimeType',
27 26
28 // From Iterable. 27 // From Iterable.
29 'isEmpty', 28 'isEmpty',
30 'isNotEmpty', 29 'isNotEmpty',
31 'length', 30 'length',
32 'contains', 31 'contains',
33 'join', 32 'join',
34 33
35 // From List. 34 // From List.
36 'add', 35 'add',
37 'addAll', 36 'addAll',
38 'clear', 37 'clear',
39 'fillRange', 38 'fillRange',
40 'indexOf', 39 'indexOf',
41 'insert', 40 'insert',
42 'insertAll', 41 'insertAll',
43 'lastIndexOf', 42 'lastIndexOf',
44 'remove', 43 'remove',
45 'removeRange', 44 'removeRange',
46 'replaceRange', 45 'replaceRange',
47 'setAll', 46 'setAll',
48 'setRange', 47 'setRange',
49 'shuffle', 48 'shuffle',
50 '[]=', 49 '[]=',
51 50
52 // From JSArray. 51 // From JSArray.
53 'checkMutable', 52 'checkMutable',
54 'checkGrowable', 53 'checkGrowable',
55 ]); 54 ]);
56 55
57 Set<String> doesNotEscapeMapSet = new Set<String>.from( 56 Set<String> doesNotEscapeMapSet = new Set<String>.from(const <String>[
58 const <String>[ 57 // From Object.
59 // From Object. 58 '==',
60 '==', 59 'hashCode',
61 'hashCode', 60 'toString',
62 'toString', 61 'noSuchMethod',
63 'noSuchMethod', 62 'runtimeType',
64 'runtimeType', 63 // from Map.
65 // from Map. 64 'isEmpty',
66 'isEmpty', 65 'isNotEmpty',
67 'isNotEmpty', 66 'length',
68 'length', 67 'clear',
69 'clear', 68 'containsKey',
70 'containsKey', 69 'containsValue',
71 'containsValue', 70 '[]=',
72 '[]=', 71 // [keys] only allows key values to escape, which we do not track.
73 // [keys] only allows key values to escape, which we do not track. 72 'keys'
74 'keys' 73 ]);
75 ]);
76 74
77 /// Common logic to trace a value through the type inference graph nodes. 75 /// Common logic to trace a value through the type inference graph nodes.
78 abstract class TracerVisitor<T extends TypeInformation> 76 abstract class TracerVisitor<T extends TypeInformation>
79 implements TypeInformationVisitor { 77 implements TypeInformationVisitor {
80 final T tracedType; 78 final T tracedType;
81 final TypeGraphInferrerEngine inferrer; 79 final TypeGraphInferrerEngine inferrer;
82 final Compiler compiler; 80 final Compiler compiler;
83 81
84 static const int MAX_ANALYSIS_COUNT = 16; 82 static const int MAX_ANALYSIS_COUNT = 16;
85 final Setlet<Element> analyzedElements = new Setlet<Element>(); 83 final Setlet<Element> analyzedElements = new Setlet<Element>();
86 84
87 TracerVisitor(this.tracedType, TypeGraphInferrerEngine inferrer) 85 TracerVisitor(this.tracedType, TypeGraphInferrerEngine inferrer)
88 : this.inferrer = inferrer, this.compiler = inferrer.compiler; 86 : this.inferrer = inferrer,
87 this.compiler = inferrer.compiler;
89 88
90 // Work list that gets populated with [TypeInformation] that could 89 // Work list that gets populated with [TypeInformation] that could
91 // contain the container. 90 // contain the container.
92 final List<TypeInformation> workList = <TypeInformation>[]; 91 final List<TypeInformation> workList = <TypeInformation>[];
93 92
94 // Work list of lists to analyze after analyzing the users of a 93 // Work list of lists to analyze after analyzing the users of a
95 // [TypeInformation]. We know the [tracedType] has been stored in these 94 // [TypeInformation]. We know the [tracedType] has been stored in these
96 // lists and we must check how it escapes from these lists. 95 // lists and we must check how it escapes from these lists.
97 final List<ListTypeInformation> listsToAnalyze = 96 final List<ListTypeInformation> listsToAnalyze = <ListTypeInformation>[];
98 <ListTypeInformation>[];
99 // Work list of maps to analyze after analyzing the users of a 97 // Work list of maps to analyze after analyzing the users of a
100 // [TypeInformation]. We know the [tracedType] has been stored in these 98 // [TypeInformation]. We know the [tracedType] has been stored in these
101 // maps and we must check how it escapes from these maps. 99 // maps and we must check how it escapes from these maps.
102 final List<MapTypeInformation> mapsToAnalyze = <MapTypeInformation>[]; 100 final List<MapTypeInformation> mapsToAnalyze = <MapTypeInformation>[];
103 101
104 final Setlet<TypeInformation> flowsInto = new Setlet<TypeInformation>(); 102 final Setlet<TypeInformation> flowsInto = new Setlet<TypeInformation>();
105 103
106 // The current [TypeInformation] in the analysis. 104 // The current [TypeInformation] in the analysis.
107 TypeInformation currentUser; 105 TypeInformation currentUser;
108 bool continueAnalyzing = true; 106 bool continueAnalyzing = true;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 addNewEscapeInformation(info); 177 addNewEscapeInformation(info);
180 } 178 }
181 179
182 void visitListTypeInformation(ListTypeInformation info) { 180 void visitListTypeInformation(ListTypeInformation info) {
183 listsToAnalyze.add(info); 181 listsToAnalyze.add(info);
184 } 182 }
185 183
186 void visitMapTypeInformation(MapTypeInformation info) { 184 void visitMapTypeInformation(MapTypeInformation info) {
187 mapsToAnalyze.add(info); 185 mapsToAnalyze.add(info);
188 } 186 }
187
189 void visitConcreteTypeInformation(ConcreteTypeInformation info) {} 188 void visitConcreteTypeInformation(ConcreteTypeInformation info) {}
190 189
191 void visitStringLiteralTypeInformation(StringLiteralTypeInformation info) {} 190 void visitStringLiteralTypeInformation(StringLiteralTypeInformation info) {}
192 191
193 void visitBoolLiteralTypeInformation(BoolLiteralTypeInformation info) {} 192 void visitBoolLiteralTypeInformation(BoolLiteralTypeInformation info) {}
194 193
195 void visitClosureTypeInformation(ClosureTypeInformation info) {} 194 void visitClosureTypeInformation(ClosureTypeInformation info) {}
196 195
197 void visitClosureCallSiteTypeInformation( 196 void visitClosureCallSiteTypeInformation(
198 ClosureCallSiteTypeInformation info) {} 197 ClosureCallSiteTypeInformation info) {}
199 198
200 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { 199 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
201 Element called = info.calledElement; 200 Element called = info.calledElement;
202 if (inferrer.types.getInferredTypeOf(called) == currentUser) { 201 if (inferrer.types.getInferredTypeOf(called) == currentUser) {
203 addNewEscapeInformation(info); 202 addNewEscapeInformation(info);
204 } 203 }
205 } 204 }
206 205
207 void analyzeStoredIntoList(ListTypeInformation list) { 206 void analyzeStoredIntoList(ListTypeInformation list) {
208 inferrer.analyzeListAndEnqueue(list); 207 inferrer.analyzeListAndEnqueue(list);
209 if (list.bailedOut) { 208 if (list.bailedOut) {
210 bailout('Stored in a list that bailed out'); 209 bailout('Stored in a list that bailed out');
211 } else { 210 } else {
212 list.flowsInto.forEach((flow) { 211 list.flowsInto.forEach((flow) {
213 flow.users.forEach((user) { 212 flow.users.forEach((user) {
214 if (user is !DynamicCallSiteTypeInformation) return; 213 if (user is! DynamicCallSiteTypeInformation) return;
215 if (user.receiver != flow) return; 214 if (user.receiver != flow) return;
216 if (inferrer.returnsListElementTypeSet.contains(user.selector)) { 215 if (inferrer.returnsListElementTypeSet.contains(user.selector)) {
217 addNewEscapeInformation(user); 216 addNewEscapeInformation(user);
218 } else if (!doesNotEscapeListSet.contains(user.selector.name)) { 217 } else if (!doesNotEscapeListSet.contains(user.selector.name)) {
219 bailout('Escape from a list via [${user.selector.name}]'); 218 bailout('Escape from a list via [${user.selector.name}]');
220 } 219 }
221 }); 220 });
222 }); 221 });
223 } 222 }
224 } 223 }
225 224
226 void analyzeStoredIntoMap(MapTypeInformation map) { 225 void analyzeStoredIntoMap(MapTypeInformation map) {
227 inferrer.analyzeMapAndEnqueue(map); 226 inferrer.analyzeMapAndEnqueue(map);
228 if (map.bailedOut) { 227 if (map.bailedOut) {
229 bailout('Stored in a map that bailed out'); 228 bailout('Stored in a map that bailed out');
230 } else { 229 } else {
231 map.flowsInto.forEach((flow) { 230 map.flowsInto.forEach((flow) {
232 flow.users.forEach((user) { 231 flow.users.forEach((user) {
233 if (user is !DynamicCallSiteTypeInformation) return; 232 if (user is! DynamicCallSiteTypeInformation) return;
234 if (user.receiver != flow) return; 233 if (user.receiver != flow) return;
235 if (user.selector.isIndex) { 234 if (user.selector.isIndex) {
236 addNewEscapeInformation(user); 235 addNewEscapeInformation(user);
237 } else if (!doesNotEscapeMapSet.contains(user.selector.name)) { 236 } else if (!doesNotEscapeMapSet.contains(user.selector.name)) {
238 bailout('Escape from a map via [${user.selector.name}]'); 237 bailout('Escape from a map via [${user.selector.name}]');
239 } 238 }
240 }); 239 });
241 }); 240 });
242 } 241 }
243 } 242 }
244 243
245 /** 244 /**
246 * Checks whether this is a call to a list adding method. The definition 245 * Checks whether this is a call to a list adding method. The definition
247 * of what list adding means has to stay in sync with 246 * of what list adding means has to stay in sync with
248 * [isParameterOfListAddingMethod]. 247 * [isParameterOfListAddingMethod].
249 */ 248 */
250 bool isAddedToContainer(DynamicCallSiteTypeInformation info) { 249 bool isAddedToContainer(DynamicCallSiteTypeInformation info) {
251 if (info.arguments == null) return false; 250 if (info.arguments == null) return false;
252 var receiverType = info.receiver.type; 251 var receiverType = info.receiver.type;
253 if (!receiverType.isContainer) return false; 252 if (!receiverType.isContainer) return false;
254 String selectorName = info.selector.name; 253 String selectorName = info.selector.name;
255 List<TypeInformation> arguments = info.arguments.positional; 254 List<TypeInformation> arguments = info.arguments.positional;
256 return (selectorName == '[]=' && currentUser == arguments[1]) 255 return (selectorName == '[]=' && currentUser == arguments[1]) ||
257 || (selectorName == 'insert' && currentUser == arguments[1]) 256 (selectorName == 'insert' && currentUser == arguments[1]) ||
258 || (selectorName == 'add' && currentUser == arguments[0]); 257 (selectorName == 'add' && currentUser == arguments[0]);
259 } 258 }
260 259
261 bool isIndexSetOnMap(DynamicCallSiteTypeInformation info) { 260 bool isIndexSetOnMap(DynamicCallSiteTypeInformation info) {
262 if (info.arguments == null) return false; 261 if (info.arguments == null) return false;
263 var receiverType = info.receiver.type; 262 var receiverType = info.receiver.type;
264 if (!receiverType.isMap) return false; 263 if (!receiverType.isMap) return false;
265 return info.selector.name == '[]='; 264 return info.selector.name == '[]=';
266 } 265 }
267 266
268 /** 267 /**
269 * Checks whether this is a call to a map adding method for values. The 268 * Checks whether this is a call to a map adding method for values. The
270 * definition of map adding method has to stay in sync with 269 * definition of map adding method has to stay in sync with
271 * [isParameterOfMapAddingMethod]. 270 * [isParameterOfMapAddingMethod].
272 */ 271 */
273 bool isValueAddedToMap(DynamicCallSiteTypeInformation info) { 272 bool isValueAddedToMap(DynamicCallSiteTypeInformation info) {
274 return isIndexSetOnMap(info) && 273 return isIndexSetOnMap(info) && currentUser == info.arguments.positional[1];
275 currentUser == info.arguments.positional[1];
276 } 274 }
277 275
278 /** 276 /**
279 * Checks whether this is a call to a map adding method for keys. The 277 * Checks whether this is a call to a map adding method for keys. The
280 * definition of map adding method has to stay in sync with 278 * definition of map adding method has to stay in sync with
281 * [isParameterOfMapAddingMethod]. 279 * [isParameterOfMapAddingMethod].
282 */ 280 */
283 bool isKeyAddedToMap(DynamicCallSiteTypeInformation info) { 281 bool isKeyAddedToMap(DynamicCallSiteTypeInformation info) {
284 return isIndexSetOnMap(info) && 282 return isIndexSetOnMap(info) && currentUser == info.arguments.positional[0];
285 currentUser == info.arguments.positional[0];
286 } 283 }
287 284
288 void visitDynamicCallSiteTypeInformation( 285 void visitDynamicCallSiteTypeInformation(
289 DynamicCallSiteTypeInformation info) { 286 DynamicCallSiteTypeInformation info) {
290 if (isAddedToContainer(info)) { 287 if (isAddedToContainer(info)) {
291 ContainerTypeMask mask = info.receiver.type; 288 ContainerTypeMask mask = info.receiver.type;
292 289
293 if (mask.allocationNode != null) { 290 if (mask.allocationNode != null) {
294 ListTypeInformation list = 291 ListTypeInformation list =
295 inferrer.types.allocatedLists[mask.allocationNode]; 292 inferrer.types.allocatedLists[mask.allocationNode];
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 * Check whether element is the parameter of a list adding method. 331 * Check whether element is the parameter of a list adding method.
335 * The definition of what a list adding method is has to stay in sync with 332 * The definition of what a list adding method is has to stay in sync with
336 * [isAddedToContainer]. 333 * [isAddedToContainer].
337 */ 334 */
338 bool isParameterOfListAddingMethod(Element element) { 335 bool isParameterOfListAddingMethod(Element element) {
339 if (!element.isParameter) return false; 336 if (!element.isParameter) return false;
340 if (element.enclosingClass != compiler.backend.listImplementation) { 337 if (element.enclosingClass != compiler.backend.listImplementation) {
341 return false; 338 return false;
342 } 339 }
343 Element method = element.enclosingElement; 340 Element method = element.enclosingElement;
344 return (method.name == '[]=') 341 return (method.name == '[]=') ||
345 || (method.name == 'add') 342 (method.name == 'add') ||
346 || (method.name == 'insert'); 343 (method.name == 'insert');
347 } 344 }
348 345
349 /** 346 /**
350 * Check whether element is the parameter of a list adding method. 347 * Check whether element is the parameter of a list adding method.
351 * The definition of what a list adding method is has to stay in sync with 348 * The definition of what a list adding method is has to stay in sync with
352 * [isValueAddedToMap] and [isKeyAddedToMap]. 349 * [isValueAddedToMap] and [isKeyAddedToMap].
353 */ 350 */
354 bool isParameterOfMapAddingMethod(Element element) { 351 bool isParameterOfMapAddingMethod(Element element) {
355 if (!element.isParameter) return false; 352 if (!element.isParameter) return false;
356 if (element.enclosingClass != compiler.backend.mapImplementation) { 353 if (element.enclosingClass != compiler.backend.mapImplementation) {
357 return false; 354 return false;
358 } 355 }
359 Element method = element.enclosingElement; 356 Element method = element.enclosingElement;
360 return (method.name == '[]='); 357 return (method.name == '[]=');
361 } 358 }
362 359
363 bool isClosure(Element element) { 360 bool isClosure(Element element) {
364 if (!element.isFunction) return false; 361 if (!element.isFunction) return false;
362
365 /// Creating an instance of a class that implements [Function] also 363 /// Creating an instance of a class that implements [Function] also
366 /// closurizes the corresponding [call] member. We do not currently 364 /// closurizes the corresponding [call] member. We do not currently
367 /// track these, thus the check for [isClosurized] on such a method will 365 /// track these, thus the check for [isClosurized] on such a method will
368 /// return false. Instead we catch that case here for now. 366 /// return false. Instead we catch that case here for now.
369 // TODO(herhut): Handle creation of closures from instances of Function. 367 // TODO(herhut): Handle creation of closures from instances of Function.
370 if (element.isInstanceMember && 368 if (element.isInstanceMember && element.name == Identifiers.call) {
371 element.name == Identifiers.call) {
372 return true; 369 return true;
373 } 370 }
374 Element outermost = element.outermostEnclosingMemberOrTopLevel; 371 Element outermost = element.outermostEnclosingMemberOrTopLevel;
375 return outermost.declaration != element.declaration; 372 return outermost.declaration != element.declaration;
376 } 373 }
377 374
378 void visitMemberTypeInformation(MemberTypeInformation info) { 375 void visitMemberTypeInformation(MemberTypeInformation info) {
379 if (info.isClosurized) { 376 if (info.isClosurized) {
380 bailout('Returned from a closurized method'); 377 bailout('Returned from a closurized method');
381 } 378 }
(...skipping 18 matching lines...) Expand all
400 } 397 }
401 if (isParameterOfListAddingMethod(info.element) || 398 if (isParameterOfListAddingMethod(info.element) ||
402 isParameterOfMapAddingMethod(info.element)) { 399 isParameterOfMapAddingMethod(info.element)) {
403 // These elements are being handled in 400 // These elements are being handled in
404 // [visitDynamicCallSiteTypeInformation]. 401 // [visitDynamicCallSiteTypeInformation].
405 return; 402 return;
406 } 403 }
407 addNewEscapeInformation(info); 404 addNewEscapeInformation(info);
408 } 405 }
409 } 406 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/inferrer/map_tracer.dart ('k') | pkg/compiler/lib/src/inferrer/simple_types_inferrer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698