OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.world; | 5 library dart2js.world; |
6 | 6 |
7 import 'closure.dart' show 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 'js_backend/backend.dart' show JavaScriptBackend; | 21 import 'js_backend/backend.dart' show JavaScriptBackend; |
22 import 'ordered_typeset.dart'; | 22 import 'ordered_typeset.dart'; |
23 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask; | 23 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask; |
24 import 'universe/class_set.dart'; | 24 import 'universe/class_set.dart'; |
25 import 'universe/function_set.dart' show FunctionSet; | 25 import 'universe/function_set.dart' show FunctionSet; |
26 import 'universe/selector.dart' show Selector; | 26 import 'universe/selector.dart' show Selector; |
27 import 'universe/side_effects.dart' show SideEffects; | 27 import 'universe/side_effects.dart' show SideEffects; |
28 import 'util/util.dart' show Link; | 28 import 'util/util.dart' show Link; |
29 | 29 |
30 /// The [ClassWorld] represents the information known about a program when | 30 /// Common superinterface for [OpenWorld] and [ClosedWorld]. |
| 31 abstract class World {} |
| 32 |
| 33 /// The [ClosedWorld] represents the information known about a program when |
31 /// compiling with closed-world semantics. | 34 /// compiling with closed-world semantics. |
32 /// | 35 /// |
33 /// Given the entrypoint of an application, we can track what's reachable from | 36 /// Given the entrypoint of an application, we can track what's reachable from |
34 /// it, what functions are called, what classes are allocated, which native | 37 /// it, what functions are called, what classes are allocated, which native |
35 /// JavaScript types are touched, what language features are used, and so on. | 38 /// 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 | 39 /// This precise knowledge about what's live in the program is later used in |
37 /// optimizations and other compiler decisions during code generation. | 40 /// optimizations and other compiler decisions during code generation. |
38 abstract class ClassWorld { | 41 abstract class ClosedWorld implements World { |
39 // TODO(johnniwinther): Refine this into a `BackendClasses` interface. | 42 // TODO(johnniwinther): Refine this into a `BackendClasses` interface. |
40 Backend get backend; | 43 Backend get backend; |
41 | 44 |
42 CoreClasses get coreClasses; | 45 CoreClasses get coreClasses; |
43 | 46 |
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]); | |
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 { | |
81 /// Returns `true` if [cls] is either directly or indirectly instantiated. | 47 /// Returns `true` if [cls] is either directly or indirectly instantiated. |
82 bool isInstantiated(ClassElement cls); | 48 bool isInstantiated(ClassElement cls); |
83 | 49 |
84 /// Returns `true` if [cls] is directly instantiated. | 50 /// Returns `true` if [cls] is directly instantiated. |
85 bool isDirectlyInstantiated(ClassElement cls); | 51 bool isDirectlyInstantiated(ClassElement cls); |
86 | 52 |
87 /// Returns `true` if [cls] is indirectly instantiated, that is through a | 53 /// Returns `true` if [cls] is indirectly instantiated, that is through a |
88 /// subclass. | 54 /// subclass. |
89 bool isIndirectlyInstantiated(ClassElement cls); | 55 bool isIndirectlyInstantiated(ClassElement cls); |
90 | 56 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 /// Returns `true` if [cls] or any superclass mixes in [mixin]. | 148 /// Returns `true` if [cls] or any superclass mixes in [mixin]. |
183 bool isSubclassOfMixinUseOf(ClassElement cls, ClassElement mixin); | 149 bool isSubclassOfMixinUseOf(ClassElement cls, ClassElement mixin); |
184 | 150 |
185 /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass | 151 /// Returns `true` if every subtype of [x] is a subclass of [y] or a subclass |
186 /// of a mixin application of [y]. | 152 /// of a mixin application of [y]. |
187 bool everySubtypeIsSubclassOfOrMixinUseOf(ClassElement x, ClassElement y); | 153 bool everySubtypeIsSubclassOfOrMixinUseOf(ClassElement x, ClassElement y); |
188 | 154 |
189 /// Returns `true` if any subclass of [superclass] implements [type]. | 155 /// Returns `true` if any subclass of [superclass] implements [type]. |
190 bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); | 156 bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); |
191 | 157 |
| 158 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies |
| 159 /// of known classes. |
| 160 /// |
| 161 /// This method is only provided for testing. For queries on classes, use the |
| 162 /// methods defined in [ClosedWorld]. |
| 163 ClassHierarchyNode getClassHierarchyNode(ClassElement cls); |
| 164 |
| 165 /// Returns [ClassSet] for [cls] used to model the extends and implements |
| 166 /// relations of known classes. |
| 167 /// |
| 168 /// This method is only provided for testing. For queries on classes, use the |
| 169 /// methods defined in [ClosedWorld]. |
| 170 ClassSet getClassSet(ClassElement cls); |
| 171 |
| 172 // TODO(johnniwinther): Find a better strategy for caching these. |
| 173 @deprecated |
| 174 List<Map<ClassElement, TypeMask>> get canonicalizedTypeMasks; |
| 175 |
192 /// Returns the [FunctionSet] containing all live functions in the closed | 176 /// Returns the [FunctionSet] containing all live functions in the closed |
193 /// world. | 177 /// world. |
194 FunctionSet get allFunctions; | 178 FunctionSet get allFunctions; |
195 | 179 |
196 /// Returns `true` if the field [element] is known to be effectively final. | 180 /// Returns `true` if the field [element] is known to be effectively final. |
197 bool fieldNeverChanges(Element element); | 181 bool fieldNeverChanges(Element element); |
198 | 182 |
199 /// Extends the receiver type [mask] for calling [selector] to take live | 183 /// Extends the receiver type [mask] for calling [selector] to take live |
200 /// `noSuchMethod` handlers into account. | 184 /// `noSuchMethod` handlers into account. |
201 TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask); | 185 TypeMask extendMaskIfReachesAll(Selector selector, TypeMask mask); |
(...skipping 21 matching lines...) Expand all Loading... |
223 bool getCannotThrow(Element element); | 207 bool getCannotThrow(Element element); |
224 | 208 |
225 /// Returns `true` if [element] is called in a loop. | 209 /// Returns `true` if [element] is called in a loop. |
226 // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'? | 210 // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'? |
227 bool isCalledInLoop(Element element); | 211 bool isCalledInLoop(Element element); |
228 | 212 |
229 /// Returns `true` if [element] might be passed to `Function.apply`. | 213 /// Returns `true` if [element] might be passed to `Function.apply`. |
230 // TODO(johnniwinther): Is this 'passed invocation target` or | 214 // TODO(johnniwinther): Is this 'passed invocation target` or |
231 // `passed as argument`? | 215 // `passed as argument`? |
232 bool getMightBePassedToApply(Element element); | 216 bool getMightBePassedToApply(Element element); |
| 217 |
| 218 /// Returns a string representation of the closed world. |
| 219 /// |
| 220 /// If [cls] is provided, the dump will contain only classes related to [cls]. |
| 221 String dump([ClassElement cls]); |
233 } | 222 } |
234 | 223 |
235 /// Interface for computing side effects and uses of elements. This is used | 224 /// Interface for computing side effects and uses of elements. This is used |
236 /// during type inference to compute the [ClosedWorld] for code generation. | 225 /// during type inference to compute the [ClosedWorld] for code generation. |
237 abstract class ClosedWorldRefiner { | 226 abstract class ClosedWorldRefiner { |
238 /// Registers the side [effects] of executing [element]. | 227 /// Registers the side [effects] of executing [element]. |
239 void registerSideEffects(Element element, SideEffects effects); | 228 void registerSideEffects(Element element, SideEffects effects); |
240 | 229 |
241 /// Registers the executing of [element] as without side effects. | 230 /// Registers the executing of [element] as without side effects. |
242 void registerSideEffectsFree(Element element); | 231 void registerSideEffectsFree(Element element); |
(...skipping 15 matching lines...) Expand all Loading... |
258 void addFunctionCalledInLoop(Element element); | 247 void addFunctionCalledInLoop(Element element); |
259 | 248 |
260 /// Registers that [element] is guaranteed not to throw an exception. | 249 /// Registers that [element] is guaranteed not to throw an exception. |
261 void registerCannotThrow(Element element); | 250 void registerCannotThrow(Element element); |
262 | 251 |
263 /// Adds the closure class [cls] to the inference world. The class is | 252 /// Adds the closure class [cls] to the inference world. The class is |
264 /// considered directly instantiated. | 253 /// considered directly instantiated. |
265 void registerClosureClass(ClassElement cls); | 254 void registerClosureClass(ClassElement cls); |
266 } | 255 } |
267 | 256 |
268 abstract class OpenWorld implements ClassWorld { | 257 abstract class OpenWorld implements World { |
269 /// Called to add [cls] to the set of known classes. | 258 /// Called to add [cls] to the set of known classes. |
270 /// | 259 /// |
271 /// This ensures that class hierarchy queries can be performed on [cls] and | 260 /// This ensures that class hierarchy queries can be performed on [cls] and |
272 /// classes that extend or implement it. | 261 /// classes that extend or implement it. |
273 void registerClass(ClassElement cls); | 262 void registerClass(ClassElement cls); |
274 | 263 |
275 void registerUsedElement(Element element); | 264 void registerUsedElement(Element element); |
276 void registerTypedef(TypedefElement typedef); | 265 void registerTypedef(TypedefElement typedef); |
277 | 266 |
278 ClosedWorld closeWorld(); | 267 ClosedWorld closeWorld(); |
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 void registerTypedef(TypedefElement typdef) { | 731 void registerTypedef(TypedefElement typdef) { |
743 _allTypedefs.add(typdef); | 732 _allTypedefs.add(typdef); |
744 } | 733 } |
745 | 734 |
746 Iterable<TypedefElement> get allTypedefs => _allTypedefs; | 735 Iterable<TypedefElement> get allTypedefs => _allTypedefs; |
747 | 736 |
748 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies | 737 /// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies |
749 /// of known classes. | 738 /// of known classes. |
750 /// | 739 /// |
751 /// This method is only provided for testing. For queries on classes, use the | 740 /// This method is only provided for testing. For queries on classes, use the |
752 /// methods defined in [ClassWorld]. | 741 /// methods defined in [ClosedWorld]. |
753 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) { | 742 ClassHierarchyNode getClassHierarchyNode(ClassElement cls) { |
754 return _classHierarchyNodes[cls.declaration]; | 743 return _classHierarchyNodes[cls.declaration]; |
755 } | 744 } |
756 | 745 |
757 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) { | 746 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) { |
758 cls = cls.declaration; | 747 cls = cls.declaration; |
759 return _classHierarchyNodes.putIfAbsent(cls, () { | 748 return _classHierarchyNodes.putIfAbsent(cls, () { |
760 ClassHierarchyNode parentNode; | 749 ClassHierarchyNode parentNode; |
761 if (cls.superclass != null) { | 750 if (cls.superclass != null) { |
762 parentNode = _ensureClassHierarchyNode(cls.superclass); | 751 parentNode = _ensureClassHierarchyNode(cls.superclass); |
763 } | 752 } |
764 return new ClassHierarchyNode(parentNode, cls); | 753 return new ClassHierarchyNode(parentNode, cls); |
765 }); | 754 }); |
766 } | 755 } |
767 | 756 |
768 /// Returns [ClassSet] for [cls] used to model the extends and implements | 757 /// Returns [ClassSet] for [cls] used to model the extends and implements |
769 /// relations of known classes. | 758 /// relations of known classes. |
770 /// | 759 /// |
771 /// This method is only provided for testing. For queries on classes, use the | 760 /// This method is only provided for testing. For queries on classes, use the |
772 /// methods defined in [ClassWorld]. | 761 /// methods defined in [ClosedWorld]. |
773 ClassSet getClassSet(ClassElement cls) { | 762 ClassSet getClassSet(ClassElement cls) { |
774 return _classSets[cls.declaration]; | 763 return _classSets[cls.declaration]; |
775 } | 764 } |
776 | 765 |
777 ClassSet _ensureClassSet(ClassElement cls) { | 766 ClassSet _ensureClassSet(ClassElement cls) { |
778 cls = cls.declaration; | 767 cls = cls.declaration; |
779 return _classSets.putIfAbsent(cls, () { | 768 return _classSets.putIfAbsent(cls, () { |
780 ClassHierarchyNode node = _ensureClassHierarchyNode(cls); | 769 ClassHierarchyNode node = _ensureClassHierarchyNode(cls); |
781 ClassSet classSet = new ClassSet(node); | 770 ClassSet classSet = new ClassSet(node); |
782 | 771 |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1017 if (element is SynthesizedCallMethodElementX) { | 1006 if (element is SynthesizedCallMethodElementX) { |
1018 return getMightBePassedToApply(element.expression); | 1007 return getMightBePassedToApply(element.expression); |
1019 } | 1008 } |
1020 return functionsThatMightBePassedToApply.contains(element); | 1009 return functionsThatMightBePassedToApply.contains(element); |
1021 } | 1010 } |
1022 | 1011 |
1023 @override | 1012 @override |
1024 bool getCurrentlyKnownMightBePassedToApply(Element element) { | 1013 bool getCurrentlyKnownMightBePassedToApply(Element element) { |
1025 return getMightBePassedToApply(element); | 1014 return getMightBePassedToApply(element); |
1026 } | 1015 } |
1027 | |
1028 bool get hasClosedWorldAssumption => !_compiler.options.hasIncrementalSupport; | |
1029 } | 1016 } |
OLD | NEW |