| 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 | 7 import 'closure.dart' show SynthesizedCallMethodElementX; |
| 8 SynthesizedCallMethodElementX; | |
| 9 import 'common.dart'; | 8 import 'common.dart'; |
| 10 import 'common/backend_api.dart' show | 9 import 'common/backend_api.dart' show Backend; |
| 11 Backend; | 10 import 'compiler.dart' show Compiler; |
| 12 import 'compiler.dart' show | 11 import 'core_types.dart' show CoreClasses; |
| 13 Compiler; | |
| 14 import 'core_types.dart' show | |
| 15 CoreClasses; | |
| 16 import 'dart_types.dart'; | 12 import 'dart_types.dart'; |
| 17 import 'elements/elements.dart' show | 13 import 'elements/elements.dart' |
| 18 ClassElement, | 14 show |
| 19 Element, | 15 ClassElement, |
| 20 FunctionElement, | 16 Element, |
| 21 MixinApplicationElement, | 17 FunctionElement, |
| 22 TypedefElement, | 18 MixinApplicationElement, |
| 23 VariableElement; | 19 TypedefElement, |
| 20 VariableElement; |
| 24 import 'ordered_typeset.dart'; | 21 import 'ordered_typeset.dart'; |
| 25 import 'types/types.dart' as ti; | 22 import 'types/types.dart' as ti; |
| 26 import 'universe/class_set.dart'; | 23 import 'universe/class_set.dart'; |
| 27 import 'universe/function_set.dart' show | 24 import 'universe/function_set.dart' show FunctionSet; |
| 28 FunctionSet; | 25 import 'universe/selector.dart' show Selector; |
| 29 import 'universe/selector.dart' show | 26 import 'universe/side_effects.dart' show SideEffects; |
| 30 Selector; | 27 import 'util/util.dart' show Link; |
| 31 import 'universe/side_effects.dart' show | |
| 32 SideEffects; | |
| 33 import 'util/util.dart' show | |
| 34 Link; | |
| 35 | 28 |
| 36 abstract class ClassWorld { | 29 abstract class ClassWorld { |
| 37 // TODO(johnniwinther): Refine this into a `BackendClasses` interface. | 30 // TODO(johnniwinther): Refine this into a `BackendClasses` interface. |
| 38 Backend get backend; | 31 Backend get backend; |
| 39 | 32 |
| 40 // TODO(johnniwinther): Remove the need for this getter. | 33 // TODO(johnniwinther): Remove the need for this getter. |
| 41 @deprecated | 34 @deprecated |
| 42 Compiler get compiler; | 35 Compiler get compiler; |
| 43 | 36 |
| 44 /// The [ClassElement] for the [Object] class defined in 'dart:core'. | 37 /// The [ClassElement] for the [Object] class defined in 'dart:core'. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 /// Returns an iterable over the live classes that extend [cls] _not_ | 85 /// Returns an iterable over the live classes that extend [cls] _not_ |
| 93 /// including [cls] itself. | 86 /// including [cls] itself. |
| 94 Iterable<ClassElement> strictSubclassesOf(ClassElement cls); | 87 Iterable<ClassElement> strictSubclassesOf(ClassElement cls); |
| 95 | 88 |
| 96 /// Returns the number of live classes that extend [cls] _not_ | 89 /// Returns the number of live classes that extend [cls] _not_ |
| 97 /// including [cls] itself. | 90 /// including [cls] itself. |
| 98 int strictSubclassCount(ClassElement cls); | 91 int strictSubclassCount(ClassElement cls); |
| 99 | 92 |
| 100 /// Applies [f] to each live class that extend [cls] _not_ including [cls] | 93 /// Applies [f] to each live class that extend [cls] _not_ including [cls] |
| 101 /// itself. | 94 /// itself. |
| 102 void forEachStrictSubclassOf(ClassElement cls, | 95 void forEachStrictSubclassOf( |
| 103 IterationStep f(ClassElement cls)); | 96 ClassElement cls, IterationStep f(ClassElement cls)); |
| 104 | 97 |
| 105 /// Returns `true` if [predicate] applies to any live class that extend [cls] | 98 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
| 106 /// _not_ including [cls] itself. | 99 /// _not_ including [cls] itself. |
| 107 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)); | 100 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)); |
| 108 | 101 |
| 109 /// Returns an iterable over the directly instantiated that implement [cls] | 102 /// Returns an iterable over the directly instantiated that implement [cls] |
| 110 /// possibly including [cls] itself, if it is live. | 103 /// possibly including [cls] itself, if it is live. |
| 111 Iterable<ClassElement> subtypesOf(ClassElement cls); | 104 Iterable<ClassElement> subtypesOf(ClassElement cls); |
| 112 | 105 |
| 113 /// Returns an iterable over the live classes that implement [cls] _not_ | 106 /// Returns an iterable over the live classes that implement [cls] _not_ |
| 114 /// including [cls] if it is live. | 107 /// including [cls] if it is live. |
| 115 Iterable<ClassElement> strictSubtypesOf(ClassElement cls); | 108 Iterable<ClassElement> strictSubtypesOf(ClassElement cls); |
| 116 | 109 |
| 117 /// Returns the number of live classes that implement [cls] _not_ | 110 /// Returns the number of live classes that implement [cls] _not_ |
| 118 /// including [cls] itself. | 111 /// including [cls] itself. |
| 119 int strictSubtypeCount(ClassElement cls); | 112 int strictSubtypeCount(ClassElement cls); |
| 120 | 113 |
| 121 /// Applies [f] to each live class that implements [cls] _not_ including [cls] | 114 /// Applies [f] to each live class that implements [cls] _not_ including [cls] |
| 122 /// itself. | 115 /// itself. |
| 123 void forEachStrictSubtypeOf(ClassElement cls, | 116 void forEachStrictSubtypeOf( |
| 124 IterationStep f(ClassElement cls)); | 117 ClassElement cls, IterationStep f(ClassElement cls)); |
| 125 | 118 |
| 126 /// Returns `true` if [predicate] applies to any live class that implements | 119 /// Returns `true` if [predicate] applies to any live class that implements |
| 127 /// [cls] _not_ including [cls] itself. | 120 /// [cls] _not_ including [cls] itself. |
| 128 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)); | 121 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)); |
| 129 | 122 |
| 130 /// Returns `true` if [a] and [b] have any known common subtypes. | 123 /// Returns `true` if [a] and [b] have any known common subtypes. |
| 131 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b); | 124 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b); |
| 132 | 125 |
| 133 /// Returns `true` if any live class other than [cls] extends [cls]. | 126 /// Returns `true` if any live class other than [cls] extends [cls]. |
| 134 bool hasAnyStrictSubclass(ClassElement cls); | 127 bool hasAnyStrictSubclass(ClassElement cls); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 152 /// Returns an iterable over the common supertypes of the [classes]. | 145 /// Returns an iterable over the common supertypes of the [classes]. |
| 153 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes); | 146 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes); |
| 154 | 147 |
| 155 /// Returns an iterable over the live mixin applications that mixin [cls]. | 148 /// Returns an iterable over the live mixin applications that mixin [cls]. |
| 156 Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls); | 149 Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls); |
| 157 | 150 |
| 158 /// Returns `true` if [cls] is mixed into a live class. | 151 /// Returns `true` if [cls] is mixed into a live class. |
| 159 bool isUsedAsMixin(ClassElement cls); | 152 bool isUsedAsMixin(ClassElement cls); |
| 160 | 153 |
| 161 /// Returns `true` if any live class that mixes in [cls] implements [type]. | 154 /// Returns `true` if any live class that mixes in [cls] implements [type]. |
| 162 bool hasAnySubclassOfMixinUseThatImplements(ClassElement cls, | 155 bool hasAnySubclassOfMixinUseThatImplements( |
| 163 ClassElement type); | 156 ClassElement cls, ClassElement type); |
| 164 | 157 |
| 165 /// Returns `true` if any live class that mixes in [mixin] is also a subclass | 158 /// Returns `true` if any live class that mixes in [mixin] is also a subclass |
| 166 /// of [superclass]. | 159 /// of [superclass]. |
| 167 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin); | 160 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin); |
| 168 | 161 |
| 169 /// Returns `true` if any subclass of [superclass] implements [type]. | 162 /// Returns `true` if any subclass of [superclass] implements [type]. |
| 170 bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); | 163 bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); |
| 171 | 164 |
| 172 /// Returns `true` if closed-world assumptions can be made, that is, | 165 /// Returns `true` if closed-world assumptions can be made, that is, |
| 173 /// incremental compilation isn't enabled. | 166 /// incremental compilation isn't enabled. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 188 ClassElement get doubleClass => coreClasses.doubleClass; | 181 ClassElement get doubleClass => coreClasses.doubleClass; |
| 189 ClassElement get stringClass => coreClasses.stringClass; | 182 ClassElement get stringClass => coreClasses.stringClass; |
| 190 ClassElement get nullClass => coreClasses.nullClass; | 183 ClassElement get nullClass => coreClasses.nullClass; |
| 191 | 184 |
| 192 /// Cache of [ti.FlatTypeMask]s grouped by the 8 possible values of the | 185 /// Cache of [ti.FlatTypeMask]s grouped by the 8 possible values of the |
| 193 /// [ti.FlatTypeMask.flags] property. | 186 /// [ti.FlatTypeMask.flags] property. |
| 194 List<Map<ClassElement, ti.TypeMask>> canonicalizedTypeMasks = | 187 List<Map<ClassElement, ti.TypeMask>> canonicalizedTypeMasks = |
| 195 new List<Map<ClassElement, ti.TypeMask>>.filled(8, null); | 188 new List<Map<ClassElement, ti.TypeMask>>.filled(8, null); |
| 196 | 189 |
| 197 bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { | 190 bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { |
| 198 return | 191 return invariant(cls, cls.isDeclaration, |
| 199 invariant(cls, cls.isDeclaration, | |
| 200 message: '$cls must be the declaration.') && | 192 message: '$cls must be the declaration.') && |
| 201 invariant(cls, cls.isResolved, | 193 invariant(cls, cls.isResolved, |
| 202 message: '$cls must be resolved.')/* && | 194 message: |
| 195 '$cls must be resolved.') /* && |
| 203 // TODO(johnniwinther): Reinsert this or similar invariant. | 196 // TODO(johnniwinther): Reinsert this or similar invariant. |
| 204 (!mustBeInstantiated || | 197 (!mustBeInstantiated || |
| 205 invariant(cls, isInstantiated(cls), | 198 invariant(cls, isInstantiated(cls), |
| 206 message: '$cls is not instantiated.'))*/; | 199 message: '$cls is not instantiated.'))*/ |
| 207 } | 200 ; |
| 201 } |
| 208 | 202 |
| 209 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an | 203 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an |
| 210 /// instance of [y]. | 204 /// instance of [y]. |
| 211 bool isSubtypeOf(ClassElement x, ClassElement y) { | 205 bool isSubtypeOf(ClassElement x, ClassElement y) { |
| 212 assert(checkInvariants(x)); | 206 assert(checkInvariants(x)); |
| 213 assert(checkInvariants(y, mustBeInstantiated: false)); | 207 assert(checkInvariants(y, mustBeInstantiated: false)); |
| 214 | 208 |
| 215 if (y == objectClass) return true; | 209 if (y == objectClass) return true; |
| 216 if (x == objectClass) return false; | 210 if (x == objectClass) return false; |
| 217 if (x.asInstanceOf(y) != null) return true; | 211 if (x.asInstanceOf(y) != null) return true; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 /// Returns `true` if [cls] is implemented by an instantiated class. | 248 /// Returns `true` if [cls] is implemented by an instantiated class. |
| 255 bool isImplemented(ClassElement cls) { | 249 bool isImplemented(ClassElement cls) { |
| 256 return compiler.resolverWorld.isImplemented(cls); | 250 return compiler.resolverWorld.isImplemented(cls); |
| 257 } | 251 } |
| 258 | 252 |
| 259 /// Returns an iterable over the directly instantiated classes that extend | 253 /// Returns an iterable over the directly instantiated classes that extend |
| 260 /// [cls] possibly including [cls] itself, if it is live. | 254 /// [cls] possibly including [cls] itself, if it is live. |
| 261 Iterable<ClassElement> subclassesOf(ClassElement cls) { | 255 Iterable<ClassElement> subclassesOf(ClassElement cls) { |
| 262 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; | 256 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; |
| 263 if (hierarchy == null) return const <ClassElement>[]; | 257 if (hierarchy == null) return const <ClassElement>[]; |
| 264 return hierarchy.subclassesByMask( | 258 return hierarchy.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); |
| 265 ClassHierarchyNode.DIRECTLY_INSTANTIATED); | |
| 266 } | 259 } |
| 267 | 260 |
| 268 /// Returns an iterable over the directly instantiated classes that extend | 261 /// Returns an iterable over the directly instantiated classes that extend |
| 269 /// [cls] _not_ including [cls] itself. | 262 /// [cls] _not_ including [cls] itself. |
| 270 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { | 263 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { |
| 271 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 264 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 272 if (subclasses == null) return const <ClassElement>[]; | 265 if (subclasses == null) return const <ClassElement>[]; |
| 273 return subclasses.subclassesByMask( | 266 return subclasses.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
| 274 ClassHierarchyNode.DIRECTLY_INSTANTIATED, strict: true); | 267 strict: true); |
| 275 } | 268 } |
| 276 | 269 |
| 277 /// Returns the number of live classes that extend [cls] _not_ | 270 /// Returns the number of live classes that extend [cls] _not_ |
| 278 /// including [cls] itself. | 271 /// including [cls] itself. |
| 279 int strictSubclassCount(ClassElement cls) { | 272 int strictSubclassCount(ClassElement cls) { |
| 280 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 273 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 281 if (subclasses == null) return 0; | 274 if (subclasses == null) return 0; |
| 282 return subclasses.instantiatedSubclassCount; | 275 return subclasses.instantiatedSubclassCount; |
| 283 } | 276 } |
| 284 | 277 |
| 285 /// Applies [f] to each live class that extend [cls] _not_ including [cls] | 278 /// Applies [f] to each live class that extend [cls] _not_ including [cls] |
| 286 /// itself. | 279 /// itself. |
| 287 void forEachStrictSubclassOf(ClassElement cls, | 280 void forEachStrictSubclassOf( |
| 288 IterationStep f(ClassElement cls)) { | 281 ClassElement cls, IterationStep f(ClassElement cls)) { |
| 289 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 282 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 290 if (subclasses == null) return; | 283 if (subclasses == null) return; |
| 291 subclasses.forEachSubclass( | 284 subclasses.forEachSubclass(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
| 292 f, | |
| 293 ClassHierarchyNode.DIRECTLY_INSTANTIATED, | |
| 294 strict: true); | 285 strict: true); |
| 295 } | 286 } |
| 296 | 287 |
| 297 /// Returns `true` if [predicate] applies to any live class that extend [cls] | 288 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
| 298 /// _not_ including [cls] itself. | 289 /// _not_ including [cls] itself. |
| 299 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) { | 290 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) { |
| 300 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; | 291 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 301 if (subclasses == null) return false; | 292 if (subclasses == null) return false; |
| 302 return subclasses.anySubclass( | 293 return subclasses.anySubclass( |
| 303 predicate, | 294 predicate, ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
| 304 ClassHierarchyNode.DIRECTLY_INSTANTIATED, | |
| 305 strict: true); | 295 strict: true); |
| 306 } | 296 } |
| 307 | 297 |
| 308 /// Returns an iterable over the directly instantiated that implement [cls] | 298 /// Returns an iterable over the directly instantiated that implement [cls] |
| 309 /// possibly including [cls] itself, if it is live. | 299 /// possibly including [cls] itself, if it is live. |
| 310 Iterable<ClassElement> subtypesOf(ClassElement cls) { | 300 Iterable<ClassElement> subtypesOf(ClassElement cls) { |
| 311 ClassSet classSet = _classSets[cls.declaration]; | 301 ClassSet classSet = _classSets[cls.declaration]; |
| 312 if (classSet == null) { | 302 if (classSet == null) { |
| 313 return const <ClassElement>[]; | 303 return const <ClassElement>[]; |
| 314 } else { | 304 } else { |
| 315 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); | 305 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); |
| 316 } | 306 } |
| 317 } | 307 } |
| 318 | 308 |
| 319 /// Returns an iterable over the directly instantiated that implement [cls] | 309 /// Returns an iterable over the directly instantiated that implement [cls] |
| 320 /// _not_ including [cls]. | 310 /// _not_ including [cls]. |
| 321 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { | 311 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { |
| 322 ClassSet classSet = _classSets[cls.declaration]; | 312 ClassSet classSet = _classSets[cls.declaration]; |
| 323 if (classSet == null) { | 313 if (classSet == null) { |
| 324 return const <ClassElement>[]; | 314 return const <ClassElement>[]; |
| 325 } else { | 315 } else { |
| 326 return classSet.subtypesByMask( | 316 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
| 327 ClassHierarchyNode.DIRECTLY_INSTANTIATED, | |
| 328 strict: true); | 317 strict: true); |
| 329 } | 318 } |
| 330 } | 319 } |
| 331 | 320 |
| 332 /// Returns the number of live classes that implement [cls] _not_ | 321 /// Returns the number of live classes that implement [cls] _not_ |
| 333 /// including [cls] itself. | 322 /// including [cls] itself. |
| 334 int strictSubtypeCount(ClassElement cls) { | 323 int strictSubtypeCount(ClassElement cls) { |
| 335 ClassSet classSet = _classSets[cls.declaration]; | 324 ClassSet classSet = _classSets[cls.declaration]; |
| 336 if (classSet == null) return 0; | 325 if (classSet == null) return 0; |
| 337 return classSet.instantiatedSubtypeCount; | 326 return classSet.instantiatedSubtypeCount; |
| 338 } | 327 } |
| 339 | 328 |
| 340 /// Applies [f] to each live class that implements [cls] _not_ including [cls] | 329 /// Applies [f] to each live class that implements [cls] _not_ including [cls] |
| 341 /// itself. | 330 /// itself. |
| 342 void forEachStrictSubtypeOf(ClassElement cls, | 331 void forEachStrictSubtypeOf( |
| 343 IterationStep f(ClassElement cls)) { | 332 ClassElement cls, IterationStep f(ClassElement cls)) { |
| 344 ClassSet classSet = _classSets[cls.declaration]; | 333 ClassSet classSet = _classSets[cls.declaration]; |
| 345 if (classSet == null) return; | 334 if (classSet == null) return; |
| 346 classSet.forEachSubtype( | 335 classSet.forEachSubtype(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
| 347 f, | |
| 348 ClassHierarchyNode.DIRECTLY_INSTANTIATED, | |
| 349 strict: true); | 336 strict: true); |
| 350 } | 337 } |
| 351 | 338 |
| 352 /// Returns `true` if [predicate] applies to any live class that extend [cls] | 339 /// Returns `true` if [predicate] applies to any live class that extend [cls] |
| 353 /// _not_ including [cls] itself. | 340 /// _not_ including [cls] itself. |
| 354 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) { | 341 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) { |
| 355 ClassSet classSet = _classSets[cls.declaration]; | 342 ClassSet classSet = _classSets[cls.declaration]; |
| 356 if (classSet == null) return false; | 343 if (classSet == null) return false; |
| 357 return classSet.anySubtype( | 344 return classSet.anySubtype( |
| 358 predicate, | 345 predicate, ClassHierarchyNode.DIRECTLY_INSTANTIATED, |
| 359 ClassHierarchyNode.DIRECTLY_INSTANTIATED, | |
| 360 strict: true); | 346 strict: true); |
| 361 } | 347 } |
| 362 | 348 |
| 363 /// Returns `true` if [a] and [b] have any known common subtypes. | 349 /// Returns `true` if [a] and [b] have any known common subtypes. |
| 364 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) { | 350 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) { |
| 365 ClassSet classSetA = _classSets[a.declaration]; | 351 ClassSet classSetA = _classSets[a.declaration]; |
| 366 ClassSet classSetB = _classSets[b.declaration]; | 352 ClassSet classSetB = _classSets[b.declaration]; |
| 367 if (classSetA == null || classSetB == null) return false; | 353 if (classSetA == null || classSetB == null) return false; |
| 368 // TODO(johnniwinther): Implement an optimized query on [ClassSet]. | 354 // TODO(johnniwinther): Implement an optimized query on [ClassSet]. |
| 369 Set<ClassElement> subtypesOfB = classSetB.subtypes().toSet(); | 355 Set<ClassElement> subtypesOfB = classSetB.subtypes().toSet(); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 399 // Vacuously true. | 385 // Vacuously true. |
| 400 return true; | 386 return true; |
| 401 } | 387 } |
| 402 return classSet.hasOnlyInstantiatedSubclasses; | 388 return classSet.hasOnlyInstantiatedSubclasses; |
| 403 } | 389 } |
| 404 | 390 |
| 405 @override | 391 @override |
| 406 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { | 392 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { |
| 407 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; | 393 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; |
| 408 return hierarchy != null | 394 return hierarchy != null |
| 409 ? hierarchy.getLubOfInstantiatedSubclasses() : null; | 395 ? hierarchy.getLubOfInstantiatedSubclasses() |
| 396 : null; |
| 410 } | 397 } |
| 411 | 398 |
| 412 @override | 399 @override |
| 413 ClassElement getLubOfInstantiatedSubtypes(ClassElement cls) { | 400 ClassElement getLubOfInstantiatedSubtypes(ClassElement cls) { |
| 414 ClassSet classSet = _classSets[cls.declaration]; | 401 ClassSet classSet = _classSets[cls.declaration]; |
| 415 return classSet != null | 402 return classSet != null ? classSet.getLubOfInstantiatedSubtypes() : null; |
| 416 ? classSet.getLubOfInstantiatedSubtypes() : null; | |
| 417 } | 403 } |
| 418 | 404 |
| 419 /// Returns an iterable over the common supertypes of the [classes]. | 405 /// Returns an iterable over the common supertypes of the [classes]. |
| 420 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { | 406 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { |
| 421 Iterator<ClassElement> iterator = classes.iterator; | 407 Iterator<ClassElement> iterator = classes.iterator; |
| 422 if (!iterator.moveNext()) return const <ClassElement>[]; | 408 if (!iterator.moveNext()) return const <ClassElement>[]; |
| 423 | 409 |
| 424 ClassElement cls = iterator.current; | 410 ClassElement cls = iterator.current; |
| 425 assert(checkInvariants(cls)); | 411 assert(checkInvariants(cls)); |
| 426 OrderedTypeSet typeSet = cls.allSupertypesAndSelf; | 412 OrderedTypeSet typeSet = cls.allSupertypesAndSelf; |
| 427 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element); | 413 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element); |
| 428 | 414 |
| 429 int depth = typeSet.maxDepth; | 415 int depth = typeSet.maxDepth; |
| 430 Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>(); | 416 Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>(); |
| 431 do { | 417 do { |
| 432 ClassElement otherClass = iterator.current; | 418 ClassElement otherClass = iterator.current; |
| 433 assert(checkInvariants(otherClass)); | 419 assert(checkInvariants(otherClass)); |
| 434 OrderedTypeSet otherTypeSet = otherClass.allSupertypesAndSelf; | 420 OrderedTypeSet otherTypeSet = otherClass.allSupertypesAndSelf; |
| 435 otherTypeSets = otherTypeSets.prepend(otherTypeSet); | 421 otherTypeSets = otherTypeSets.prepend(otherTypeSet); |
| 436 if (otherTypeSet.maxDepth < depth) { | 422 if (otherTypeSet.maxDepth < depth) { |
| 437 depth = otherTypeSet.maxDepth; | 423 depth = otherTypeSet.maxDepth; |
| 438 } | 424 } |
| 439 } while (iterator.moveNext()); | 425 } while (iterator.moveNext()); |
| 440 | 426 |
| 441 List<ClassElement> commonSupertypes = <ClassElement>[]; | 427 List<ClassElement> commonSupertypes = <ClassElement>[]; |
| 442 OUTER: for (Link<DartType> link = typeSet[depth]; | 428 OUTER: for (Link<DartType> link = typeSet[depth]; |
| 443 link.head.element != objectClass; | 429 link.head.element != objectClass; |
| 444 link = link.tail) { | 430 link = link.tail) { |
| 445 ClassElement cls = link.head.element; | 431 ClassElement cls = link.head.element; |
| 446 for (Link<OrderedTypeSet> link = otherTypeSets; | 432 for (Link<OrderedTypeSet> link = otherTypeSets; |
| 447 !link.isEmpty; | 433 !link.isEmpty; |
| 448 link = link.tail) { | 434 link = link.tail) { |
| 449 if (link.head.asInstanceOf(cls) == null) { | 435 if (link.head.asInstanceOf(cls) == null) { |
| 450 continue OUTER; | 436 continue OUTER; |
| 451 } | 437 } |
| 452 } | 438 } |
| 453 commonSupertypes.add(cls); | 439 commonSupertypes.add(cls); |
| 454 } | 440 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 Iterable<MixinApplicationElement> uses = _liveMixinUses[cls]; | 476 Iterable<MixinApplicationElement> uses = _liveMixinUses[cls]; |
| 491 return uses != null ? uses : const <MixinApplicationElement>[]; | 477 return uses != null ? uses : const <MixinApplicationElement>[]; |
| 492 } | 478 } |
| 493 | 479 |
| 494 /// Returns `true` if [cls] is mixed into a live class. | 480 /// Returns `true` if [cls] is mixed into a live class. |
| 495 bool isUsedAsMixin(ClassElement cls) { | 481 bool isUsedAsMixin(ClassElement cls) { |
| 496 return !mixinUsesOf(cls).isEmpty; | 482 return !mixinUsesOf(cls).isEmpty; |
| 497 } | 483 } |
| 498 | 484 |
| 499 /// Returns `true` if any live class that mixes in [cls] implements [type]. | 485 /// Returns `true` if any live class that mixes in [cls] implements [type]. |
| 500 bool hasAnySubclassOfMixinUseThatImplements(ClassElement cls, | 486 bool hasAnySubclassOfMixinUseThatImplements( |
| 501 ClassElement type) { | 487 ClassElement cls, ClassElement type) { |
| 502 return mixinUsesOf(cls).any( | 488 return mixinUsesOf(cls) |
| 503 (use) => hasAnySubclassThatImplements(use, type)); | 489 .any((use) => hasAnySubclassThatImplements(use, type)); |
| 504 } | 490 } |
| 505 | 491 |
| 506 /// Returns `true` if any live class that mixes in [mixin] is also a subclass | 492 /// Returns `true` if any live class that mixes in [mixin] is also a subclass |
| 507 /// of [superclass]. | 493 /// of [superclass]. |
| 508 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin) { | 494 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin) { |
| 509 return mixinUsesOf(mixin).any((each) => each.isSubclassOf(superclass)); | 495 return mixinUsesOf(mixin).any((each) => each.isSubclassOf(superclass)); |
| 510 } | 496 } |
| 511 | 497 |
| 512 /// Returns `true` if any subclass of [superclass] implements [type]. | 498 /// Returns `true` if any subclass of [superclass] implements [type]. |
| 513 bool hasAnySubclassThatImplements(ClassElement superclass, | 499 bool hasAnySubclassThatImplements( |
| 514 ClassElement type) { | 500 ClassElement superclass, ClassElement type) { |
| 515 Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass); | 501 Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass); |
| 516 if (subclasses == null) return false; | 502 if (subclasses == null) return false; |
| 517 return subclasses.contains(type); | 503 return subclasses.contains(type); |
| 518 } | 504 } |
| 519 | 505 |
| 520 final Compiler compiler; | 506 final Compiler compiler; |
| 521 Backend get backend => compiler.backend; | 507 Backend get backend => compiler.backend; |
| 522 final FunctionSet allFunctions; | 508 final FunctionSet allFunctions; |
| 523 final Set<Element> functionsCalledInLoop = new Set<Element>(); | 509 final Set<Element> functionsCalledInLoop = new Set<Element>(); |
| 524 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>(); | 510 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>(); |
| 525 | 511 |
| 526 final Set<TypedefElement> allTypedefs = new Set<TypedefElement>(); | 512 final Set<TypedefElement> allTypedefs = new Set<TypedefElement>(); |
| 527 | 513 |
| 528 final Map<ClassElement, List<MixinApplicationElement>> _mixinUses = | 514 final Map<ClassElement, List<MixinApplicationElement>> _mixinUses = |
| 529 new Map<ClassElement, List<MixinApplicationElement>>(); | 515 new Map<ClassElement, List<MixinApplicationElement>>(); |
| 530 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses; | 516 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses; |
| 531 | 517 |
| 532 final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses = | 518 final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses = |
| 533 new Map<ClassElement, Set<ClassElement>>(); | 519 new Map<ClassElement, Set<ClassElement>>(); |
| 534 | 520 |
| 535 // We keep track of subtype and subclass relationships in four | 521 // We keep track of subtype and subclass relationships in four |
| 536 // distinct sets to make class hierarchy analysis faster. | 522 // distinct sets to make class hierarchy analysis faster. |
| 537 final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes = | 523 final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes = |
| 538 <ClassElement, ClassHierarchyNode>{}; | 524 <ClassElement, ClassHierarchyNode>{}; |
| 539 final Map<ClassElement, ClassSet> _classSets = | 525 final Map<ClassElement, ClassSet> _classSets = <ClassElement, ClassSet>{}; |
| 540 <ClassElement, ClassSet>{}; | |
| 541 | 526 |
| 542 final Set<Element> sideEffectsFreeElements = new Set<Element>(); | 527 final Set<Element> sideEffectsFreeElements = new Set<Element>(); |
| 543 | 528 |
| 544 final Set<Element> elementsThatCannotThrow = new Set<Element>(); | 529 final Set<Element> elementsThatCannotThrow = new Set<Element>(); |
| 545 | 530 |
| 546 final Set<Element> functionsThatMightBePassedToApply = | 531 final Set<Element> functionsThatMightBePassedToApply = |
| 547 new Set<FunctionElement>(); | 532 new Set<FunctionElement>(); |
| 548 | 533 |
| 549 final Set<Element> alreadyPopulated; | 534 final Set<Element> alreadyPopulated; |
| 550 | 535 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 if (cls != coreClasses.functionClass && | 616 if (cls != coreClasses.functionClass && |
| 632 cls.implementsFunction(coreClasses)) { | 617 cls.implementsFunction(coreClasses)) { |
| 633 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); | 618 ClassSet subtypeSet = _ensureClassSet(coreClasses.functionClass); |
| 634 subtypeSet.addSubtype(node); | 619 subtypeSet.addSubtype(node); |
| 635 } | 620 } |
| 636 if (!node.isInstantiated && node.parentNode != null) { | 621 if (!node.isInstantiated && node.parentNode != null) { |
| 637 _updateSuperClassHierarchyNodeForClass(node.parentNode); | 622 _updateSuperClassHierarchyNodeForClass(node.parentNode); |
| 638 } | 623 } |
| 639 } | 624 } |
| 640 | 625 |
| 641 void _updateClassHierarchyNodeForClass( | 626 void _updateClassHierarchyNodeForClass(ClassElement cls, |
| 642 ClassElement cls, | |
| 643 {bool directlyInstantiated: false}) { | 627 {bool directlyInstantiated: false}) { |
| 644 ClassHierarchyNode node = getClassHierarchyNode(cls); | 628 ClassHierarchyNode node = getClassHierarchyNode(cls); |
| 645 _updateSuperClassHierarchyNodeForClass(node); | 629 _updateSuperClassHierarchyNodeForClass(node); |
| 646 if (directlyInstantiated) { | 630 if (directlyInstantiated) { |
| 647 node.isDirectlyInstantiated = true; | 631 node.isDirectlyInstantiated = true; |
| 648 } | 632 } |
| 649 } | 633 } |
| 650 | 634 |
| 651 void populate() { | 635 void populate() { |
| 652 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` | 636 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 if (cls != null) { | 675 if (cls != null) { |
| 692 sb.write("Classes in the closed world related to $cls:\n"); | 676 sb.write("Classes in the closed world related to $cls:\n"); |
| 693 } else { | 677 } else { |
| 694 sb.write("Instantiated classes in the closed world:\n"); | 678 sb.write("Instantiated classes in the closed world:\n"); |
| 695 } | 679 } |
| 696 getClassHierarchyNode(coreClasses.objectClass) | 680 getClassHierarchyNode(coreClasses.objectClass) |
| 697 .printOn(sb, ' ', instantiatedOnly: cls == null, withRespectTo: cls); | 681 .printOn(sb, ' ', instantiatedOnly: cls == null, withRespectTo: cls); |
| 698 return sb.toString(); | 682 return sb.toString(); |
| 699 } | 683 } |
| 700 | 684 |
| 701 void registerMixinUse(MixinApplicationElement mixinApplication, | 685 void registerMixinUse( |
| 702 ClassElement mixin) { | 686 MixinApplicationElement mixinApplication, ClassElement mixin) { |
| 703 // TODO(johnniwinther): Add map restricted to live classes. | 687 // TODO(johnniwinther): Add map restricted to live classes. |
| 704 // We don't support patch classes as mixin. | 688 // We don't support patch classes as mixin. |
| 705 assert(mixin.isDeclaration); | 689 assert(mixin.isDeclaration); |
| 706 List<MixinApplicationElement> users = | 690 List<MixinApplicationElement> users = _mixinUses.putIfAbsent( |
| 707 _mixinUses.putIfAbsent(mixin, () => | 691 mixin, () => new List<MixinApplicationElement>()); |
| 708 new List<MixinApplicationElement>()); | |
| 709 users.add(mixinApplication); | 692 users.add(mixinApplication); |
| 710 } | 693 } |
| 711 | 694 |
| 712 bool hasAnyUserDefinedGetter(Selector selector, ti.TypeMask mask) { | 695 bool hasAnyUserDefinedGetter(Selector selector, ti.TypeMask mask) { |
| 713 return allFunctions.filter(selector, mask).any((each) => each.isGetter); | 696 return allFunctions.filter(selector, mask).any((each) => each.isGetter); |
| 714 } | 697 } |
| 715 | 698 |
| 716 void registerUsedElement(Element element) { | 699 void registerUsedElement(Element element) { |
| 717 if (element.isInstanceMember && !element.isAbstract) { | 700 if (element.isInstanceMember && !element.isAbstract) { |
| 718 allFunctions.add(element); | 701 allFunctions.add(element); |
| 719 } | 702 } |
| 720 } | 703 } |
| 721 | 704 |
| 722 VariableElement locateSingleField(Selector selector, ti.TypeMask mask) { | 705 VariableElement locateSingleField(Selector selector, ti.TypeMask mask) { |
| 723 Element result = locateSingleElement(selector, mask); | 706 Element result = locateSingleElement(selector, mask); |
| 724 return (result != null && result.isField) ? result : null; | 707 return (result != null && result.isField) ? result : null; |
| 725 } | 708 } |
| 726 | 709 |
| 727 Element locateSingleElement(Selector selector, ti.TypeMask mask) { | 710 Element locateSingleElement(Selector selector, ti.TypeMask mask) { |
| 728 mask = mask == null | 711 mask = mask == null ? compiler.typesTask.dynamicType : mask; |
| 729 ? compiler.typesTask.dynamicType | |
| 730 : mask; | |
| 731 return mask.locateSingleElement(selector, mask, compiler); | 712 return mask.locateSingleElement(selector, mask, compiler); |
| 732 } | 713 } |
| 733 | 714 |
| 734 ti.TypeMask extendMaskIfReachesAll(Selector selector, ti.TypeMask mask) { | 715 ti.TypeMask extendMaskIfReachesAll(Selector selector, ti.TypeMask mask) { |
| 735 bool canReachAll = true; | 716 bool canReachAll = true; |
| 736 if (mask != null) { | 717 if (mask != null) { |
| 737 canReachAll = | 718 canReachAll = compiler.enabledInvokeOn && |
| 738 compiler.enabledInvokeOn && | |
| 739 mask.needsNoSuchMethodHandling(selector, this); | 719 mask.needsNoSuchMethodHandling(selector, this); |
| 740 } | 720 } |
| 741 return canReachAll ? compiler.typesTask.dynamicType : mask; | 721 return canReachAll ? compiler.typesTask.dynamicType : mask; |
| 742 } | 722 } |
| 743 | 723 |
| 744 void addFunctionCalledInLoop(Element element) { | 724 void addFunctionCalledInLoop(Element element) { |
| 745 functionsCalledInLoop.add(element.declaration); | 725 functionsCalledInLoop.add(element.declaration); |
| 746 } | 726 } |
| 747 | 727 |
| 748 bool isCalledInLoop(Element element) { | 728 bool isCalledInLoop(Element element) { |
| 749 return functionsCalledInLoop.contains(element.declaration); | 729 return functionsCalledInLoop.contains(element.declaration); |
| 750 } | 730 } |
| 751 | 731 |
| 752 bool fieldNeverChanges(Element element) { | 732 bool fieldNeverChanges(Element element) { |
| 753 if (!element.isField) return false; | 733 if (!element.isField) return false; |
| 754 if (backend.isNative(element)) { | 734 if (backend.isNative(element)) { |
| 755 // Some native fields are views of data that may be changed by operations. | 735 // Some native fields are views of data that may be changed by operations. |
| 756 // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2). | 736 // E.g. node.firstChild depends on parentNode.removeBefore(n1, n2). |
| 757 // TODO(sra): Refine the effect classification so that native effects are | 737 // TODO(sra): Refine the effect classification so that native effects are |
| 758 // distinct from ordinary Dart effects. | 738 // distinct from ordinary Dart effects. |
| 759 return false; | 739 return false; |
| 760 } | 740 } |
| 761 | 741 |
| 762 if (element.isFinal || element.isConst) { | 742 if (element.isFinal || element.isConst) { |
| 763 return true; | 743 return true; |
| 764 } | 744 } |
| 765 if (element.isInstanceMember) { | 745 if (element.isInstanceMember) { |
| 766 return !compiler.resolverWorld.hasInvokedSetter(element, this) && | 746 return !compiler.resolverWorld.hasInvokedSetter(element, this) && |
| 767 !compiler.resolverWorld.fieldSetters.contains(element); | 747 !compiler.resolverWorld.fieldSetters.contains(element); |
| 768 } | 748 } |
| 769 return false; | 749 return false; |
| 770 } | 750 } |
| 771 | 751 |
| 772 SideEffects getSideEffectsOfElement(Element element) { | 752 SideEffects getSideEffectsOfElement(Element element) { |
| 773 // The type inferrer (where the side effects are being computed), | 753 // The type inferrer (where the side effects are being computed), |
| 774 // does not see generative constructor bodies because they are | 754 // does not see generative constructor bodies because they are |
| 775 // created by the backend. Also, it does not make any distinction | 755 // created by the backend. Also, it does not make any distinction |
| 776 // between a constructor and its body for side effects. This | 756 // between a constructor and its body for side effects. This |
| 777 // implies that currently, the side effects of a constructor body | 757 // implies that currently, the side effects of a constructor body |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 837 // function expressions's element. | 817 // function expressions's element. |
| 838 // TODO(herhut): Generate classes for function expressions earlier. | 818 // TODO(herhut): Generate classes for function expressions earlier. |
| 839 if (element is SynthesizedCallMethodElementX) { | 819 if (element is SynthesizedCallMethodElementX) { |
| 840 return getMightBePassedToApply(element.expression); | 820 return getMightBePassedToApply(element.expression); |
| 841 } | 821 } |
| 842 return functionsThatMightBePassedToApply.contains(element); | 822 return functionsThatMightBePassedToApply.contains(element); |
| 843 } | 823 } |
| 844 | 824 |
| 845 bool get hasClosedWorldAssumption => !compiler.options.hasIncrementalSupport; | 825 bool get hasClosedWorldAssumption => !compiler.options.hasIncrementalSupport; |
| 846 } | 826 } |
| OLD | NEW |