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