OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 dart2js.world; | 5 library dart2js.world; |
6 | 6 |
7 import 'closure.dart' show ClosureClassElement, SynthesizedCallMethodElementX; | 7 import 'closure.dart' show ClosureClassElement; |
8 import 'common.dart'; | 8 import 'common.dart'; |
9 import 'constants/constant_system.dart'; | 9 import 'constants/constant_system.dart'; |
10 import 'common_elements.dart' show CommonElements, ElementEnvironment; | 10 import 'common_elements.dart' show CommonElements, ElementEnvironment; |
11 import 'elements/entities.dart'; | 11 import 'elements/entities.dart'; |
12 import 'elements/elements.dart' | 12 import 'elements/elements.dart' |
13 show | 13 show |
14 ClassElement, | 14 ClassElement, |
15 Element, | 15 Element, |
16 MemberElement, | 16 MemberElement, |
17 MethodElement, | |
17 MixinApplicationElement, | 18 MixinApplicationElement, |
18 TypedefElement; | 19 TypedefElement; |
19 import 'elements/resolution_types.dart'; | 20 import 'elements/resolution_types.dart'; |
20 import 'elements/types.dart'; | 21 import 'elements/types.dart'; |
21 import 'js_backend/backend_usage.dart' show BackendUsage; | 22 import 'js_backend/backend_usage.dart' show BackendUsage; |
22 import 'js_backend/interceptor_data.dart' show InterceptorData; | 23 import 'js_backend/interceptor_data.dart' show InterceptorData; |
23 import 'js_backend/native_data.dart' show NativeData; | 24 import 'js_backend/native_data.dart' show NativeData; |
24 import 'ordered_typeset.dart'; | 25 import 'ordered_typeset.dart'; |
25 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask; | 26 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask; |
26 import 'universe/class_set.dart'; | 27 import 'universe/class_set.dart'; |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
304 /// Returns the single [MemberEntity] that matches a call to [selector] on a | 305 /// Returns the single [MemberEntity] that matches a call to [selector] on a |
305 /// receiver of type [mask]. If multiple targets exist, `null` is returned. | 306 /// receiver of type [mask]. If multiple targets exist, `null` is returned. |
306 MemberEntity locateSingleElement(Selector selector, TypeMask mask); | 307 MemberEntity locateSingleElement(Selector selector, TypeMask mask); |
307 | 308 |
308 /// Returns the single field that matches a call to [selector] on a | 309 /// Returns the single field that matches a call to [selector] on a |
309 /// receiver of type [mask]. If multiple targets exist or the single target | 310 /// receiver of type [mask]. If multiple targets exist or the single target |
310 /// is not a field, `null` is returned. | 311 /// is not a field, `null` is returned. |
311 FieldEntity locateSingleField(Selector selector, TypeMask mask); | 312 FieldEntity locateSingleField(Selector selector, TypeMask mask); |
312 | 313 |
313 /// Returns the side effects of executing [element]. | 314 /// Returns the side effects of executing [element]. |
314 SideEffects getSideEffectsOfElement(Entity element); | 315 SideEffects getSideEffectsOfElement(FunctionEntity element); |
315 | 316 |
316 /// Returns the side effects of calling [selector] on a receiver of type | 317 /// Returns the side effects of calling [selector] on a receiver of type |
317 /// [mask]. | 318 /// [mask]. |
318 SideEffects getSideEffectsOfSelector(Selector selector, TypeMask mask); | 319 SideEffects getSideEffectsOfSelector(Selector selector, TypeMask mask); |
319 | 320 |
320 /// Returns `true` if [element] is guaranteed not to throw an exception. | 321 /// Returns `true` if [element] is guaranteed not to throw an exception. |
321 bool getCannotThrow(Entity element); | 322 bool getCannotThrow(FunctionEntity element); |
322 | 323 |
323 /// Returns `true` if [element] is called in a loop. | 324 /// Returns `true` if [element] is called in a loop. |
324 // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'? | 325 // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'? |
325 bool isCalledInLoop(Entity element); | 326 // TODO(johnniwinther): Change [MemberEntity] to [FunctionEntity]. |
327 bool isCalledInLoop(MemberEntity element); | |
326 | 328 |
327 /// Returns `true` if [element] might be passed to `Function.apply`. | 329 /// Returns `true` if [element] might be passed to `Function.apply`. |
328 // TODO(johnniwinther): Is this 'passed invocation target` or | 330 // TODO(johnniwinther): Is this 'passed invocation target` or |
329 // `passed as argument`? | 331 // `passed as argument`? |
330 bool getMightBePassedToApply(Entity element); | 332 bool getMightBePassedToApply(FunctionEntity element); |
331 | 333 |
332 /// Returns a string representation of the closed world. | 334 /// Returns a string representation of the closed world. |
333 /// | 335 /// |
334 /// If [cls] is provided, the dump will contain only classes related to [cls]. | 336 /// If [cls] is provided, the dump will contain only classes related to [cls]. |
335 String dump([ClassEntity cls]); | 337 String dump([ClassEntity cls]); |
336 } | 338 } |
337 | 339 |
338 /// Interface for computing side effects and uses of elements. This is used | 340 /// Interface for computing side effects and uses of elements. This is used |
339 /// during type inference to compute the [ClosedWorld] for code generation. | 341 /// during type inference to compute the [ClosedWorld] for code generation. |
340 abstract class ClosedWorldRefiner { | 342 abstract class ClosedWorldRefiner { |
341 /// The closed world being refined. | 343 /// The closed world being refined. |
342 ClosedWorld get closedWorld; | 344 ClosedWorld get closedWorld; |
343 | 345 |
344 /// Registers the side [effects] of executing [element]. | 346 /// Registers the side [effects] of executing [element]. |
345 void registerSideEffects(Entity element, SideEffects effects); | 347 void registerSideEffects(FunctionEntity element, SideEffects effects); |
346 | 348 |
347 /// Registers the executing of [element] as without side effects. | 349 /// Registers the executing of [element] as without side effects. |
348 void registerSideEffectsFree(Entity element); | 350 void registerSideEffectsFree(FunctionEntity element); |
349 | 351 |
350 /// Returns the currently known side effects of executing [element]. | 352 /// Returns the currently known side effects of executing [element]. |
351 SideEffects getCurrentlyKnownSideEffects(Entity element); | 353 SideEffects getCurrentlyKnownSideEffects(FunctionEntity element); |
352 | 354 |
353 /// Registers that [element] might be passed to `Function.apply`. | 355 /// Registers that [element] might be passed to `Function.apply`. |
354 // TODO(johnniwinther): Is this 'passed invocation target` or | 356 // TODO(johnniwinther): Is this 'passed invocation target` or |
355 // `passed as argument`? | 357 // `passed as argument`? |
356 void registerMightBePassedToApply(Entity element); | 358 void registerMightBePassedToApply(FunctionEntity element); |
357 | 359 |
358 /// Returns `true` if [element] might be passed to `Function.apply` given the | 360 /// Returns `true` if [element] might be passed to `Function.apply` given the |
359 /// currently inferred information. | 361 /// currently inferred information. |
360 bool getCurrentlyKnownMightBePassedToApply(Entity element); | 362 bool getCurrentlyKnownMightBePassedToApply(FunctionEntity element); |
361 | 363 |
362 /// Registers that [element] is called in a loop. | 364 /// Registers that [element] is called in a loop. |
363 // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'? | 365 // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'? |
364 void addFunctionCalledInLoop(Entity element); | 366 void addFunctionCalledInLoop(MemberEntity element); |
365 | 367 |
366 /// Registers that [element] is guaranteed not to throw an exception. | 368 /// Registers that [element] is guaranteed not to throw an exception. |
367 void registerCannotThrow(Entity element); | 369 void registerCannotThrow(FunctionEntity element); |
368 | 370 |
369 /// Adds the closure class [cls] to the inference world. The class is | 371 /// Adds the closure class [cls] to the inference world. The class is |
370 /// considered directly instantiated. | 372 /// considered directly instantiated. |
371 void registerClosureClass(covariant ClassElement cls); | 373 void registerClosureClass(covariant ClassElement cls); |
372 } | 374 } |
373 | 375 |
374 abstract class OpenWorld implements World { | 376 abstract class OpenWorld implements World { |
375 /// Called to add [cls] to the set of known classes. | 377 /// Called to add [cls] to the set of known classes. |
376 /// | 378 /// |
377 /// This ensures that class hierarchy queries can be performed on [cls] and | 379 /// This ensures that class hierarchy queries can be performed on [cls] and |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
416 final Map<ClassEntity, Set<ClassEntity>> _typesImplementedBySubclasses; | 418 final Map<ClassEntity, Set<ClassEntity>> _typesImplementedBySubclasses; |
417 | 419 |
418 // We keep track of subtype and subclass relationships in four | 420 // We keep track of subtype and subclass relationships in four |
419 // distinct sets to make class hierarchy analysis faster. | 421 // distinct sets to make class hierarchy analysis faster. |
420 final Map<ClassEntity, ClassHierarchyNode> _classHierarchyNodes; | 422 final Map<ClassEntity, ClassHierarchyNode> _classHierarchyNodes; |
421 final Map<ClassEntity, ClassSet> _classSets; | 423 final Map<ClassEntity, ClassSet> _classSets; |
422 | 424 |
423 final Map<ClassEntity, Map<ClassEntity, bool>> _subtypeCoveredByCache = | 425 final Map<ClassEntity, Map<ClassEntity, bool>> _subtypeCoveredByCache = |
424 <ClassEntity, Map<ClassEntity, bool>>{}; | 426 <ClassEntity, Map<ClassEntity, bool>>{}; |
425 | 427 |
426 final Set<Entity> _functionsCalledInLoop = new Set<Entity>(); | 428 final Set<MemberEntity> _functionsCalledInLoop = new Set<MemberEntity>(); |
427 final Map<Entity, SideEffects> _sideEffects = new Map<Entity, SideEffects>(); | 429 final Map<FunctionEntity, SideEffects> _sideEffects = |
430 new Map<FunctionEntity, SideEffects>(); | |
428 | 431 |
429 final Set<Entity> _sideEffectsFreeElements = new Set<Entity>(); | 432 final Set<FunctionEntity> _sideEffectsFreeElements = |
433 new Set<FunctionEntity>(); | |
430 | 434 |
431 final Set<Entity> _elementsThatCannotThrow = new Set<Entity>(); | 435 final Set<FunctionEntity> _elementsThatCannotThrow = |
436 new Set<FunctionEntity>(); | |
432 | 437 |
433 final Set<Entity> _functionsThatMightBePassedToApply = new Set<Entity>(); | 438 final Set<FunctionEntity> _functionsThatMightBePassedToApply = |
439 new Set<FunctionEntity>(); | |
434 | 440 |
435 CommonMasks _commonMasks; | 441 CommonMasks _commonMasks; |
436 | 442 |
437 final ElementEnvironment elementEnvironment; | 443 final ElementEnvironment elementEnvironment; |
438 final DartTypes dartTypes; | 444 final DartTypes dartTypes; |
439 final CommonElements commonElements; | 445 final CommonElements commonElements; |
440 | 446 |
441 // TODO(johnniwinther): Avoid this. | 447 // TODO(johnniwinther): Avoid this. |
442 final ResolutionWorldBuilder _resolverWorld; | 448 final ResolutionWorldBuilder _resolverWorld; |
443 | 449 |
(...skipping 630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1074 sideEffects.setAllSideEffects(); | 1080 sideEffects.setAllSideEffects(); |
1075 sideEffects.setDependsOnSomething(); | 1081 sideEffects.setDependsOnSomething(); |
1076 } | 1082 } |
1077 } else { | 1083 } else { |
1078 sideEffects.add(getSideEffectsOfElement(e)); | 1084 sideEffects.add(getSideEffectsOfElement(e)); |
1079 } | 1085 } |
1080 } | 1086 } |
1081 return sideEffects; | 1087 return sideEffects; |
1082 } | 1088 } |
1083 | 1089 |
1084 SideEffects getSideEffectsOfElement(covariant Entity element) { | 1090 SideEffects getSideEffectsOfElement(FunctionEntity element) { |
1085 assert(checkEntity(element)); | 1091 assert(checkEntity(element)); |
1086 return _sideEffects.putIfAbsent(element, _makeSideEffects); | 1092 return _sideEffects.putIfAbsent(element, _makeSideEffects); |
1087 } | 1093 } |
1088 | 1094 |
1089 static SideEffects _makeSideEffects() => new SideEffects(); | 1095 static SideEffects _makeSideEffects() => new SideEffects(); |
1090 | 1096 |
1091 @override | 1097 @override |
1092 SideEffects getCurrentlyKnownSideEffects(Entity element) { | 1098 SideEffects getCurrentlyKnownSideEffects(FunctionEntity element) { |
1093 return getSideEffectsOfElement(element); | 1099 return getSideEffectsOfElement(element); |
1094 } | 1100 } |
1095 | 1101 |
1096 void registerSideEffects(Entity element, SideEffects effects) { | 1102 void registerSideEffects(FunctionEntity element, SideEffects effects) { |
1097 assert(checkEntity(element)); | 1103 assert(checkEntity(element)); |
1098 if (_sideEffectsFreeElements.contains(element)) return; | 1104 if (_sideEffectsFreeElements.contains(element)) return; |
1099 _sideEffects[element] = effects; | 1105 _sideEffects[element] = effects; |
1100 } | 1106 } |
1101 | 1107 |
1102 void registerSideEffectsFree(Entity element) { | 1108 void registerSideEffectsFree(FunctionEntity element) { |
1103 assert(checkEntity(element)); | 1109 assert(checkEntity(element)); |
1104 _sideEffects[element] = new SideEffects.empty(); | 1110 _sideEffects[element] = new SideEffects.empty(); |
1105 _sideEffectsFreeElements.add(element); | 1111 _sideEffectsFreeElements.add(element); |
1106 } | 1112 } |
1107 | 1113 |
1108 void addFunctionCalledInLoop(Entity element) { | 1114 void addFunctionCalledInLoop(MemberEntity element) { |
1109 assert(checkEntity(element)); | 1115 assert(checkEntity(element)); |
1110 _functionsCalledInLoop.add(element); | 1116 _functionsCalledInLoop.add(element); |
1111 } | 1117 } |
1112 | 1118 |
1113 bool isCalledInLoop(Entity element) { | 1119 bool isCalledInLoop(MemberEntity element) { |
1114 assert(checkEntity(element)); | 1120 assert(checkEntity(element)); |
1115 return _functionsCalledInLoop.contains(element); | 1121 return _functionsCalledInLoop.contains(element); |
1116 } | 1122 } |
1117 | 1123 |
1118 void registerCannotThrow(Entity element) { | 1124 void registerCannotThrow(FunctionEntity element) { |
1119 assert(checkEntity(element)); | 1125 assert(checkEntity(element)); |
1120 _elementsThatCannotThrow.add(element); | 1126 _elementsThatCannotThrow.add(element); |
1121 } | 1127 } |
1122 | 1128 |
1123 bool getCannotThrow(Entity element) { | 1129 bool getCannotThrow(FunctionEntity element) { |
1124 return _elementsThatCannotThrow.contains(element); | 1130 return _elementsThatCannotThrow.contains(element); |
1125 } | 1131 } |
1126 | 1132 |
1127 void registerMightBePassedToApply(Entity element) { | 1133 void registerMightBePassedToApply(FunctionEntity element) { |
1128 _functionsThatMightBePassedToApply.add(element); | 1134 _functionsThatMightBePassedToApply.add(element); |
1129 } | 1135 } |
1130 | 1136 |
1131 bool getMightBePassedToApply(Entity element) { | 1137 bool getMightBePassedToApply(FunctionEntity element) { |
1132 // We have to check whether the element we look at was created after | |
1133 // type inference ran. This is currently only the case for the call | |
1134 // method of function classes that were generated for function | |
1135 // expressions. In such a case, we have to look at the original | |
1136 // function expressions's element. | |
1137 // TODO(herhut): Generate classes for function expressions earlier. | |
1138 if (element is SynthesizedCallMethodElementX) { | |
1139 return getMightBePassedToApply(element.expression); | |
Siggi Cherem (dart-lang)
2017/06/30 18:13:54
neat to get rid of this, but this is unrelated to
Johnni Winther
2017/06/30 19:02:02
No, this was a fix for the same kind of discrepanc
Siggi Cherem (dart-lang)
2017/06/30 20:34:36
I see - the comment above was misleading, it gave
Johnni Winther
2017/07/03 07:26:07
When the comment was written they _were_ created a
| |
1140 } | |
1141 return _functionsThatMightBePassedToApply.contains(element); | 1138 return _functionsThatMightBePassedToApply.contains(element); |
1142 } | 1139 } |
1143 | 1140 |
1144 @override | 1141 @override |
1145 bool getCurrentlyKnownMightBePassedToApply(Entity element) { | 1142 bool getCurrentlyKnownMightBePassedToApply(FunctionEntity element) { |
1146 return getMightBePassedToApply(element); | 1143 return getMightBePassedToApply(element); |
1147 } | 1144 } |
1148 | 1145 |
1149 @override | 1146 @override |
1150 String dump([ClassEntity cls]) { | 1147 String dump([ClassEntity cls]) { |
1151 if (cls is! ClassElement) { | 1148 if (cls is! ClassElement) { |
1152 // TODO(johnniwinther): Support [cls] as a [ClassEntity]. | 1149 // TODO(johnniwinther): Support [cls] as a [ClassEntity]. |
1153 cls = null; | 1150 cls = null; |
1154 } | 1151 } |
1155 StringBuffer sb = new StringBuffer(); | 1152 StringBuffer sb = new StringBuffer(); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1293 if (cls != commonElements.functionClass && | 1290 if (cls != commonElements.functionClass && |
1294 cls.implementsFunction(commonElements)) { | 1291 cls.implementsFunction(commonElements)) { |
1295 ClassSet subtypeSet = getClassSet(commonElements.functionClass); | 1292 ClassSet subtypeSet = getClassSet(commonElements.functionClass); |
1296 subtypeSet.addSubtype(node); | 1293 subtypeSet.addSubtype(node); |
1297 } | 1294 } |
1298 if (!node.isInstantiated && node.parentNode != null) { | 1295 if (!node.isInstantiated && node.parentNode != null) { |
1299 _updateSuperClassHierarchyNodeForClass(node.parentNode); | 1296 _updateSuperClassHierarchyNodeForClass(node.parentNode); |
1300 } | 1297 } |
1301 } | 1298 } |
1302 | 1299 |
1303 SideEffects getSideEffectsOfElement(Element element) { | 1300 SideEffects getSideEffectsOfElement(covariant MethodElement element) { |
1304 // The type inferrer (where the side effects are being computed), | 1301 // The type inferrer (where the side effects are being computed), |
1305 // does not see generative constructor bodies because they are | 1302 // does not see generative constructor bodies because they are |
1306 // created by the backend. Also, it does not make any distinction | 1303 // created by the backend. Also, it does not make any distinction |
1307 // between a constructor and its body for side effects. This | 1304 // between a constructor and its body for side effects. This |
1308 // implies that currently, the side effects of a constructor body | 1305 // implies that currently, the side effects of a constructor body |
1309 // contain the side effects of the initializers. | 1306 // contain the side effects of the initializers. |
1310 assert(!element.isGenerativeConstructorBody); | 1307 assert(!element.isGenerativeConstructorBody); |
1311 assert(!element.isField); | 1308 assert(!element.isField); |
1312 return super.getSideEffectsOfElement(element); | 1309 return super.getSideEffectsOfElement(element); |
1313 } | 1310 } |
1314 } | 1311 } |
OLD | NEW |