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 SynthesizedCallMethodElementX; | 7 import 'closure.dart' show SynthesizedCallMethodElementX; |
8 import 'common/backend_api.dart' show Backend; | 8 import 'common/backend_api.dart' show Backend; |
9 import 'common.dart'; | 9 import 'common.dart'; |
10 import 'compiler.dart' show Compiler; | 10 import 'compiler.dart' show Compiler; |
11 import 'core_types.dart' show CoreClasses; | 11 import 'core_types.dart' show CoreClasses; |
12 import 'dart_types.dart'; | 12 import 'dart_types.dart'; |
13 import 'elements/elements.dart' | 13 import 'elements/elements.dart' |
14 show | 14 show |
15 ClassElement, | 15 ClassElement, |
16 Element, | 16 Element, |
17 FunctionElement, | 17 FunctionElement, |
18 MixinApplicationElement, | 18 MixinApplicationElement, |
19 TypedefElement, | 19 TypedefElement, |
20 VariableElement; | 20 VariableElement; |
21 import 'ordered_typeset.dart'; | 21 import 'ordered_typeset.dart'; |
22 import 'types/masks.dart' show TypeMask, FlatTypeMask; | 22 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask; |
23 import 'universe/class_set.dart'; | 23 import 'universe/class_set.dart'; |
24 import 'universe/function_set.dart' show FunctionSet; | 24 import 'universe/function_set.dart' show FunctionSet; |
25 import 'universe/selector.dart' show Selector; | 25 import 'universe/selector.dart' show Selector; |
26 import 'universe/side_effects.dart' show SideEffects; | 26 import 'universe/side_effects.dart' show SideEffects; |
27 import 'util/util.dart' show Link; | 27 import 'util/util.dart' show Link; |
28 | 28 |
29 /// The [ClassWorld] represents the information known about a program when | 29 /// The [ClassWorld] represents the information known about a program when |
30 /// compiling with closed-world semantics. | 30 /// compiling with closed-world semantics. |
31 /// | 31 /// |
32 /// Given the entrypoint of an application, we can track what's reachable from | 32 /// Given the entrypoint of an application, we can track what's reachable from |
33 /// it, what functions are called, what classes are allocated, which native | 33 /// it, what functions are called, what classes are allocated, which native |
34 /// JavaScript types are touched, what language features are used, and so on. | 34 /// JavaScript types are touched, what language features are used, and so on. |
35 /// This precise knowledge about what's live in the program is later used in | 35 /// This precise knowledge about what's live in the program is later used in |
36 /// optimizations and other compiler decisions during code generation. | 36 /// optimizations and other compiler decisions during code generation. |
37 abstract class ClassWorld { | 37 abstract class ClassWorld { |
38 // TODO(johnniwinther): Refine this into a `BackendClasses` interface. | 38 // TODO(johnniwinther): Refine this into a `BackendClasses` interface. |
39 Backend get backend; | 39 Backend get backend; |
40 | 40 |
41 // TODO(johnniwinther): Remove the need for this getter. | 41 CommonMasks get commonMasks; |
Siggi Cherem (dart-lang)
2016/09/06 20:23:08
I really wonder whether we want to also expose the
Johnni Winther
2016/09/19 13:03:49
Removed. It was only need in an assertion where a
| |
42 @deprecated | |
43 Compiler get compiler; | |
44 | 42 |
45 /// The [ClassElement] for the [Object] class defined in 'dart:core'. | 43 CoreClasses get coreClasses; |
46 ClassElement get objectClass; | |
47 | |
48 /// The [ClassElement] for the [Function] class defined in 'dart:core'. | |
49 ClassElement get functionClass; | |
50 | |
51 /// The [ClassElement] for the [bool] class defined in 'dart:core'. | |
52 ClassElement get boolClass; | |
53 | |
54 /// The [ClassElement] for the [num] class defined in 'dart:core'. | |
55 ClassElement get numClass; | |
56 | |
57 /// The [ClassElement] for the [int] class defined in 'dart:core'. | |
58 ClassElement get intClass; | |
59 | |
60 /// The [ClassElement] for the [double] class defined in 'dart:core'. | |
61 ClassElement get doubleClass; | |
62 | |
63 /// The [ClassElement] for the [String] class defined in 'dart:core'. | |
64 ClassElement get stringClass; | |
65 | 44 |
66 /// Returns `true` if [cls] is either directly or indirectly instantiated. | 45 /// Returns `true` if [cls] is either directly or indirectly instantiated. |
67 bool isInstantiated(ClassElement cls); | 46 bool isInstantiated(ClassElement cls); |
68 | 47 |
69 /// Returns `true` if [cls] is directly instantiated. | 48 /// Returns `true` if [cls] is directly instantiated. |
70 bool isDirectlyInstantiated(ClassElement cls); | 49 bool isDirectlyInstantiated(ClassElement cls); |
71 | 50 |
72 /// Returns `true` if [cls] is indirectly instantiated, that is through a | 51 /// Returns `true` if [cls] is indirectly instantiated, that is through a |
73 /// subclass. | 52 /// subclass. |
74 bool isIndirectlyInstantiated(ClassElement cls); | 53 bool isIndirectlyInstantiated(ClassElement cls); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
178 bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); | 157 bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); |
179 | 158 |
180 /// Returns `true` if closed-world assumptions can be made, that is, | 159 /// Returns `true` if closed-world assumptions can be made, that is, |
181 /// incremental compilation isn't enabled. | 160 /// incremental compilation isn't enabled. |
182 bool get hasClosedWorldAssumption; | 161 bool get hasClosedWorldAssumption; |
183 | 162 |
184 /// Returns a string representation of the closed world. | 163 /// Returns a string representation of the closed world. |
185 /// | 164 /// |
186 /// If [cls] is provided, the dump will contain only classes related to [cls]. | 165 /// If [cls] is provided, the dump will contain only classes related to [cls]. |
187 String dump([ClassElement cls]); | 166 String dump([ClassElement cls]); |
167 | |
168 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies | |
169 /// of known classes. | |
170 /// | |
171 /// This method is only provided for testing. For queries on classes, use the | |
172 /// methods defined in [ClassWorld]. | |
173 ClassHierarchyNode getClassHierarchyNode(ClassElement cls); | |
188 } | 174 } |
189 | 175 |
190 class World implements ClassWorld { | 176 abstract class ClosedWorld extends ClassWorld { |
Siggi Cherem (dart-lang)
2016/09/06 20:23:09
+ dartdoc
Johnni Winther
2016/09/19 13:03:49
Done.
| |
191 ClassElement get objectClass => coreClasses.objectClass; | 177 /// Returns the [FunctionSet] containing all live functions in the closed |
192 ClassElement get functionClass => coreClasses.functionClass; | 178 /// world. |
193 ClassElement get boolClass => coreClasses.boolClass; | 179 FunctionSet get allFunctions; |
194 ClassElement get numClass => coreClasses.numClass; | |
195 ClassElement get intClass => coreClasses.intClass; | |
196 ClassElement get doubleClass => coreClasses.doubleClass; | |
197 ClassElement get stringClass => coreClasses.stringClass; | |
198 ClassElement get nullClass => coreClasses.nullClass; | |
199 | 180 |
181 /// Returns `true` if the field [element] is known to be effectively final. | |
182 bool fieldNeverChanges(Element element); | |
183 | |
184 /// Extends the receiver type [mask] for calling [selector] to take live | |
185 /// `noSuchMethod` handlers into account. | |
186 TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask); | |
187 | |
188 /// Returns all resolved typedefs. | |
189 Iterable<TypedefElement> get allTypedefs; | |
190 | |
191 /// Returns the single [Element] that matches a call to [selector] on a | |
192 /// receiver of type [mask]. If multiple targets exists, `null` is returned. | |
193 Element locateSingleElement(Selector selector, TypeMask mask); | |
194 | |
195 /// Returns the single field that matches a call to [selector] on a | |
196 /// receiver of type [mask]. If multiple targets exists or the single target | |
197 /// is not a field, `null` is returned. | |
198 VariableElement locateSingleField(Selector selector, TypeMask mask); | |
199 | |
200 /// Returns the side effects of executing [element]. | |
201 SideEffects getSideEffectsOfElement(Element element); | |
202 | |
203 /// Returns the side effects of calling [selector] on a receiver of type | |
204 /// [mask]. | |
205 SideEffects getSideEffectsOfSelector(Selector selector, TypeMask mask); | |
206 | |
207 /// Returns `true` if [element] is guaranteed not to throw an exception. | |
208 bool getCannotThrow(Element element); | |
209 | |
210 /// Returns `true` if [element] is called in a loop. | |
211 // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'? | |
212 bool isCalledInLoop(Element element); | |
213 | |
214 /// Returns `true` if [element] might be passed to `Function.apply`. | |
215 // TODO(johnniwinther): Is this 'passed invocation target` or | |
216 // `passed as argument`? | |
217 bool getMightBePassedToApply(Element element); | |
218 } | |
219 | |
220 abstract class InferenceWorld { | |
Siggi Cherem (dart-lang)
2016/09/06 20:23:08
Interesting... this is good to see, because it hig
Johnni Winther
2016/09/19 13:03:49
Renamed the class to [ClosedWorldRefiner] and add
| |
221 /// Registers the side [effects] of executing [element]. | |
222 void registerSideEffects(Element element, SideEffects effects); | |
223 | |
224 /// Registers the executing of [element] as without side effects. | |
225 void registerSideEffectsFree(Element element); | |
226 | |
227 /// Returns the currently known side effects of executing [element]. | |
228 SideEffects getSideEffectsOfElement(Element element); | |
229 | |
230 /// Registers that [element] might be passed to `Function.apply`. | |
231 // TODO(johnniwinther): Is this 'passed invocation target` or | |
232 // `passed as argument`? | |
233 void registerMightBePassedToApply(Element element); | |
234 | |
235 /// Returns `true` if [element] might be passed to `Function.apply` given the | |
236 /// currently inferred information. | |
237 bool getMightBePassedToApply(Element element); | |
238 | |
239 /// Registers that [element] is called in a loop. | |
240 // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'? | |
241 void addFunctionCalledInLoop(Element element); | |
242 | |
243 /// Registers that [element] is guaranteed not to throw an exception. | |
244 void registerCannotThrow(Element element); | |
245 | |
246 /// Adds the closure class [cls] to the inference world. The class is | |
247 /// considered directly instantiated. | |
248 void registerClosureClass(ClassElement cls); | |
249 } | |
250 | |
251 class World implements ClosedWorld, InferenceWorld { | |
200 /// Cache of [FlatTypeMask]s grouped by the 8 possible values of the | 252 /// Cache of [FlatTypeMask]s grouped by the 8 possible values of the |
201 /// `FlatTypeMask.flags` property. | 253 /// `FlatTypeMask.flags` property. |
202 List<Map<ClassElement, TypeMask>> canonicalizedTypeMasks = | 254 List<Map<ClassElement, TypeMask>> canonicalizedTypeMasks = |
203 new List<Map<ClassElement, TypeMask>>.filled(8, null); | 255 new List<Map<ClassElement, TypeMask>>.filled(8, null); |
204 | 256 |
205 bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { | 257 bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { |
206 return invariant(cls, cls.isDeclaration, | 258 return invariant(cls, cls.isDeclaration, |
207 message: '$cls must be the declaration.') && | 259 message: '$cls must be the declaration.') && |
208 invariant(cls, cls.isResolved, | 260 invariant(cls, cls.isResolved, |
209 message: | 261 message: |
210 '$cls must be resolved.') /* && | 262 '$cls must be resolved.') /* && |
211 // TODO(johnniwinther): Reinsert this or similar invariant. | 263 // TODO(johnniwinther): Reinsert this or similar invariant. |
212 (!mustBeInstantiated || | 264 (!mustBeInstantiated || |
213 invariant(cls, isInstantiated(cls), | 265 invariant(cls, isInstantiated(cls), |
214 message: '$cls is not instantiated.'))*/ | 266 message: '$cls is not instantiated.'))*/ |
215 ; | 267 ; |
216 } | 268 } |
217 | 269 |
218 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an | 270 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an |
219 /// instance of [y]. | 271 /// instance of [y]. |
220 bool isSubtypeOf(ClassElement x, ClassElement y) { | 272 bool isSubtypeOf(ClassElement x, ClassElement y) { |
221 assert(checkInvariants(x)); | 273 assert(checkInvariants(x)); |
222 assert(checkInvariants(y, mustBeInstantiated: false)); | 274 assert(checkInvariants(y, mustBeInstantiated: false)); |
223 | 275 |
224 if (y == objectClass) return true; | 276 if (y == coreClasses.objectClass) return true; |
225 if (x == objectClass) return false; | 277 if (x == coreClasses.objectClass) return false; |
226 if (x.asInstanceOf(y) != null) return true; | 278 if (x.asInstanceOf(y) != null) return true; |
227 if (y != functionClass) return false; | 279 if (y != coreClasses.functionClass) return false; |
228 return x.callType != null; | 280 return x.callType != null; |
229 } | 281 } |
230 | 282 |
231 /// Return `true` if [x] is a (non-strict) subclass of [y]. | 283 /// Return `true` if [x] is a (non-strict) subclass of [y]. |
232 bool isSubclassOf(ClassElement x, ClassElement y) { | 284 bool isSubclassOf(ClassElement x, ClassElement y) { |
233 assert(checkInvariants(x)); | 285 assert(checkInvariants(x)); |
234 assert(checkInvariants(y)); | 286 assert(checkInvariants(y)); |
235 | 287 |
236 if (y == objectClass) return true; | 288 if (y == coreClasses.objectClass) return true; |
237 if (x == objectClass) return false; | 289 if (x == coreClasses.objectClass) return false; |
238 while (x != null && x.hierarchyDepth >= y.hierarchyDepth) { | 290 while (x != null && x.hierarchyDepth >= y.hierarchyDepth) { |
239 if (x == y) return true; | 291 if (x == y) return true; |
240 x = x.superclass; | 292 x = x.superclass; |
241 } | 293 } |
242 return false; | 294 return false; |
243 } | 295 } |
244 | 296 |
245 @override | 297 @override |
246 bool isInstantiated(ClassElement cls) { | 298 bool isInstantiated(ClassElement cls) { |
247 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; | 299 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; |
248 return node != null && node.isInstantiated; | 300 return node != null && node.isInstantiated; |
249 } | 301 } |
250 | 302 |
251 @override | 303 @override |
252 bool isDirectlyInstantiated(ClassElement cls) { | 304 bool isDirectlyInstantiated(ClassElement cls) { |
253 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; | 305 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; |
254 return node != null && node.isDirectlyInstantiated; | 306 return node != null && node.isDirectlyInstantiated; |
255 } | 307 } |
256 | 308 |
257 @override | 309 @override |
258 bool isIndirectlyInstantiated(ClassElement cls) { | 310 bool isIndirectlyInstantiated(ClassElement cls) { |
259 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; | 311 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; |
260 return node != null && node.isIndirectlyInstantiated; | 312 return node != null && node.isIndirectlyInstantiated; |
261 } | 313 } |
262 | 314 |
263 /// Returns `true` if [cls] is implemented by an instantiated class. | 315 /// Returns `true` if [cls] is implemented by an instantiated class. |
264 bool isImplemented(ClassElement cls) { | 316 bool isImplemented(ClassElement cls) { |
265 return compiler.resolverWorld.isImplemented(cls); | 317 return _compiler.resolverWorld.isImplemented(cls); |
266 } | 318 } |
267 | 319 |
268 /// Returns an iterable over the directly instantiated classes that extend | 320 /// Returns an iterable over the directly instantiated classes that extend |
269 /// [cls] possibly including [cls] itself, if it is live. | 321 /// [cls] possibly including [cls] itself, if it is live. |
270 Iterable<ClassElement> subclassesOf(ClassElement cls) { | 322 Iterable<ClassElement> subclassesOf(ClassElement cls) { |
271 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; | 323 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; |
272 if (hierarchy == null) return const <ClassElement>[]; | 324 if (hierarchy == null) return const <ClassElement>[]; |
273 return hierarchy.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); | 325 return hierarchy.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); |
274 } | 326 } |
275 | 327 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
387 /// Returns `true` if any directly instantiated class other than [cls] | 439 /// Returns `true` if any directly instantiated class other than [cls] |
388 /// implements [cls]. | 440 /// implements [cls]. |
389 bool hasAnyStrictSubtype(ClassElement cls) { | 441 bool hasAnyStrictSubtype(ClassElement cls) { |
390 return strictSubtypeCount(cls) > 0; | 442 return strictSubtypeCount(cls) > 0; |
391 } | 443 } |
392 | 444 |
393 /// Returns `true` if all directly instantiated classes that implement [cls] | 445 /// Returns `true` if all directly instantiated classes that implement [cls] |
394 /// extend it. | 446 /// extend it. |
395 bool hasOnlySubclasses(ClassElement cls) { | 447 bool hasOnlySubclasses(ClassElement cls) { |
396 // TODO(johnniwinther): move this to ClassSet? | 448 // TODO(johnniwinther): move this to ClassSet? |
397 if (cls == objectClass) return true; | 449 if (cls == coreClasses.objectClass) return true; |
398 ClassSet classSet = _classSets[cls.declaration]; | 450 ClassSet classSet = _classSets[cls.declaration]; |
399 if (classSet == null) { | 451 if (classSet == null) { |
400 // Vacuously true. | 452 // Vacuously true. |
401 return true; | 453 return true; |
402 } | 454 } |
403 return classSet.hasOnlyInstantiatedSubclasses; | 455 return classSet.hasOnlyInstantiatedSubclasses; |
404 } | 456 } |
405 | 457 |
406 @override | 458 @override |
407 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { | 459 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { |
(...skipping 27 matching lines...) Expand all Loading... | |
435 OrderedTypeSet otherTypeSet = otherClass.allSupertypesAndSelf; | 487 OrderedTypeSet otherTypeSet = otherClass.allSupertypesAndSelf; |
436 otherTypeSets = otherTypeSets.prepend(otherTypeSet); | 488 otherTypeSets = otherTypeSets.prepend(otherTypeSet); |
437 if (otherTypeSet.maxDepth < depth) { | 489 if (otherTypeSet.maxDepth < depth) { |
438 depth = otherTypeSet.maxDepth; | 490 depth = otherTypeSet.maxDepth; |
439 } | 491 } |
440 } while (iterator.moveNext()); | 492 } while (iterator.moveNext()); |
441 | 493 |
442 List<ClassElement> commonSupertypes = <ClassElement>[]; | 494 List<ClassElement> commonSupertypes = <ClassElement>[]; |
443 OUTER: | 495 OUTER: |
444 for (Link<DartType> link = typeSet[depth]; | 496 for (Link<DartType> link = typeSet[depth]; |
445 link.head.element != objectClass; | 497 link.head.element != coreClasses.objectClass; |
446 link = link.tail) { | 498 link = link.tail) { |
447 ClassElement cls = link.head.element; | 499 ClassElement cls = link.head.element; |
448 for (Link<OrderedTypeSet> link = otherTypeSets; | 500 for (Link<OrderedTypeSet> link = otherTypeSets; |
449 !link.isEmpty; | 501 !link.isEmpty; |
450 link = link.tail) { | 502 link = link.tail) { |
451 if (link.head.asInstanceOf(cls) == null) { | 503 if (link.head.asInstanceOf(cls) == null) { |
452 continue OUTER; | 504 continue OUTER; |
453 } | 505 } |
454 } | 506 } |
455 commonSupertypes.add(cls); | 507 commonSupertypes.add(cls); |
456 } | 508 } |
457 commonSupertypes.add(objectClass); | 509 commonSupertypes.add(coreClasses.objectClass); |
458 return commonSupertypes; | 510 return commonSupertypes; |
459 } | 511 } |
460 | 512 |
461 /// Returns an iterable over all mixin applications that mixin [cls]. | 513 /// Returns an iterable over all mixin applications that mixin [cls]. |
462 Iterable<MixinApplicationElement> allMixinUsesOf(ClassElement cls) { | 514 Iterable<MixinApplicationElement> allMixinUsesOf(ClassElement cls) { |
463 Iterable<MixinApplicationElement> uses = _mixinUses[cls]; | 515 Iterable<MixinApplicationElement> uses = _mixinUses[cls]; |
464 return uses != null ? uses : const <MixinApplicationElement>[]; | 516 return uses != null ? uses : const <MixinApplicationElement>[]; |
465 } | 517 } |
466 | 518 |
467 /// Returns an iterable over the live mixin applications that mixin [cls]. | 519 /// Returns an iterable over the live mixin applications that mixin [cls]. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
540 } | 592 } |
541 | 593 |
542 /// Returns `true` if any subclass of [superclass] implements [type]. | 594 /// Returns `true` if any subclass of [superclass] implements [type]. |
543 bool hasAnySubclassThatImplements( | 595 bool hasAnySubclassThatImplements( |
544 ClassElement superclass, ClassElement type) { | 596 ClassElement superclass, ClassElement type) { |
545 Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass); | 597 Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass); |
546 if (subclasses == null) return false; | 598 if (subclasses == null) return false; |
547 return subclasses.contains(type); | 599 return subclasses.contains(type); |
548 } | 600 } |
549 | 601 |
550 final Compiler compiler; | 602 final Compiler _compiler; |
551 Backend get backend => compiler.backend; | 603 Backend get backend => _compiler.backend; |
604 CommonMasks get commonMasks => _compiler.commonMasks; | |
552 final FunctionSet allFunctions; | 605 final FunctionSet allFunctions; |
553 final Set<Element> functionsCalledInLoop = new Set<Element>(); | 606 final Set<Element> functionsCalledInLoop = new Set<Element>(); |
554 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>(); | 607 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>(); |
555 | 608 |
556 final Set<TypedefElement> allTypedefs = new Set<TypedefElement>(); | 609 final Set<TypedefElement> allTypedefs = new Set<TypedefElement>(); |
557 | 610 |
558 final Map<ClassElement, Set<MixinApplicationElement>> _mixinUses = | 611 final Map<ClassElement, Set<MixinApplicationElement>> _mixinUses = |
559 new Map<ClassElement, Set<MixinApplicationElement>>(); | 612 new Map<ClassElement, Set<MixinApplicationElement>>(); |
560 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses; | 613 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses; |
561 | 614 |
(...skipping 11 matching lines...) Expand all Loading... | |
573 | 626 |
574 final Set<Element> sideEffectsFreeElements = new Set<Element>(); | 627 final Set<Element> sideEffectsFreeElements = new Set<Element>(); |
575 | 628 |
576 final Set<Element> elementsThatCannotThrow = new Set<Element>(); | 629 final Set<Element> elementsThatCannotThrow = new Set<Element>(); |
577 | 630 |
578 final Set<Element> functionsThatMightBePassedToApply = | 631 final Set<Element> functionsThatMightBePassedToApply = |
579 new Set<FunctionElement>(); | 632 new Set<FunctionElement>(); |
580 | 633 |
581 final Set<Element> alreadyPopulated; | 634 final Set<Element> alreadyPopulated; |
582 | 635 |
583 bool get isClosed => compiler.phase > Compiler.PHASE_RESOLVING; | 636 bool get isClosed => _compiler.phase > Compiler.PHASE_RESOLVING; |
584 | 637 |
585 // Used by selectors. | 638 // Used by selectors. |
586 bool isForeign(Element element) { | 639 bool isForeign(Element element) { |
587 return compiler.backend.isForeign(element); | 640 return backend.isForeign(element); |
588 } | 641 } |
589 | 642 |
590 Set<ClassElement> typesImplementedBySubclassesOf(ClassElement cls) { | 643 Set<ClassElement> typesImplementedBySubclassesOf(ClassElement cls) { |
591 return _typesImplementedBySubclasses[cls.declaration]; | 644 return _typesImplementedBySubclasses[cls.declaration]; |
592 } | 645 } |
593 | 646 |
594 World(Compiler compiler) | 647 World(Compiler compiler) |
595 : allFunctions = new FunctionSet(compiler), | 648 : allFunctions = new FunctionSet(compiler), |
596 this.compiler = compiler, | 649 this._compiler = compiler, |
597 alreadyPopulated = compiler.cacheStrategy.newSet(); | 650 alreadyPopulated = compiler.cacheStrategy.newSet(); |
598 | 651 |
599 CoreClasses get coreClasses => compiler.coreClasses; | 652 CoreClasses get coreClasses => _compiler.coreClasses; |
600 | 653 |
601 DiagnosticReporter get reporter => compiler.reporter; | 654 DiagnosticReporter get reporter => _compiler.reporter; |
602 | 655 |
603 /// Called to add [cls] to the set of known classes. | 656 /// Called to add [cls] to the set of known classes. |
604 /// | 657 /// |
605 /// This ensures that class hierarchy queries can be performed on [cls] and | 658 /// This ensures that class hierarchy queries can be performed on [cls] and |
606 /// classes that extend or implement it. | 659 /// classes that extend or implement it. |
607 void registerClass(ClassElement cls, {bool isDirectlyInstantiated: false}) { | 660 void registerClass(ClassElement cls) => _registerClass(cls); |
661 | |
662 void registerClosureClass(ClassElement cls) { | |
663 _registerClass(cls, isDirectlyInstantiated: true); | |
664 } | |
665 | |
666 void _registerClass(ClassElement cls, {bool isDirectlyInstantiated: false}) { | |
608 _ensureClassSet(cls); | 667 _ensureClassSet(cls); |
609 if (isDirectlyInstantiated) { | 668 if (isDirectlyInstantiated) { |
610 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); | 669 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); |
611 } | 670 } |
612 } | 671 } |
613 | 672 |
614 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies | 673 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies |
615 /// of known classes. | 674 /// of known classes. |
616 /// | 675 /// |
617 /// This method is only provided for testing. For queries on classes, use the | 676 /// This method is only provided for testing. For queries on classes, use the |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
686 if (directlyInstantiated) { | 745 if (directlyInstantiated) { |
687 node.isDirectlyInstantiated = true; | 746 node.isDirectlyInstantiated = true; |
688 } | 747 } |
689 } | 748 } |
690 | 749 |
691 void populate() { | 750 void populate() { |
692 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` | 751 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` |
693 /// properties of the [ClassHierarchyNode] for [cls]. | 752 /// properties of the [ClassHierarchyNode] for [cls]. |
694 | 753 |
695 void addSubtypes(ClassElement cls) { | 754 void addSubtypes(ClassElement cls) { |
696 if (compiler.options.hasIncrementalSupport && | 755 if (_compiler.options.hasIncrementalSupport && |
697 !alreadyPopulated.add(cls)) { | 756 !alreadyPopulated.add(cls)) { |
698 return; | 757 return; |
699 } | 758 } |
700 assert(cls.isDeclaration); | 759 assert(cls.isDeclaration); |
701 if (!cls.isResolved) { | 760 if (!cls.isResolved) { |
702 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); | 761 reporter.internalError(cls, 'Class "${cls.name}" is not resolved.'); |
703 } | 762 } |
704 | 763 |
705 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); | 764 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); |
706 | 765 |
707 // Walk through the superclasses, and record the types | 766 // Walk through the superclasses, and record the types |
708 // implemented by that type on the superclasses. | 767 // implemented by that type on the superclasses. |
709 ClassElement superclass = cls.superclass; | 768 ClassElement superclass = cls.superclass; |
710 while (superclass != null) { | 769 while (superclass != null) { |
711 Set<Element> typesImplementedBySubclassesOfCls = | 770 Set<Element> typesImplementedBySubclassesOfCls = |
712 _typesImplementedBySubclasses.putIfAbsent( | 771 _typesImplementedBySubclasses.putIfAbsent( |
713 superclass, () => new Set<ClassElement>()); | 772 superclass, () => new Set<ClassElement>()); |
714 for (DartType current in cls.allSupertypes) { | 773 for (DartType current in cls.allSupertypes) { |
715 typesImplementedBySubclassesOfCls.add(current.element); | 774 typesImplementedBySubclassesOfCls.add(current.element); |
716 } | 775 } |
717 superclass = superclass.superclass; | 776 superclass = superclass.superclass; |
718 } | 777 } |
719 } | 778 } |
720 | 779 |
721 // Use the [:seenClasses:] set to include non-instantiated | 780 // Use the [:seenClasses:] set to include non-instantiated |
722 // classes: if the superclass of these classes require RTI, then | 781 // classes: if the superclass of these classes require RTI, then |
723 // they also need RTI, so that a constructor passes the type | 782 // they also need RTI, so that a constructor passes the type |
724 // variables to the super constructor. | 783 // variables to the super constructor. |
725 compiler.resolverWorld.directlyInstantiatedClasses.forEach(addSubtypes); | 784 _compiler.resolverWorld.directlyInstantiatedClasses.forEach(addSubtypes); |
726 } | 785 } |
727 | 786 |
728 @override | 787 @override |
729 String dump([ClassElement cls]) { | 788 String dump([ClassElement cls]) { |
730 StringBuffer sb = new StringBuffer(); | 789 StringBuffer sb = new StringBuffer(); |
731 if (cls != null) { | 790 if (cls != null) { |
732 sb.write("Classes in the closed world related to $cls:\n"); | 791 sb.write("Classes in the closed world related to $cls:\n"); |
733 } else { | 792 } else { |
734 sb.write("Instantiated classes in the closed world:\n"); | 793 sb.write("Instantiated classes in the closed world:\n"); |
735 } | 794 } |
(...skipping 21 matching lines...) Expand all Loading... | |
757 allFunctions.add(element); | 816 allFunctions.add(element); |
758 } | 817 } |
759 } | 818 } |
760 | 819 |
761 VariableElement locateSingleField(Selector selector, TypeMask mask) { | 820 VariableElement locateSingleField(Selector selector, TypeMask mask) { |
762 Element result = locateSingleElement(selector, mask); | 821 Element result = locateSingleElement(selector, mask); |
763 return (result != null && result.isField) ? result : null; | 822 return (result != null && result.isField) ? result : null; |
764 } | 823 } |
765 | 824 |
766 Element locateSingleElement(Selector selector, TypeMask mask) { | 825 Element locateSingleElement(Selector selector, TypeMask mask) { |
767 mask ??= compiler.commonMasks.dynamicType; | 826 mask ??= commonMasks.dynamicType; |
768 return mask.locateSingleElement(selector, compiler); | 827 return mask.locateSingleElement(selector, _compiler); |
769 } | 828 } |
770 | 829 |
771 TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) { | 830 TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask) { |
772 bool canReachAll = true; | 831 bool canReachAll = true; |
773 if (mask != null) { | 832 if (mask != null) { |
774 canReachAll = compiler.enabledInvokeOn && | 833 canReachAll = _compiler.enabledInvokeOn && |
775 mask.needsNoSuchMethodHandling(selector, this); | 834 mask.needsNoSuchMethodHandling(selector, this); |
776 } | 835 } |
777 return canReachAll ? compiler.commonMasks.dynamicType : mask; | 836 return canReachAll ? commonMasks.dynamicType : mask; |
778 } | 837 } |
779 | 838 |
780 void addFunctionCalledInLoop(Element element) { | 839 void addFunctionCalledInLoop(Element element) { |
781 functionsCalledInLoop.add(element.declaration); | 840 functionsCalledInLoop.add(element.declaration); |
782 } | 841 } |
783 | 842 |
784 bool isCalledInLoop(Element element) { | 843 bool isCalledInLoop(Element element) { |
785 return functionsCalledInLoop.contains(element.declaration); | 844 return functionsCalledInLoop.contains(element.declaration); |
786 } | 845 } |
787 | 846 |
788 bool fieldNeverChanges(Element element) { | 847 bool fieldNeverChanges(Element element) { |
789 if (!element.isField) return false; | 848 if (!element.isField) return false; |
790 if (backend.isNative(element)) { | 849 if (backend.isNative(element)) { |
791 // Some native fields are views of data that may be changed by operations. | 850 // Some native fields are views of data that may be changed by operations. |
792 // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2). | 851 // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2). |
793 // TODO(sra): Refine the effect classification so that native effects are | 852 // TODO(sra): Refine the effect classification so that native effects are |
794 // distinct from ordinary Dart effects. | 853 // distinct from ordinary Dart effects. |
795 return false; | 854 return false; |
796 } | 855 } |
797 | 856 |
798 if (element.isFinal || element.isConst) { | 857 if (element.isFinal || element.isConst) { |
799 return true; | 858 return true; |
800 } | 859 } |
801 if (element.isInstanceMember) { | 860 if (element.isInstanceMember) { |
802 return !compiler.resolverWorld.hasInvokedSetter(element, this) && | 861 return !_compiler.resolverWorld.hasInvokedSetter(element, this) && |
803 !compiler.resolverWorld.fieldSetters.contains(element); | 862 !_compiler.resolverWorld.fieldSetters.contains(element); |
804 } | 863 } |
805 return false; | 864 return false; |
806 } | 865 } |
807 | 866 |
808 SideEffects getSideEffectsOfElement(Element element) { | 867 SideEffects getSideEffectsOfElement(Element element) { |
809 // The type inferrer (where the side effects are being computed), | 868 // The type inferrer (where the side effects are being computed), |
810 // does not see generative constructor bodies because they are | 869 // does not see generative constructor bodies because they are |
811 // created by the backend. Also, it does not make any distinction | 870 // created by the backend. Also, it does not make any distinction |
812 // between a constructor and its body for side effects. This | 871 // between a constructor and its body for side effects. This |
813 // implies that currently, the side effects of a constructor body | 872 // implies that currently, the side effects of a constructor body |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
871 // method of function classes that were generated for function | 930 // method of function classes that were generated for function |
872 // expressions. In such a case, we have to look at the original | 931 // expressions. In such a case, we have to look at the original |
873 // function expressions's element. | 932 // function expressions's element. |
874 // TODO(herhut): Generate classes for function expressions earlier. | 933 // TODO(herhut): Generate classes for function expressions earlier. |
875 if (element is SynthesizedCallMethodElementX) { | 934 if (element is SynthesizedCallMethodElementX) { |
876 return getMightBePassedToApply(element.expression); | 935 return getMightBePassedToApply(element.expression); |
877 } | 936 } |
878 return functionsThatMightBePassedToApply.contains(element); | 937 return functionsThatMightBePassedToApply.contains(element); |
879 } | 938 } |
880 | 939 |
881 bool get hasClosedWorldAssumption => !compiler.options.hasIncrementalSupport; | 940 bool get hasClosedWorldAssumption => !_compiler.options.hasIncrementalSupport; |
882 } | 941 } |
OLD | NEW |