Chromium Code Reviews| 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 |