Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: pkg/compiler/lib/src/world.dart

Issue 2363773005: Move closed world reasoning methods from ClassWorld to ClosedWorld. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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;
(...skipping 23 matching lines...) Expand all
34 /// it, what functions are called, what classes are allocated, which native 34 /// it, what functions are called, what classes are allocated, which native
35 /// JavaScript types are touched, what language features are used, and so on. 35 /// JavaScript types are touched, what language features are used, and so on.
36 /// This precise knowledge about what's live in the program is later used in 36 /// This precise knowledge about what's live in the program is later used in
37 /// optimizations and other compiler decisions during code generation. 37 /// optimizations and other compiler decisions during code generation.
38 abstract class ClassWorld { 38 abstract class ClassWorld {
39 // TODO(johnniwinther): Refine this into a `BackendClasses` interface. 39 // TODO(johnniwinther): Refine this into a `BackendClasses` interface.
40 Backend get backend; 40 Backend get backend;
41 41
42 CoreClasses get coreClasses; 42 CoreClasses get coreClasses;
43 43
44 /// Returns `true` if the class world is closed.
45 bool get isClosed;
46
47 /// Returns `true` if closed-world assumptions can be made, that is,
48 /// incremental compilation isn't enabled.
49 bool get hasClosedWorldAssumption;
50
51 /// Returns a string representation of the closed world.
52 ///
53 /// If [cls] is provided, the dump will contain only classes related to [cls].
54 String dump([ClassElement cls]);
Harry Terkelsen 2016/09/23 17:20:27 @OnlyForTesting? Or whatever the annotation is?
Johnni Winther 2016/09/26 14:02:47 Haven't heard of it. Can you find its exactly loca
55
56 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
57 /// of known classes.
58 ///
59 /// This method is only provided for testing. For queries on classes, use the
60 /// methods defined in [ClassWorld].
61 ClassHierarchyNode getClassHierarchyNode(ClassElement cls);
62
63 /// Returns [ClassSet] for [cls] used to model the extends and implements
64 /// relations of known classes.
65 ///
66 /// This method is only provided for testing. For queries on classes, use the
67 /// methods defined in [ClassWorld].
68 ClassSet getClassSet(ClassElement cls);
69
70 // TODO(johnniwinther): Find a better strategy for caching these.
71 @deprecated
72 List<Map<ClassElement, TypeMask>> get canonicalizedTypeMasks;
73 }
74
75 /// The [ClosedWorld] represents the information known about a program when
76 /// compiling with closed-world semantics.
77 ///
78 /// This expands [ClassWorld] with information about live functions,
79 /// side effects, and selectors with known single targets.
80 abstract class ClosedWorld extends ClassWorld {
44 /// Returns `true` if [cls] is either directly or indirectly instantiated. 81 /// Returns `true` if [cls] is either directly or indirectly instantiated.
45 bool isInstantiated(ClassElement cls); 82 bool isInstantiated(ClassElement cls);
46 83
47 /// Returns `true` if [cls] is directly instantiated. 84 /// Returns `true` if [cls] is directly instantiated.
48 bool isDirectlyInstantiated(ClassElement cls); 85 bool isDirectlyInstantiated(ClassElement cls);
49 86
50 /// Returns `true` if [cls] is indirectly instantiated, that is through a 87 /// Returns `true` if [cls] is indirectly instantiated, that is through a
51 /// subclass. 88 /// subclass.
52 bool isIndirectlyInstantiated(ClassElement cls); 89 bool isIndirectlyInstantiated(ClassElement cls);
53 90
54 /// Returns `true` if [cls] is implemented by an instantiated class. 91 /// Returns `true` if [cls] is implemented by an instantiated class.
55 bool isImplemented(ClassElement cls); 92 bool isImplemented(ClassElement cls);
56 93
57 /// Returns `true` if the class world is closed.
58 bool get isClosed;
59
60 /// Return `true` if [x] is a subclass of [y]. 94 /// Return `true` if [x] is a subclass of [y].
61 bool isSubclassOf(ClassElement x, ClassElement y); 95 bool isSubclassOf(ClassElement x, ClassElement y);
62 96
63 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an 97 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an
64 /// instance of [y]. 98 /// instance of [y].
65 bool isSubtypeOf(ClassElement x, ClassElement y); 99 bool isSubtypeOf(ClassElement x, ClassElement y);
66 100
67 /// Returns an iterable over the live classes that extend [cls] including 101 /// Returns an iterable over the live classes that extend [cls] including
68 /// [cls] itself. 102 /// [cls] itself.
69 Iterable<ClassElement> subclassesOf(ClassElement cls); 103 Iterable<ClassElement> subclassesOf(ClassElement cls);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 /// Returns `true` if [cls] or any superclass mixes in [mixin]. 182 /// Returns `true` if [cls] or any superclass mixes in [mixin].
149 bool isSubclassOfMixinUseOf(ClassElement cls, ClassElement mixin); 183 bool isSubclassOfMixinUseOf(ClassElement cls, ClassElement mixin);
150 184
151 /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass 185 /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass
152 /// of a mixin application of [y]. 186 /// of a mixin application of [y].
153 bool everySubtypeIsSubclassOfOrMixinUseOf(ClassElement x, ClassElement y); 187 bool everySubtypeIsSubclassOfOrMixinUseOf(ClassElement x, ClassElement y);
154 188
155 /// Returns `true` if any subclass of [superclass] implements [type]. 189 /// Returns `true` if any subclass of [superclass] implements [type].
156 bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); 190 bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type);
157 191
158 /// Returns `true` if closed-world assumptions can be made, that is,
159 /// incremental compilation isn't enabled.
160 bool get hasClosedWorldAssumption;
161
162 /// Returns a string representation of the closed world.
163 ///
164 /// If [cls] is provided, the dump will contain only classes related to [cls].
165 String dump([ClassElement cls]);
166
167 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
168 /// of known classes.
169 ///
170 /// This method is only provided for testing. For queries on classes, use the
171 /// methods defined in [ClassWorld].
172 ClassHierarchyNode getClassHierarchyNode(ClassElement cls);
173
174 /// Returns [ClassSet] for [cls] used to model the extends and implements
175 /// relations of known classes.
176 ///
177 /// This method is only provided for testing. For queries on classes, use the
178 /// methods defined in [ClassWorld].
179 ClassSet getClassSet(ClassElement cls);
180
181 // TODO(johnniwinther): Find a better strategy for caching these.
182 @deprecated
183 List<Map<ClassElement, TypeMask>> get canonicalizedTypeMasks;
184 }
185
186 /// The [ClosedWorld] represents the information known about a program when
187 /// compiling with closed-world semantics.
188 ///
189 /// This expands [ClassWorld] with information about live functions,
190 /// side effects, and selectors with known single targets.
191 abstract class ClosedWorld extends ClassWorld {
192 /// Returns the [FunctionSet] containing all live functions in the closed 192 /// Returns the [FunctionSet] containing all live functions in the closed
193 /// world. 193 /// world.
194 FunctionSet get allFunctions; 194 FunctionSet get allFunctions;
195 195
196 /// Returns `true` if the field [element] is known to be effectively final. 196 /// Returns `true` if the field [element] is known to be effectively final.
197 bool fieldNeverChanges(Element element); 197 bool fieldNeverChanges(Element element);
198 198
199 /// Extends the receiver type [mask] for calling [selector] to take live 199 /// Extends the receiver type [mask] for calling [selector] to take live
200 /// `noSuchMethod` handlers into account. 200 /// `noSuchMethod` handlers into account.
201 TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask); 201 TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 // TODO(johnniwinther): Reinsert this or similar invariant. 298 // TODO(johnniwinther): Reinsert this or similar invariant.
299 (!mustBeInstantiated || 299 (!mustBeInstantiated ||
300 invariant(cls, isInstantiated(cls), 300 invariant(cls, isInstantiated(cls),
301 message: '$cls is not instantiated.'))*/ 301 message: '$cls is not instantiated.'))*/
302 ; 302 ;
303 } 303 }
304 304
305 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an 305 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an
306 /// instance of [y]. 306 /// instance of [y].
307 bool isSubtypeOf(ClassElement x, ClassElement y) { 307 bool isSubtypeOf(ClassElement x, ClassElement y) {
308 assert(isClosed);
308 assert(checkInvariants(x)); 309 assert(checkInvariants(x));
309 assert(checkInvariants(y, mustBeInstantiated: false)); 310 assert(checkInvariants(y, mustBeInstantiated: false));
310 311
311 if (y == coreClasses.objectClass) return true; 312 if (y == coreClasses.objectClass) return true;
312 if (x == coreClasses.objectClass) return false; 313 if (x == coreClasses.objectClass) return false;
313 if (x.asInstanceOf(y) != null) return true; 314 if (x.asInstanceOf(y) != null) return true;
314 if (y != coreClasses.functionClass) return false; 315 if (y != coreClasses.functionClass) return false;
315 return x.callType != null; 316 return x.callType != null;
316 } 317 }
317 318
318 /// Return `true` if [x] is a (non-strict) subclass of [y]. 319 /// Return `true` if [x] is a (non-strict) subclass of [y].
319 bool isSubclassOf(ClassElement x, ClassElement y) { 320 bool isSubclassOf(ClassElement x, ClassElement y) {
321 assert(isClosed);
320 assert(checkInvariants(x)); 322 assert(checkInvariants(x));
321 assert(checkInvariants(y)); 323 assert(checkInvariants(y));
322 324
323 if (y == coreClasses.objectClass) return true; 325 if (y == coreClasses.objectClass) return true;
324 if (x == coreClasses.objectClass) return false; 326 if (x == coreClasses.objectClass) return false;
325 while (x != null && x.hierarchyDepth >= y.hierarchyDepth) { 327 while (x != null && x.hierarchyDepth >= y.hierarchyDepth) {
326 if (x == y) return true; 328 if (x == y) return true;
327 x = x.superclass; 329 x = x.superclass;
328 } 330 }
329 return false; 331 return false;
330 } 332 }
331 333
332 @override 334 @override
333 bool isInstantiated(ClassElement cls) { 335 bool isInstantiated(ClassElement cls) {
336 assert(isClosed);
334 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; 337 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration];
335 return node != null && node.isInstantiated; 338 return node != null && node.isInstantiated;
336 } 339 }
337 340
338 @override 341 @override
339 bool isDirectlyInstantiated(ClassElement cls) { 342 bool isDirectlyInstantiated(ClassElement cls) {
343 assert(isClosed);
340 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; 344 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration];
341 return node != null && node.isDirectlyInstantiated; 345 return node != null && node.isDirectlyInstantiated;
342 } 346 }
343 347
344 @override 348 @override
345 bool isIndirectlyInstantiated(ClassElement cls) { 349 bool isIndirectlyInstantiated(ClassElement cls) {
350 assert(isClosed);
346 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration]; 351 ClassHierarchyNode node = _classHierarchyNodes[cls.declaration];
347 return node != null && node.isIndirectlyInstantiated; 352 return node != null && node.isIndirectlyInstantiated;
348 } 353 }
349 354
350 /// Returns `true` if [cls] is implemented by an instantiated class. 355 /// Returns `true` if [cls] is implemented by an instantiated class.
351 bool isImplemented(ClassElement cls) { 356 bool isImplemented(ClassElement cls) {
357 assert(isClosed);
352 return _compiler.resolverWorld.isImplemented(cls); 358 return _compiler.resolverWorld.isImplemented(cls);
353 } 359 }
354 360
355 /// Returns an iterable over the directly instantiated classes that extend 361 /// Returns an iterable over the directly instantiated classes that extend
356 /// [cls] possibly including [cls] itself, if it is live. 362 /// [cls] possibly including [cls] itself, if it is live.
357 Iterable<ClassElement> subclassesOf(ClassElement cls) { 363 Iterable<ClassElement> subclassesOf(ClassElement cls) {
364 assert(isClosed);
358 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; 365 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration];
359 if (hierarchy == null) return const <ClassElement>[]; 366 if (hierarchy == null) return const <ClassElement>[];
360 return hierarchy.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); 367 return hierarchy.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED);
361 } 368 }
362 369
363 /// Returns an iterable over the directly instantiated classes that extend 370 /// Returns an iterable over the directly instantiated classes that extend
364 /// [cls] _not_ including [cls] itself. 371 /// [cls] _not_ including [cls] itself.
365 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) { 372 Iterable<ClassElement> strictSubclassesOf(ClassElement cls) {
373 assert(isClosed);
366 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; 374 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
367 if (subclasses == null) return const <ClassElement>[]; 375 if (subclasses == null) return const <ClassElement>[];
368 return subclasses.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED, 376 return subclasses.subclassesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED,
369 strict: true); 377 strict: true);
370 } 378 }
371 379
372 /// Returns the number of live classes that extend [cls] _not_ 380 /// Returns the number of live classes that extend [cls] _not_
373 /// including [cls] itself. 381 /// including [cls] itself.
374 int strictSubclassCount(ClassElement cls) { 382 int strictSubclassCount(ClassElement cls) {
383 assert(isClosed);
375 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; 384 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
376 if (subclasses == null) return 0; 385 if (subclasses == null) return 0;
377 return subclasses.instantiatedSubclassCount; 386 return subclasses.instantiatedSubclassCount;
378 } 387 }
379 388
380 /// Applies [f] to each live class that extend [cls] _not_ including [cls] 389 /// Applies [f] to each live class that extend [cls] _not_ including [cls]
381 /// itself. 390 /// itself.
382 void forEachStrictSubclassOf( 391 void forEachStrictSubclassOf(
383 ClassElement cls, IterationStep f(ClassElement cls)) { 392 ClassElement cls, IterationStep f(ClassElement cls)) {
393 assert(isClosed);
384 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; 394 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
385 if (subclasses == null) return; 395 if (subclasses == null) return;
386 subclasses.forEachSubclass(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED, 396 subclasses.forEachSubclass(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED,
387 strict: true); 397 strict: true);
388 } 398 }
389 399
390 /// Returns `true` if [predicate] applies to any live class that extend [cls] 400 /// Returns `true` if [predicate] applies to any live class that extend [cls]
391 /// _not_ including [cls] itself. 401 /// _not_ including [cls] itself.
392 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) { 402 bool anyStrictSubclassOf(ClassElement cls, bool predicate(ClassElement cls)) {
403 assert(isClosed);
393 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; 404 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
394 if (subclasses == null) return false; 405 if (subclasses == null) return false;
395 return subclasses.anySubclass( 406 return subclasses.anySubclass(
396 predicate, ClassHierarchyNode.DIRECTLY_INSTANTIATED, 407 predicate, ClassHierarchyNode.DIRECTLY_INSTANTIATED,
397 strict: true); 408 strict: true);
398 } 409 }
399 410
400 /// Returns an iterable over the directly instantiated that implement [cls] 411 /// Returns an iterable over the directly instantiated that implement [cls]
401 /// possibly including [cls] itself, if it is live. 412 /// possibly including [cls] itself, if it is live.
402 Iterable<ClassElement> subtypesOf(ClassElement cls) { 413 Iterable<ClassElement> subtypesOf(ClassElement cls) {
414 assert(isClosed);
403 ClassSet classSet = _classSets[cls.declaration]; 415 ClassSet classSet = _classSets[cls.declaration];
404 if (classSet == null) { 416 if (classSet == null) {
405 return const <ClassElement>[]; 417 return const <ClassElement>[];
406 } else { 418 } else {
407 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED); 419 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED);
408 } 420 }
409 } 421 }
410 422
411 /// Returns an iterable over the directly instantiated that implement [cls] 423 /// Returns an iterable over the directly instantiated that implement [cls]
412 /// _not_ including [cls]. 424 /// _not_ including [cls].
413 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) { 425 Iterable<ClassElement> strictSubtypesOf(ClassElement cls) {
426 assert(isClosed);
414 ClassSet classSet = _classSets[cls.declaration]; 427 ClassSet classSet = _classSets[cls.declaration];
415 if (classSet == null) { 428 if (classSet == null) {
416 return const <ClassElement>[]; 429 return const <ClassElement>[];
417 } else { 430 } else {
418 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED, 431 return classSet.subtypesByMask(ClassHierarchyNode.DIRECTLY_INSTANTIATED,
419 strict: true); 432 strict: true);
420 } 433 }
421 } 434 }
422 435
423 /// Returns the number of live classes that implement [cls] _not_ 436 /// Returns the number of live classes that implement [cls] _not_
424 /// including [cls] itself. 437 /// including [cls] itself.
425 int strictSubtypeCount(ClassElement cls) { 438 int strictSubtypeCount(ClassElement cls) {
439 assert(isClosed);
426 ClassSet classSet = _classSets[cls.declaration]; 440 ClassSet classSet = _classSets[cls.declaration];
427 if (classSet == null) return 0; 441 if (classSet == null) return 0;
428 return classSet.instantiatedSubtypeCount; 442 return classSet.instantiatedSubtypeCount;
429 } 443 }
430 444
431 /// Applies [f] to each live class that implements [cls] _not_ including [cls] 445 /// Applies [f] to each live class that implements [cls] _not_ including [cls]
432 /// itself. 446 /// itself.
433 void forEachStrictSubtypeOf( 447 void forEachStrictSubtypeOf(
434 ClassElement cls, IterationStep f(ClassElement cls)) { 448 ClassElement cls, IterationStep f(ClassElement cls)) {
449 assert(isClosed);
435 ClassSet classSet = _classSets[cls.declaration]; 450 ClassSet classSet = _classSets[cls.declaration];
436 if (classSet == null) return; 451 if (classSet == null) return;
437 classSet.forEachSubtype(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED, 452 classSet.forEachSubtype(f, ClassHierarchyNode.DIRECTLY_INSTANTIATED,
438 strict: true); 453 strict: true);
439 } 454 }
440 455
441 /// Returns `true` if [predicate] applies to any live class that extend [cls] 456 /// Returns `true` if [predicate] applies to any live class that extend [cls]
442 /// _not_ including [cls] itself. 457 /// _not_ including [cls] itself.
443 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) { 458 bool anyStrictSubtypeOf(ClassElement cls, bool predicate(ClassElement cls)) {
459 assert(isClosed);
444 ClassSet classSet = _classSets[cls.declaration]; 460 ClassSet classSet = _classSets[cls.declaration];
445 if (classSet == null) return false; 461 if (classSet == null) return false;
446 return classSet.anySubtype( 462 return classSet.anySubtype(
447 predicate, ClassHierarchyNode.DIRECTLY_INSTANTIATED, 463 predicate, ClassHierarchyNode.DIRECTLY_INSTANTIATED,
448 strict: true); 464 strict: true);
449 } 465 }
450 466
451 /// Returns `true` if [a] and [b] have any known common subtypes. 467 /// Returns `true` if [a] and [b] have any known common subtypes.
452 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) { 468 bool haveAnyCommonSubtypes(ClassElement a, ClassElement b) {
469 assert(isClosed);
453 ClassSet classSetA = _classSets[a.declaration]; 470 ClassSet classSetA = _classSets[a.declaration];
454 ClassSet classSetB = _classSets[b.declaration]; 471 ClassSet classSetB = _classSets[b.declaration];
455 if (classSetA == null || classSetB == null) return false; 472 if (classSetA == null || classSetB == null) return false;
456 // TODO(johnniwinther): Implement an optimized query on [ClassSet]. 473 // TODO(johnniwinther): Implement an optimized query on [ClassSet].
457 Set<ClassElement> subtypesOfB = classSetB.subtypes().toSet(); 474 Set<ClassElement> subtypesOfB = classSetB.subtypes().toSet();
458 for (ClassElement subtypeOfA in classSetA.subtypes()) { 475 for (ClassElement subtypeOfA in classSetA.subtypes()) {
459 if (subtypesOfB.contains(subtypeOfA)) { 476 if (subtypesOfB.contains(subtypeOfA)) {
460 return true; 477 return true;
461 } 478 }
462 } 479 }
463 return false; 480 return false;
464 } 481 }
465 482
466 /// Returns `true` if any directly instantiated class other than [cls] extends 483 /// Returns `true` if any directly instantiated class other than [cls] extends
467 /// [cls]. 484 /// [cls].
468 bool hasAnyStrictSubclass(ClassElement cls) { 485 bool hasAnyStrictSubclass(ClassElement cls) {
486 assert(isClosed);
469 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration]; 487 ClassHierarchyNode subclasses = _classHierarchyNodes[cls.declaration];
470 if (subclasses == null) return false; 488 if (subclasses == null) return false;
471 return subclasses.isIndirectlyInstantiated; 489 return subclasses.isIndirectlyInstantiated;
472 } 490 }
473 491
474 /// Returns `true` if any directly instantiated class other than [cls] 492 /// Returns `true` if any directly instantiated class other than [cls]
475 /// implements [cls]. 493 /// implements [cls].
476 bool hasAnyStrictSubtype(ClassElement cls) { 494 bool hasAnyStrictSubtype(ClassElement cls) {
477 return strictSubtypeCount(cls) > 0; 495 return strictSubtypeCount(cls) > 0;
478 } 496 }
479 497
480 /// Returns `true` if all directly instantiated classes that implement [cls] 498 /// Returns `true` if all directly instantiated classes that implement [cls]
481 /// extend it. 499 /// extend it.
482 bool hasOnlySubclasses(ClassElement cls) { 500 bool hasOnlySubclasses(ClassElement cls) {
501 assert(isClosed);
483 // TODO(johnniwinther): move this to ClassSet? 502 // TODO(johnniwinther): move this to ClassSet?
484 if (cls == coreClasses.objectClass) return true; 503 if (cls == coreClasses.objectClass) return true;
485 ClassSet classSet = _classSets[cls.declaration]; 504 ClassSet classSet = _classSets[cls.declaration];
486 if (classSet == null) { 505 if (classSet == null) {
487 // Vacuously true. 506 // Vacuously true.
488 return true; 507 return true;
489 } 508 }
490 return classSet.hasOnlyInstantiatedSubclasses; 509 return classSet.hasOnlyInstantiatedSubclasses;
491 } 510 }
492 511
493 @override 512 @override
494 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) { 513 ClassElement getLubOfInstantiatedSubclasses(ClassElement cls) {
514 assert(isClosed);
495 if (backend.isJsInterop(cls)) { 515 if (backend.isJsInterop(cls)) {
496 return backend.helpers.jsJavaScriptObjectClass; 516 return backend.helpers.jsJavaScriptObjectClass;
497 } 517 }
498 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; 518 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration];
499 return hierarchy != null 519 return hierarchy != null
500 ? hierarchy.getLubOfInstantiatedSubclasses() 520 ? hierarchy.getLubOfInstantiatedSubclasses()
501 : null; 521 : null;
502 } 522 }
503 523
504 @override 524 @override
505 ClassElement getLubOfInstantiatedSubtypes(ClassElement cls) { 525 ClassElement getLubOfInstantiatedSubtypes(ClassElement cls) {
526 assert(isClosed);
506 if (backend.isJsInterop(cls)) { 527 if (backend.isJsInterop(cls)) {
507 return backend.helpers.jsJavaScriptObjectClass; 528 return backend.helpers.jsJavaScriptObjectClass;
508 } 529 }
509 ClassSet classSet = _classSets[cls.declaration]; 530 ClassSet classSet = _classSets[cls.declaration];
510 return classSet != null ? classSet.getLubOfInstantiatedSubtypes() : null; 531 return classSet != null ? classSet.getLubOfInstantiatedSubtypes() : null;
511 } 532 }
512 533
513 /// Returns an iterable over the common supertypes of the [classes]. 534 /// Returns an iterable over the common supertypes of the [classes].
514 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) { 535 Iterable<ClassElement> commonSupertypesOf(Iterable<ClassElement> classes) {
536 assert(isClosed);
515 Iterator<ClassElement> iterator = classes.iterator; 537 Iterator<ClassElement> iterator = classes.iterator;
516 if (!iterator.moveNext()) return const <ClassElement>[]; 538 if (!iterator.moveNext()) return const <ClassElement>[];
517 539
518 ClassElement cls = iterator.current; 540 ClassElement cls = iterator.current;
519 assert(checkInvariants(cls)); 541 assert(checkInvariants(cls));
520 OrderedTypeSet typeSet = cls.allSupertypesAndSelf; 542 OrderedTypeSet typeSet = cls.allSupertypesAndSelf;
521 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element); 543 if (!iterator.moveNext()) return typeSet.types.map((type) => type.element);
522 544
523 int depth = typeSet.maxDepth; 545 int depth = typeSet.maxDepth;
524 Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>(); 546 Link<OrderedTypeSet> otherTypeSets = const Link<OrderedTypeSet>();
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 _liveMixinUses[mixin] = uses; 603 _liveMixinUses[mixin] = uses;
582 } 604 }
583 } 605 }
584 } 606 }
585 Iterable<MixinApplicationElement> uses = _liveMixinUses[cls]; 607 Iterable<MixinApplicationElement> uses = _liveMixinUses[cls];
586 return uses != null ? uses : const <MixinApplicationElement>[]; 608 return uses != null ? uses : const <MixinApplicationElement>[];
587 } 609 }
588 610
589 /// Returns `true` if [cls] is mixed into a live class. 611 /// Returns `true` if [cls] is mixed into a live class.
590 bool isUsedAsMixin(ClassElement cls) { 612 bool isUsedAsMixin(ClassElement cls) {
613 assert(isClosed);
591 return !mixinUsesOf(cls).isEmpty; 614 return !mixinUsesOf(cls).isEmpty;
592 } 615 }
593 616
594 /// Returns `true` if any live class that mixes in [cls] implements [type]. 617 /// Returns `true` if any live class that mixes in [cls] implements [type].
595 bool hasAnySubclassOfMixinUseThatImplements( 618 bool hasAnySubclassOfMixinUseThatImplements(
596 ClassElement cls, ClassElement type) { 619 ClassElement cls, ClassElement type) {
620 assert(isClosed);
597 return mixinUsesOf(cls) 621 return mixinUsesOf(cls)
598 .any((use) => hasAnySubclassThatImplements(use, type)); 622 .any((use) => hasAnySubclassThatImplements(use, type));
599 } 623 }
600 624
601 /// Returns `true` if any live class that mixes in [mixin] is also a subclass 625 /// Returns `true` if any live class that mixes in [mixin] is also a subclass
602 /// of [superclass]. 626 /// of [superclass].
603 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin) { 627 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin) {
628 assert(isClosed);
604 return mixinUsesOf(mixin).any((each) => each.isSubclassOf(superclass)); 629 return mixinUsesOf(mixin).any((each) => each.isSubclassOf(superclass));
605 } 630 }
606 631
607 /// Returns `true` if [cls] or any superclass mixes in [mixin]. 632 /// Returns `true` if [cls] or any superclass mixes in [mixin].
608 bool isSubclassOfMixinUseOf(ClassElement cls, ClassElement mixin) { 633 bool isSubclassOfMixinUseOf(ClassElement cls, ClassElement mixin) {
634 assert(isClosed);
609 if (isUsedAsMixin(mixin)) { 635 if (isUsedAsMixin(mixin)) {
610 ClassElement current = cls.declaration; 636 ClassElement current = cls.declaration;
611 mixin = mixin.declaration; 637 mixin = mixin.declaration;
612 while (current != null) { 638 while (current != null) {
613 current = current.declaration; 639 current = current.declaration;
614 if (current.isMixinApplication) { 640 if (current.isMixinApplication) {
615 MixinApplicationElement application = current; 641 MixinApplicationElement application = current;
616 if (application.mixin.declaration == mixin) return true; 642 if (application.mixin.declaration == mixin) return true;
617 } 643 }
618 current = current.superclass; 644 current = current.superclass;
619 } 645 }
620 } 646 }
621 return false; 647 return false;
622 } 648 }
623 649
624 /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass 650 /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass
625 /// of a mixin application of [y]. 651 /// of a mixin application of [y].
626 bool everySubtypeIsSubclassOfOrMixinUseOf(ClassElement x, ClassElement y) { 652 bool everySubtypeIsSubclassOfOrMixinUseOf(ClassElement x, ClassElement y) {
653 assert(isClosed);
627 x = x.declaration; 654 x = x.declaration;
628 y = y.declaration; 655 y = y.declaration;
629 Map<ClassElement, bool> secondMap = 656 Map<ClassElement, bool> secondMap =
630 _subtypeCoveredByCache[x] ??= <ClassElement, bool>{}; 657 _subtypeCoveredByCache[x] ??= <ClassElement, bool>{};
631 return secondMap[y] ??= subtypesOf(x).every((ClassElement cls) => 658 return secondMap[y] ??= subtypesOf(x).every((ClassElement cls) =>
632 isSubclassOf(cls, y) || isSubclassOfMixinUseOf(cls, y)); 659 isSubclassOf(cls, y) || isSubclassOfMixinUseOf(cls, y));
633 } 660 }
634 661
635 /// Returns `true` if any subclass of [superclass] implements [type]. 662 /// Returns `true` if any subclass of [superclass] implements [type].
636 bool hasAnySubclassThatImplements( 663 bool hasAnySubclassThatImplements(
637 ClassElement superclass, ClassElement type) { 664 ClassElement superclass, ClassElement type) {
665 assert(isClosed);
638 Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass); 666 Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass);
639 if (subclasses == null) return false; 667 if (subclasses == null) return false;
640 return subclasses.contains(type); 668 return subclasses.contains(type);
641 } 669 }
642 670
643 final Compiler _compiler; 671 final Compiler _compiler;
644 JavaScriptBackend get backend => _compiler.backend; 672 JavaScriptBackend get backend => _compiler.backend;
645 CommonMasks get commonMasks => _compiler.commonMasks; 673 CommonMasks get commonMasks => _compiler.commonMasks;
646 final FunctionSet allFunctions; 674 final FunctionSet allFunctions;
647 final Set<Element> functionsCalledInLoop = new Set<Element>(); 675 final Set<Element> functionsCalledInLoop = new Set<Element>();
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
992 return functionsThatMightBePassedToApply.contains(element); 1020 return functionsThatMightBePassedToApply.contains(element);
993 } 1021 }
994 1022
995 @override 1023 @override
996 bool getCurrentlyKnownMightBePassedToApply(Element element) { 1024 bool getCurrentlyKnownMightBePassedToApply(Element element) {
997 return getMightBePassedToApply(element); 1025 return getMightBePassedToApply(element);
998 } 1026 }
999 1027
1000 bool get hasClosedWorldAssumption => !_compiler.options.hasIncrementalSupport; 1028 bool get hasClosedWorldAssumption => !_compiler.options.hasIncrementalSupport;
1001 } 1029 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/universe/function_set.dart ('k') | tests/compiler/dart2js/jsinterop/world_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698