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 | 7 import 'closure.dart' show |
8 SynthesizedCallMethodElementX; | 8 SynthesizedCallMethodElementX; |
9 import 'common/backend_api.dart' show | 9 import 'common/backend_api.dart' show |
10 Backend; | 10 Backend; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
60 | 60 |
61 /// The [ClassElement] for the [double] class defined in 'dart:core'. | 61 /// The [ClassElement] for the [double] class defined in 'dart:core'. |
62 ClassElement get doubleClass; | 62 ClassElement get doubleClass; |
63 | 63 |
64 /// The [ClassElement] for the [String] class defined in 'dart:core'. | 64 /// The [ClassElement] for the [String] class defined in 'dart:core'. |
65 ClassElement get stringClass; | 65 ClassElement get stringClass; |
66 | 66 |
67 /// Returns `true` if [cls] is instantiated. | 67 /// Returns `true` if [cls] is instantiated. |
68 bool isInstantiated(ClassElement cls); | 68 bool isInstantiated(ClassElement cls); |
69 | 69 |
70 /// Returns `true` if [cls] is implemented by an instantiated class. | |
71 bool isImplemented(ClassElement cls); | |
72 | |
70 /// Returns `true` if the class world is closed. | 73 /// Returns `true` if the class world is closed. |
71 bool get isClosed; | 74 bool get isClosed; |
72 | 75 |
73 /// Return `true` if [x] is a subclass of [y]. | 76 /// Return `true` if [x] is a subclass of [y]. |
74 bool isSubclassOf(ClassElement x, ClassElement y); | 77 bool isSubclassOf(ClassElement x, ClassElement y); |
75 | 78 |
76 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an | 79 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an |
77 /// instance of [y]. | 80 /// instance of [y]. |
78 bool isSubtypeOf(ClassElement x, ClassElement y); | 81 bool isSubtypeOf(ClassElement x, ClassElement y); |
79 | 82 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
117 /// Returns `true` if any live class that mixes in [mixin] is also a subclass | 120 /// Returns `true` if any live class that mixes in [mixin] is also a subclass |
118 /// of [superclass]. | 121 /// of [superclass]. |
119 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin); | 122 bool hasAnySubclassThatMixes(ClassElement superclass, ClassElement mixin); |
120 | 123 |
121 /// Returns `true` if any subclass of [superclass] implements [type]. | 124 /// Returns `true` if any subclass of [superclass] implements [type]. |
122 bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); | 125 bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type); |
123 | 126 |
124 /// Returns `true` if closed-world assumptions can be made, that is, | 127 /// Returns `true` if closed-world assumptions can be made, that is, |
125 /// incremental compilation isn't enabled. | 128 /// incremental compilation isn't enabled. |
126 bool get hasClosedWorldAssumption; | 129 bool get hasClosedWorldAssumption; |
130 | |
131 /// Returns a string representation of the closed world. | |
132 String dump(); | |
127 } | 133 } |
128 | 134 |
129 class World implements ClassWorld { | 135 class World implements ClassWorld { |
130 ClassElement get objectClass => compiler.objectClass; | 136 ClassElement get objectClass => compiler.objectClass; |
131 ClassElement get functionClass => compiler.functionClass; | 137 ClassElement get functionClass => compiler.functionClass; |
132 ClassElement get boolClass => compiler.boolClass; | 138 ClassElement get boolClass => compiler.boolClass; |
133 ClassElement get numClass => compiler.numClass; | 139 ClassElement get numClass => compiler.numClass; |
134 ClassElement get intClass => compiler.intClass; | 140 ClassElement get intClass => compiler.intClass; |
135 ClassElement get doubleClass => compiler.doubleClass; | 141 ClassElement get doubleClass => compiler.doubleClass; |
136 ClassElement get stringClass => compiler.stringClass; | 142 ClassElement get stringClass => compiler.stringClass; |
137 ClassElement get nullClass => compiler.nullClass; | 143 ClassElement get nullClass => compiler.nullClass; |
138 | 144 |
139 /// Cache of [ti.FlatTypeMask]s grouped by the 8 possible values of the | 145 /// Cache of [ti.FlatTypeMask]s grouped by the 8 possible values of the |
140 /// [ti.FlatTypeMask.flags] property. | 146 /// [ti.FlatTypeMask.flags] property. |
141 List<Map<ClassElement, ti.TypeMask>> canonicalizedTypeMasks = | 147 List<Map<ClassElement, ti.TypeMask>> canonicalizedTypeMasks = |
142 new List<Map<ClassElement, ti.TypeMask>>.filled(8, null); | 148 new List<Map<ClassElement, ti.TypeMask>>.filled(8, null); |
143 | 149 |
144 bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { | 150 bool checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { |
145 return | 151 return |
146 invariant(cls, cls.isDeclaration, | 152 invariant(cls, cls.isDeclaration, |
147 message: '$cls must be the declaration.') && | 153 message: '$cls must be the declaration.') && |
148 invariant(cls, cls.isResolved, | 154 invariant(cls, cls.isResolved, |
149 message: '$cls must be resolved.') && | 155 message: '$cls must be resolved.')/* && |
156 // TODO(johnniwinther): Reinsert this or similar invariant. | |
150 (!mustBeInstantiated || | 157 (!mustBeInstantiated || |
151 invariant(cls, isInstantiated(cls), | 158 invariant(cls, isInstantiated(cls), |
152 message: '$cls is not instantiated.')); | 159 message: '$cls is not instantiated.'))*/; |
153 } | 160 } |
154 | 161 |
155 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an | 162 /// Returns `true` if [x] is a subtype of [y], that is, if [x] implements an |
156 /// instance of [y]. | 163 /// instance of [y]. |
157 bool isSubtypeOf(ClassElement x, ClassElement y) { | 164 bool isSubtypeOf(ClassElement x, ClassElement y) { |
158 assert(checkInvariants(x)); | 165 assert(checkInvariants(x)); |
159 assert(checkInvariants(y, mustBeInstantiated: false)); | 166 assert(checkInvariants(y, mustBeInstantiated: false)); |
160 | 167 |
161 if (y == objectClass) return true; | 168 if (y == objectClass) return true; |
162 if (x == objectClass) return false; | 169 if (x == objectClass) return false; |
163 if (x.asInstanceOf(y) != null) return true; | 170 if (x.asInstanceOf(y) != null) return true; |
164 if (y != functionClass) return false; | 171 if (y != functionClass) return false; |
165 return x.callType != null; | 172 return x.callType != null; |
166 } | 173 } |
167 | 174 |
168 /// Return `true` if [x] is a (non-strict) subclass of [y]. | 175 /// Return `true` if [x] is a (non-strict) subclass of [y]. |
169 bool isSubclassOf(ClassElement x, ClassElement y) { | 176 bool isSubclassOf(ClassElement x, ClassElement y) { |
170 assert(checkInvariants(x)); | 177 assert(checkInvariants(x)); |
171 assert(checkInvariants(y)); | 178 assert(checkInvariants(y)); |
172 | 179 |
173 if (y == objectClass) return true; | 180 if (y == objectClass) return true; |
174 if (x == objectClass) return false; | 181 if (x == objectClass) return false; |
175 while (x != null && x.hierarchyDepth >= y.hierarchyDepth) { | 182 while (x != null && x.hierarchyDepth >= y.hierarchyDepth) { |
176 if (x == y) return true; | 183 if (x == y) return true; |
177 x = x.superclass; | 184 x = x.superclass; |
178 } | 185 } |
179 return false; | 186 return false; |
180 } | 187 } |
181 | 188 |
182 /// Returns `true` if [cls] is instantiated. | 189 /// Returns `true` if [cls] is instantiated either directly or through a |
190 /// subclass. | |
183 bool isInstantiated(ClassElement cls) { | 191 bool isInstantiated(ClassElement cls) { |
184 return compiler.resolverWorld.isInstantiated(cls); | 192 return compiler.resolverWorld.isInstantiated(cls); |
185 } | 193 } |
186 | 194 |
195 /// Returns `true` if [cls] is implemented by an instantiated class. | |
196 bool isImplemented(ClassElement cls) { | |
197 return compiler.resolverWorld.isImplemented(cls); | |
198 } | |
199 | |
187 /// Returns an iterable over the directly instantiated classes that extend | 200 /// Returns an iterable over the directly instantiated classes that extend |
188 /// [cls] possibly including [cls] itself, if it is live. | 201 /// [cls] possibly including [cls] itself, if it is live. |
189 Iterable<ClassElement> subclassesOf(ClassElement cls) { | 202 Iterable<ClassElement> subclassesOf(ClassElement cls) { |
190 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; | 203 ClassHierarchyNode hierarchy = _classHierarchyNodes[cls.declaration]; |
191 if (hierarchy == null) return const <ClassElement>[]; | 204 if (hierarchy == null) return const <ClassElement>[]; |
192 return hierarchy.subclasses( | 205 return hierarchy.subclasses( |
193 includeIndirectlyInstantiated: false, | 206 includeIndirectlyInstantiated: false, |
194 includeUninstantiated: false); | 207 includeUninstantiated: false); |
195 } | 208 } |
196 | 209 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
302 Iterable<MixinApplicationElement> uses = _mixinUses[cls]; | 315 Iterable<MixinApplicationElement> uses = _mixinUses[cls]; |
303 return uses != null ? uses : const <MixinApplicationElement>[]; | 316 return uses != null ? uses : const <MixinApplicationElement>[]; |
304 } | 317 } |
305 | 318 |
306 /// Returns an iterable over the live mixin applications that mixin [cls]. | 319 /// Returns an iterable over the live mixin applications that mixin [cls]. |
307 Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls) { | 320 Iterable<MixinApplicationElement> mixinUsesOf(ClassElement cls) { |
308 assert(isClosed); | 321 assert(isClosed); |
309 if (_liveMixinUses == null) { | 322 if (_liveMixinUses == null) { |
310 _liveMixinUses = new Map<ClassElement, List<MixinApplicationElement>>(); | 323 _liveMixinUses = new Map<ClassElement, List<MixinApplicationElement>>(); |
311 for (ClassElement mixin in _mixinUses.keys) { | 324 for (ClassElement mixin in _mixinUses.keys) { |
312 Iterable<MixinApplicationElement> uses = | 325 List<MixinApplicationElement> uses = <MixinApplicationElement>[]; |
313 _mixinUses[mixin].where(isInstantiated); | 326 void addLiveUse(MixinApplicationElement mixinApplication) { |
karlklose
2015/09/17 10:42:38
Consider push this local function to the beginning
Johnni Winther
2015/09/17 12:56:40
It uses [uses]. Added an empty line before and aft
| |
314 if (uses.isNotEmpty) _liveMixinUses[mixin] = uses.toList(); | 327 if (isInstantiated(mixinApplication)) { |
328 uses.add(mixinApplication); | |
329 } else if (mixinApplication.isNamedMixinApplication) { | |
330 List<MixinApplicationElement> next = _mixinUses[mixinApplication]; | |
331 if (next != null) { | |
332 next.forEach(addLiveUse); | |
333 } | |
334 } | |
335 } | |
336 _mixinUses[mixin].forEach(addLiveUse); | |
337 if (uses.isNotEmpty) { | |
338 _liveMixinUses[mixin] = uses; | |
339 } | |
315 } | 340 } |
316 } | 341 } |
317 Iterable<MixinApplicationElement> uses = _liveMixinUses[cls]; | 342 Iterable<MixinApplicationElement> uses = _liveMixinUses[cls]; |
318 return uses != null ? uses : const <MixinApplicationElement>[]; | 343 return uses != null ? uses : const <MixinApplicationElement>[]; |
319 } | 344 } |
320 | 345 |
321 /// Returns `true` if [cls] is mixed into a live class. | 346 /// Returns `true` if [cls] is mixed into a live class. |
322 bool isUsedAsMixin(ClassElement cls) { | 347 bool isUsedAsMixin(ClassElement cls) { |
323 return !mixinUsesOf(cls).isEmpty; | 348 return !mixinUsesOf(cls).isEmpty; |
324 } | 349 } |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
498 } | 523 } |
499 } | 524 } |
500 | 525 |
501 // Use the [:seenClasses:] set to include non-instantiated | 526 // Use the [:seenClasses:] set to include non-instantiated |
502 // classes: if the superclass of these classes require RTI, then | 527 // classes: if the superclass of these classes require RTI, then |
503 // they also need RTI, so that a constructor passes the type | 528 // they also need RTI, so that a constructor passes the type |
504 // variables to the super constructor. | 529 // variables to the super constructor. |
505 compiler.resolverWorld.directlyInstantiatedClasses.forEach(addSubtypes); | 530 compiler.resolverWorld.directlyInstantiatedClasses.forEach(addSubtypes); |
506 } | 531 } |
507 | 532 |
533 @override | |
534 String dump() { | |
535 StringBuffer sb = new StringBuffer(); | |
536 sb.write("Instantiated classes in the closed world:\n"); | |
537 getClassHierarchyNode(compiler.objectClass) | |
538 .printOn(sb, ' ', instantiatedOnly: true); | |
539 return sb.toString(); | |
540 } | |
541 | |
508 void registerMixinUse(MixinApplicationElement mixinApplication, | 542 void registerMixinUse(MixinApplicationElement mixinApplication, |
509 ClassElement mixin) { | 543 ClassElement mixin) { |
510 // TODO(johnniwinther): Add map restricted to live classes. | 544 // TODO(johnniwinther): Add map restricted to live classes. |
511 // We don't support patch classes as mixin. | 545 // We don't support patch classes as mixin. |
512 assert(mixin.isDeclaration); | 546 assert(mixin.isDeclaration); |
513 List<MixinApplicationElement> users = | 547 List<MixinApplicationElement> users = |
514 _mixinUses.putIfAbsent(mixin, () => | 548 _mixinUses.putIfAbsent(mixin, () => |
515 new List<MixinApplicationElement>()); | 549 new List<MixinApplicationElement>()); |
516 users.add(mixinApplication); | 550 users.add(mixinApplication); |
517 } | 551 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
645 // function expressions's element. | 679 // function expressions's element. |
646 // TODO(herhut): Generate classes for function expressions earlier. | 680 // TODO(herhut): Generate classes for function expressions earlier. |
647 if (element is SynthesizedCallMethodElementX) { | 681 if (element is SynthesizedCallMethodElementX) { |
648 return getMightBePassedToApply(element.expression); | 682 return getMightBePassedToApply(element.expression); |
649 } | 683 } |
650 return functionsThatMightBePassedToApply.contains(element); | 684 return functionsThatMightBePassedToApply.contains(element); |
651 } | 685 } |
652 | 686 |
653 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport; | 687 bool get hasClosedWorldAssumption => !compiler.hasIncrementalSupport; |
654 } | 688 } |
OLD | NEW |