| 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 part of dart2js; | 5 part of dart2js; |
| 6 | 6 |
| 7 abstract class ClassWorld { | 7 abstract class ClassWorld { |
| 8 // TODO(johnniwinther): Refine this into a `BackendClasses` interface. | 8 // TODO(johnniwinther): Refine this into a `BackendClasses` interface. |
| 9 Backend get backend; | 9 Backend get backend; |
| 10 | 10 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 /// Returns `true` if the class world is closed. | 39 /// Returns `true` if the class world is closed. |
| 40 bool get isClosed; | 40 bool get isClosed; |
| 41 | 41 |
| 42 /// Return `true` if [x] is a subclass of [y]. | 42 /// Return `true` if [x] is a subclass of [y]. |
| 43 bool isSubclassOf(ClassElement x, ClassElement y); | 43 bool isSubclassOf(ClassElement x, ClassElement y); |
| 44 | 44 |
| 45 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an | 45 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an |
| 46 /// instance of [y]. | 46 /// instance of [y]. |
| 47 bool isSubtypeOf(ClassElement x, ClassElement y); | 47 bool isSubtypeOf(ClassElement x, ClassElement y); |
| 48 | 48 |
| 49 /// Returns an iterable over the live classes that extend [cls] including |
| 50 /// [cls] itself. |
| 51 Iterable<ClassElement> subclassesOf(ClassElement cls); |
| 52 |
| 49 /// Returns an iterable over the live classes that extend [cls] _not_ | 53 /// Returns an iterable over the live classes that extend [cls] _not_ |
| 50 /// including [cls] itself. | 54 /// including [cls] itself. |
| 51 Iterable<ClassElement> strictSubclassesOf(ClassElement cls); | 55 Iterable<ClassElement> strictSubclassesOf(ClassElement cls); |
| 52 | 56 |
| 53 /// Returns an iterable over the live classes that implement [cls] _not_ | 57 /// Returns an iterable over the live classes that implement [cls] _not_ |
| 54 /// including [cls] if it is live. | 58 /// including [cls] if it is live. |
| 55 Iterable<ClassElement> strictSubtypesOf(ClassElement cls); | 59 Iterable<ClassElement> strictSubtypesOf(ClassElement cls); |
| 56 | 60 |
| 57 /// Returns `true` if any live class other than [cls] extends [cls]. | 61 /// Returns `true` if any live class other than [cls] extends [cls]. |
| 58 bool hasAnyStrictSubclass(ClassElement cls); | 62 bool hasAnyStrictSubclass(ClassElement cls); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 x = x.superclass; | 142 x = x.superclass; |
| 139 } | 143 } |
| 140 return false; | 144 return false; |
| 141 } | 145 } |
| 142 | 146 |
| 143 /// Returns `true` if [cls] is instantiated. | 147 /// Returns `true` if [cls] is instantiated. |
| 144 bool isInstantiated(ClassElement cls) { | 148 bool isInstantiated(ClassElement cls) { |
| 145 return compiler.resolverWorld.isInstantiated(cls); | 149 return compiler.resolverWorld.isInstantiated(cls); |
| 146 } | 150 } |
| 147 | 151 |
| 148 /// Returns an iterable over the live classes that extend [cls] _not_ | 152 /// Returns an iterable over the directly instantiated classes that extend |
| 149 /// including [cls] itself. | 153 /// [cls] possibly including [cls] itself, if it is live. |
| 154 Iterable<ClassElement> subclassesOf(ClassElement cls) { |
| 155 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; |
| 156 if (hierarchy == null) return const <ClassElement>[]; |
| 157 assert(invariant(cls, isInstantiated(cls.declaration), |
| 158 message: 'Class $cls has not been instantiated.')); |
| 159 return hierarchy.subclasses(); |
| 160 } |
| 161 |
| 162 /// Returns an iterable over the directly instantiated classes that extend |
| 163 /// [cls] _not_ including [cls] itself. |
| 150 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { | 164 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { |
| 151 Set<ClassElement> subclasses = _subclasses[cls.declaration]; | 165 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 152 if (subclasses == null) return const <ClassElement>[]; | 166 if (subclasses == null) return const <ClassElement>[]; |
| 153 assert(invariant(cls, isInstantiated(cls.declaration), | 167 assert(invariant(cls, isInstantiated(cls.declaration), |
| 154 message: 'Class $cls has not been instantiated.')); | 168 message: 'Class $cls has not been instantiated.')); |
| 155 return subclasses; | 169 return subclasses.strictSubclasses(); |
| 156 } | 170 } |
| 157 | 171 |
| 158 /// Returns an iterable over the live classes that implement [cls] _not_ | 172 /// Returns an iterable over the directly instantiated that implement [cls] |
| 159 /// including [cls] if it is live. | 173 /// _not_ including [cls]. |
| 160 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { | 174 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { |
| 161 Set<ClassElement> subtypes = _subtypes[cls.declaration]; | 175 Set<ClassElement> subtypes = _subtypes[cls.declaration]; |
| 162 return subtypes != null ? subtypes : const <ClassElement>[]; | 176 return subtypes != null ? subtypes : const <ClassElement>[]; |
| 163 } | 177 } |
| 164 | 178 |
| 165 /// Returns `true` if any live class other than [cls] extends [cls]. | 179 /// Returns `true` if any directly instantiated class other than [cls] extends |
| 180 /// [cls]. |
| 166 bool hasAnyStrictSubclass(ClassElement cls) { | 181 bool hasAnyStrictSubclass(ClassElement cls) { |
| 167 return !strictSubclassesOf(cls).isEmpty; | 182 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; |
| 183 if (subclasses == null) return false; |
| 184 assert(invariant(cls, isInstantiated(cls.declaration), |
| 185 message: 'Class $cls has not been instantiated.')); |
| 186 return subclasses.isIndirectlyInstantiated; |
| 168 } | 187 } |
| 169 | 188 |
| 170 /// Returns `true` if any live class other than [cls] implements [cls]. | 189 /// Returns `true` if any directly instantiated class other than [cls] |
| 190 /// implements [cls]. |
| 171 bool hasAnyStrictSubtype(ClassElement cls) { | 191 bool hasAnyStrictSubtype(ClassElement cls) { |
| 172 return !strictSubtypesOf(cls).isEmpty; | 192 return !strictSubtypesOf(cls).isEmpty; |
| 173 } | 193 } |
| 174 | 194 |
| 175 /// Returns `true` if all live classes that implement [cls] extend it. | 195 /// Returns `true` if all directly instantiated classes that implement [cls] |
| 196 /// extend it. |
| 176 bool hasOnlySubclasses(ClassElement cls) { | 197 bool hasOnlySubclasses(ClassElement cls) { |
| 177 Iterable<ClassElement> subtypes = strictSubtypesOf(cls); | 198 Iterable<ClassElement> subtypes = strictSubtypesOf(cls); |
| 178 if (subtypes == null) return true; | 199 if (subtypes == null) return true; |
| 179 Iterable<ClassElement> subclasses = strictSubclassesOf(cls); | 200 Iterable<ClassElement> subclasses = strictSubclassesOf(cls); |
| 180 return subclasses != null && (subclasses.length == subtypes.length); | 201 return subclasses != null && (subclasses.length == subtypes.length); |
| 181 } | 202 } |
| 182 | 203 |
| 183 /// Returns an iterable over the common supertypes of the [classes]. | 204 /// Returns an iterable over the common supertypes of the [classes]. |
| 184 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { | 205 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { |
| 185 Iterator<ClassElement> iterator = classes.iterator; | 206 Iterator<ClassElement> iterator = classes.iterator; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 | 298 |
| 278 final Map<ClassElement, List<MixinApplicationElement>> _mixinUses = | 299 final Map<ClassElement, List<MixinApplicationElement>> _mixinUses = |
| 279 new Map<ClassElement, List<MixinApplicationElement>>(); | 300 new Map<ClassElement, List<MixinApplicationElement>>(); |
| 280 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses; | 301 Map<ClassElement, List<MixinApplicationElement>> _liveMixinUses; |
| 281 | 302 |
| 282 final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses = | 303 final Map<ClassElement, Set<ClassElement>> _typesImplementedBySubclasses = |
| 283 new Map<ClassElement, Set<ClassElement>>(); | 304 new Map<ClassElement, Set<ClassElement>>(); |
| 284 | 305 |
| 285 // We keep track of subtype and subclass relationships in four | 306 // We keep track of subtype and subclass relationships in four |
| 286 // distinct sets to make class hierarchy analysis faster. | 307 // distinct sets to make class hierarchy analysis faster. |
| 287 final Map<ClassElement, Set<ClassElement>> _subclasses = | 308 final Map<ClassElement, ClassHierarchyNode> _classHierarchyNodes = |
| 288 new Map<ClassElement, Set<ClassElement>>(); | 309 <ClassElement, ClassHierarchyNode>{}; |
| 289 final Map<ClassElement, Set<ClassElement>> _subtypes = | 310 final Map<ClassElement, Set<ClassElement>> _subtypes = |
| 290 new Map<ClassElement, Set<ClassElement>>(); | 311 new Map<ClassElement, Set<ClassElement>>(); |
| 291 | 312 |
| 292 final Set<Element> sideEffectsFreeElements = new Set<Element>(); | 313 final Set<Element> sideEffectsFreeElements = new Set<Element>(); |
| 293 | 314 |
| 294 final Set<Element> elementsThatCannotThrow = new Set<Element>(); | 315 final Set<Element> elementsThatCannotThrow = new Set<Element>(); |
| 295 | 316 |
| 296 final Set<Element> functionsThatMightBePassedToApply = | 317 final Set<Element> functionsThatMightBePassedToApply = |
| 297 new Set<FunctionElement>(); | 318 new Set<FunctionElement>(); |
| 298 | 319 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 312 | 333 |
| 313 Set<ClassElement> typesImplementedBySubclassesOf(ClassElement cls) { | 334 Set<ClassElement> typesImplementedBySubclassesOf(ClassElement cls) { |
| 314 return _typesImplementedBySubclasses[cls.declaration]; | 335 return _typesImplementedBySubclasses[cls.declaration]; |
| 315 } | 336 } |
| 316 | 337 |
| 317 World(Compiler compiler) | 338 World(Compiler compiler) |
| 318 : allFunctions = new FunctionSet(compiler), | 339 : allFunctions = new FunctionSet(compiler), |
| 319 this.compiler = compiler, | 340 this.compiler = compiler, |
| 320 alreadyPopulated = compiler.cacheStrategy.newSet(); | 341 alreadyPopulated = compiler.cacheStrategy.newSet(); |
| 321 | 342 |
| 343 ClassHierarchyNode classHierarchyNode(ClassElement cls) { |
| 344 return _classHierarchyNodes[cls]; |
| 345 } |
| 346 |
| 322 void populate() { | 347 void populate() { |
| 348 |
| 349 /// Ensure that a [ClassHierarchyNode] exists for [cls]. Updates the |
| 350 /// `isDirectlyInstantiated` and `isIndirectlyInstantiated` property of the |
| 351 /// node according the provided arguments and returns the node. |
| 352 ClassHierarchyNode createClassHierarchyNodeForClass( |
| 353 ClassElement cls, |
| 354 {bool directlyInstantiated: false, |
| 355 bool indirectlyInstantiated: false}) { |
| 356 assert(isInstantiated(cls)); |
| 357 |
| 358 ClassHierarchyNode node = _classHierarchyNodes.putIfAbsent(cls, () { |
| 359 ClassHierarchyNode node = new ClassHierarchyNode(cls); |
| 360 if (cls.superclass != null) { |
| 361 createClassHierarchyNodeForClass(cls.superclass, |
| 362 indirectlyInstantiated: |
| 363 directlyInstantiated || indirectlyInstantiated) |
| 364 .addDirectSubclass(node); |
| 365 } |
| 366 return node; |
| 367 }); |
| 368 if (directlyInstantiated) { |
| 369 node.isDirectlyInstantiated = true; |
| 370 } |
| 371 if (indirectlyInstantiated) { |
| 372 node.isIndirectlyInstantiated = true; |
| 373 } |
| 374 return node; |
| 375 } |
| 376 |
| 323 void addSubtypes(ClassElement cls) { | 377 void addSubtypes(ClassElement cls) { |
| 324 if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) { | 378 if (compiler.hasIncrementalSupport && !alreadyPopulated.add(cls)) { |
| 325 return; | 379 return; |
| 326 } | 380 } |
| 327 assert(cls.isDeclaration); | 381 assert(cls.isDeclaration); |
| 328 if (!cls.isResolved) { | 382 if (!cls.isResolved) { |
| 329 compiler.internalError(cls, 'Class "${cls.name}" is not resolved.'); | 383 compiler.internalError(cls, 'Class "${cls.name}" is not resolved.'); |
| 330 } | 384 } |
| 331 | 385 |
| 386 createClassHierarchyNodeForClass(cls, directlyInstantiated: true); |
| 387 |
| 332 for (DartType type in cls.allSupertypes) { | 388 for (DartType type in cls.allSupertypes) { |
| 333 Set<Element> subtypesOfSupertype = | 389 Set<Element> subtypesOfSupertype = |
| 334 _subtypes.putIfAbsent(type.element, () => new Set<ClassElement>()); | 390 _subtypes.putIfAbsent(type.element, () => new Set<ClassElement>()); |
| 335 subtypesOfSupertype.add(cls); | 391 subtypesOfSupertype.add(cls); |
| 336 } | 392 } |
| 337 | 393 |
| 338 // Walk through the superclasses, and record the types | 394 // Walk through the superclasses, and record the types |
| 339 // implemented by that type on the superclasses. | 395 // implemented by that type on the superclasses. |
| 340 ClassElement superclass = cls.superclass; | 396 ClassElement superclass = cls.superclass; |
| 341 while (superclass != null) { | 397 while (superclass != null) { |
| 342 Set<Element> subclassesOfSuperclass = | |
| 343 _subclasses.putIfAbsent(superclass, () => new Set<ClassElement>()); | |
| 344 subclassesOfSuperclass.add(cls); | |
| 345 | |
| 346 Set<Element> typesImplementedBySubclassesOfCls = | 398 Set<Element> typesImplementedBySubclassesOfCls = |
| 347 _typesImplementedBySubclasses.putIfAbsent( | 399 _typesImplementedBySubclasses.putIfAbsent( |
| 348 superclass, () => new Set<ClassElement>()); | 400 superclass, () => new Set<ClassElement>()); |
| 349 for (DartType current in cls.allSupertypes) { | 401 for (DartType current in cls.allSupertypes) { |
| 350 typesImplementedBySubclassesOfCls.add(current.element); | 402 typesImplementedBySubclassesOfCls.add(current.element); |
| 351 } | 403 } |
| 352 superclass = superclass.superclass; | 404 superclass = superclass.superclass; |
| 353 } | 405 } |
| 354 } | 406 } |
| 355 | 407 |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 // function expressions's element. | 552 // function expressions's element. |
| 501 // TODO(herhut): Generate classes for function expressions earlier. | 553 // TODO(herhut): Generate classes for function expressions earlier. |
| 502 if (element is closureMapping.SynthesizedCallMethodElementX) { | 554 if (element is closureMapping.SynthesizedCallMethodElementX) { |
| 503 return getMightBePassedToApply(element.expression); | 555 return getMightBePassedToApply(element.expression); |
| 504 } | 556 } |
| 505 return functionsThatMightBePassedToApply.contains(element); | 557 return functionsThatMightBePassedToApply.contains(element); |
| 506 } | 558 } |
| 507 | 559 |
| 508 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport; | 560 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport; |
| 509 } | 561 } |
| OLD | NEW |