| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 part of world_builder; | 5 part of world_builder; |
| 6 | 6 |
| 7 /// [ResolutionEnqueuerWorldBuilder] based on the [Element] model. | 7 /// [ResolutionEnqueuerWorldBuilder] based on the [Element] model. |
| 8 class ElementResolutionWorldBuilder extends ResolutionWorldBuilderBase { | 8 class ElementResolutionWorldBuilder extends ResolutionWorldBuilderBase { |
| 9 /// Used for testing the new more precise computation of instantiated types | 9 /// Used for testing the new more precise computation of instantiated types |
| 10 /// and classes. | 10 /// and classes. |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 _ClassUsage _createClassUsage(ClassElement cls) { | 99 _ClassUsage _createClassUsage(ClassElement cls) { |
| 100 cls.ensureResolved(_resolution); | 100 cls.ensureResolved(_resolution); |
| 101 _resolution.ensureClassMembers(cls); | 101 _resolution.ensureClassMembers(cls); |
| 102 return super._createClassUsage(cls); | 102 return super._createClassUsage(cls); |
| 103 } | 103 } |
| 104 | 104 |
| 105 /// Called to add [cls] to the set of known classes. | 105 /// Called to add [cls] to the set of known classes. |
| 106 /// | 106 /// |
| 107 /// This ensures that class hierarchy queries can be performed on [cls] and | 107 /// This ensures that class hierarchy queries can be performed on [cls] and |
| 108 /// classes that extend or implement it. | 108 /// classes that extend or implement it. |
| 109 void registerClass(ClassEntity cls) => _registerClass(cls); | 109 void registerClass(ClassElement cls) => _registerClass(cls.declaration); |
| 110 | 110 |
| 111 void _registerClass(ClassEntity cls, {bool isDirectlyInstantiated: false}) { | 111 void _registerClass(ClassEntity cls, {bool isDirectlyInstantiated: false}) { |
| 112 _ensureClassSet(cls); | 112 _ensureClassSet(cls); |
| 113 if (isDirectlyInstantiated) { | 113 if (isDirectlyInstantiated) { |
| 114 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); | 114 _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true); |
| 115 } | 115 } |
| 116 } | 116 } |
| 117 | 117 |
| 118 void _processInstantiatedClassMember( | 118 void _processInstantiatedClassMember( |
| 119 ClassEntity cls, MemberElement member, MemberUsedCallback memberUsed) { | 119 ClassEntity cls, MemberElement member, MemberUsedCallback memberUsed) { |
| 120 assert(invariant(member, member.isDeclaration)); | 120 assert(invariant(member, member.isDeclaration)); |
| 121 member.computeType(_resolution); | 121 member.computeType(_resolution); |
| 122 super._processInstantiatedClassMember(cls, member, memberUsed); | 122 super._processInstantiatedClassMember(cls, member, memberUsed); |
| 123 } | 123 } |
| 124 | 124 |
| 125 ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) { | 125 @override |
| 126 cls = cls.declaration; | 126 ClassEntity getAppliedMixin(ClassElement cls) { |
| 127 return _classHierarchyNodes.putIfAbsent(cls, () { | 127 if (cls.isMixinApplication) { |
| 128 ClassHierarchyNode parentNode; | 128 MixinApplicationElement mixinApplication = cls; |
| 129 if (cls.superclass != null) { | 129 // Note: If [mixinApplication] is malformed [mixin] is `null`. |
| 130 parentNode = _ensureClassHierarchyNode(cls.superclass); | 130 return mixinApplication.mixin; |
| 131 } | 131 } |
| 132 return new ClassHierarchyNode(parentNode, cls, cls.hierarchyDepth); | 132 return null; |
| 133 }); | |
| 134 } | 133 } |
| 135 | 134 |
| 136 ClassSet _ensureClassSet(ClassElement cls) { | 135 @override |
| 137 cls = cls.declaration; | 136 int getHierarchyDepth(ClassElement cls) => cls.hierarchyDepth; |
| 138 return _classSets.putIfAbsent(cls, () { | |
| 139 ClassHierarchyNode node = _ensureClassHierarchyNode(cls); | |
| 140 ClassSet classSet = new ClassSet(node); | |
| 141 | 137 |
| 142 for (ResolutionInterfaceType type in cls.allSupertypes) { | 138 @override |
| 143 // TODO(johnniwinther): Optimization: Avoid adding [cls] to | 139 bool checkClass(ClassElement cls) => cls.isDeclaration; |
| 144 // superclasses. | |
| 145 ClassSet subtypeSet = _ensureClassSet(type.element); | |
| 146 subtypeSet.addSubtype(node); | |
| 147 } | |
| 148 if (cls.isMixinApplication) { | |
| 149 // TODO(johnniwinther): Store this in the [ClassSet]. | |
| 150 MixinApplicationElement mixinApplication = cls; | |
| 151 if (mixinApplication.mixin != null) { | |
| 152 // If [mixinApplication] is malformed [mixin] is `null`. | |
| 153 registerMixinUse(mixinApplication, mixinApplication.mixin); | |
| 154 } | |
| 155 } | |
| 156 | 140 |
| 157 return classSet; | 141 @override |
| 158 }); | 142 bool validateClass(ClassElement cls) => cls.isResolved; |
| 159 } | |
| 160 | 143 |
| 161 void _updateSuperClassHierarchyNodeForClass(ClassHierarchyNode node) { | 144 @override |
| 162 // Ensure that classes implicitly implementing `Function` are in its | 145 bool implementsFunction(ClassElement cls) => |
| 163 // subtype set. | 146 cls.implementsFunction(_commonElements); |
| 164 ClassElement cls = node.cls; | |
| 165 if (cls != _commonElements.functionClass && | |
| 166 cls.implementsFunction(_commonElements)) { | |
| 167 ClassSet subtypeSet = _ensureClassSet(_commonElements.functionClass); | |
| 168 subtypeSet.addSubtype(node); | |
| 169 } | |
| 170 if (!node.isInstantiated && node.parentNode != null) { | |
| 171 _updateSuperClassHierarchyNodeForClass(node.parentNode); | |
| 172 } | |
| 173 } | |
| 174 | 147 |
| 175 void _updateClassHierarchyNodeForClass(ClassElement cls, | 148 @override |
| 176 {bool directlyInstantiated: false, bool abstractlyInstantiated: false}) { | 149 ClassEntity getSuperClass(ClassElement cls) => cls.superclass; |
| 177 ClassHierarchyNode node = _ensureClassHierarchyNode(cls); | 150 |
| 178 _updateSuperClassHierarchyNodeForClass(node); | 151 @override |
| 179 if (directlyInstantiated) { | 152 Iterable<InterfaceType> getSupertypes(ClassElement cls) => cls.allSupertypes; |
| 180 node.isDirectlyInstantiated = true; | |
| 181 } | |
| 182 if (abstractlyInstantiated) { | |
| 183 node.isAbstractlyInstantiated = true; | |
| 184 } | |
| 185 } | |
| 186 | 153 |
| 187 ClosedWorld closeWorld() { | 154 ClosedWorld closeWorld() { |
| 188 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses = | 155 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses = |
| 189 new Map<ClassEntity, Set<ClassEntity>>(); | 156 populateHierarchyNodes(); |
| 190 | |
| 191 /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated` | |
| 192 /// properties of the [ClassHierarchyNode] for [cls]. | |
| 193 | |
| 194 void addSubtypes(ClassElement cls, InstantiationInfo info) { | |
| 195 if (!info.hasInstantiation) { | |
| 196 return; | |
| 197 } | |
| 198 assert(cls.isDeclaration); | |
| 199 if (!cls.isResolved) { | |
| 200 throw new SpannableAssertionFailure( | |
| 201 cls, 'Class "${cls.name}" is not resolved.'); | |
| 202 } | |
| 203 | |
| 204 _updateClassHierarchyNodeForClass(cls, | |
| 205 directlyInstantiated: info.isDirectlyInstantiated, | |
| 206 abstractlyInstantiated: info.isAbstractlyInstantiated); | |
| 207 | |
| 208 // Walk through the superclasses, and record the types | |
| 209 // implemented by that type on the superclasses. | |
| 210 ClassElement superclass = cls.superclass; | |
| 211 while (superclass != null) { | |
| 212 Set<ClassEntity> typesImplementedBySubclassesOfCls = | |
| 213 typesImplementedBySubclasses.putIfAbsent( | |
| 214 superclass, () => new Set<ClassEntity>()); | |
| 215 for (ResolutionInterfaceType current in cls.allSupertypes) { | |
| 216 typesImplementedBySubclassesOfCls.add(current.element); | |
| 217 } | |
| 218 superclass = superclass.superclass; | |
| 219 } | |
| 220 } | |
| 221 | |
| 222 // Use the [:seenClasses:] set to include non-instantiated | |
| 223 // classes: if the superclass of these classes require RTI, then | |
| 224 // they also need RTI, so that a constructor passes the type | |
| 225 // variables to the super constructor. | |
| 226 forEachInstantiatedClass(addSubtypes); | |
| 227 | |
| 228 _closed = true; | 157 _closed = true; |
| 229 return _closedWorldCache = new ClosedWorldImpl( | 158 return _closedWorldCache = new ClosedWorldImpl( |
| 230 commonElements: _commonElements, | 159 commonElements: _commonElements, |
| 231 constantSystem: _backend.constantSystem, | 160 constantSystem: _backend.constantSystem, |
| 232 nativeData: _backend.nativeData, | 161 nativeData: _backend.nativeData, |
| 233 interceptorData: _backend.interceptorData, | 162 interceptorData: _backend.interceptorData, |
| 234 backendUsage: _backend.backendUsage, | 163 backendUsage: _backend.backendUsage, |
| 235 resolutionWorldBuilder: this, | 164 resolutionWorldBuilder: this, |
| 236 functionSetBuilder: _allFunctions, | 165 functionSetBuilder: _allFunctions, |
| 237 allTypedefs: _allTypedefs, | 166 allTypedefs: _allTypedefs, |
| 238 mixinUses: _mixinUses, | 167 mixinUses: _mixinUses, |
| 239 typesImplementedBySubclasses: typesImplementedBySubclasses, | 168 typesImplementedBySubclasses: typesImplementedBySubclasses, |
| 240 classHierarchyNodes: _classHierarchyNodes, | 169 classHierarchyNodes: _classHierarchyNodes, |
| 241 classSets: _classSets); | 170 classSets: _classSets); |
| 242 } | 171 } |
| 243 | 172 |
| 244 @override | 173 @override |
| 245 void registerMixinUse( | 174 void registerMixinUse( |
| 246 MixinApplicationElement mixinApplication, ClassElement mixin) { | 175 MixinApplicationElement mixinApplication, ClassElement mixin) { |
| 247 assert(mixin.isDeclaration); | 176 assert(mixin.isDeclaration); |
| 248 super.registerMixinUse(mixinApplication, mixin); | 177 super.registerMixinUse(mixinApplication, mixin); |
| 249 } | 178 } |
| 250 } | 179 } |
| OLD | NEW |