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

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

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

Powered by Google App Engine
This is Rietveld 408576698