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

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

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

Powered by Google App Engine
This is Rietveld 408576698