Chromium Code Reviews| 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 part of dart2js; | 5 part of dart2js; |
| 6 | 6 |
| 7 class World { | 7 class World { |
| 8 final Compiler compiler; | 8 final Compiler compiler; |
| 9 final Map<ClassElement, Set<ClassElement>> subtypes; | 9 final Map<ClassElement, Set<ClassElement>> subtypes; |
| 10 final Map<ClassElement, Set<MixinApplicationElement>> mixinUses; | 10 final Map<ClassElement, Set<MixinApplicationElement>> mixinUses; |
| 11 final Map<ClassElement, Set<ClassElement>> typesImplementedBySubclasses; | 11 final Map<ClassElement, Set<ClassElement>> typesImplementedBySubclasses; |
| 12 final Set<ClassElement> classesNeedingRti; | 12 final Set<ClassElement> classesNeedingRti; |
| 13 final Map<ClassElement, Set<ClassElement>> rtiDependencies; | 13 final Map<ClassElement, Set<ClassElement>> rtiDependencies; |
| 14 final FunctionSet userDefinedGetters; | 14 final FullFunctionSet allFunctions; |
| 15 final FunctionSet userDefinedSetters; | |
|
ngeoffray
2013/02/18 08:35:34
So special handling user-defined getters/setters t
| |
| 16 | 15 |
| 17 World(Compiler compiler) | 16 World(Compiler compiler) |
| 18 : subtypes = new Map<ClassElement, Set<ClassElement>>(), | 17 : subtypes = new Map<ClassElement, Set<ClassElement>>(), |
| 19 mixinUses = new Map<ClassElement, Set<MixinApplicationElement>>(), | 18 mixinUses = new Map<ClassElement, Set<MixinApplicationElement>>(), |
| 20 typesImplementedBySubclasses = | 19 typesImplementedBySubclasses = |
| 21 new Map<ClassElement, Set<ClassElement>>(), | 20 new Map<ClassElement, Set<ClassElement>>(), |
| 22 userDefinedGetters = new FunctionSet(compiler), | |
| 23 userDefinedSetters = new FunctionSet(compiler), | |
| 24 classesNeedingRti = new Set<ClassElement>(), | 21 classesNeedingRti = new Set<ClassElement>(), |
| 25 rtiDependencies = new Map<ClassElement, Set<ClassElement>>(), | 22 rtiDependencies = new Map<ClassElement, Set<ClassElement>>(), |
| 23 allFunctions = new FullFunctionSet(compiler), | |
| 26 this.compiler = compiler; | 24 this.compiler = compiler; |
| 27 | 25 |
| 28 void populate() { | 26 void populate() { |
| 29 void addSubtypes(ClassElement cls) { | 27 void addSubtypes(ClassElement cls) { |
| 30 if (cls.resolutionState != STATE_DONE) { | 28 if (cls.resolutionState != STATE_DONE) { |
| 31 compiler.internalErrorOnElement( | 29 compiler.internalErrorOnElement( |
| 32 cls, 'Class "${cls.name.slowToString()}" is not resolved.'); | 30 cls, 'Class "${cls.name.slowToString()}" is not resolved.'); |
| 33 } | 31 } |
| 34 | 32 |
| 35 for (DartType type in cls.allSupertypes) { | 33 for (DartType type in cls.allSupertypes) { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 110 if (!element.isClass() || !dependency.isClass()) return; | 108 if (!element.isClass() || !dependency.isClass()) return; |
| 111 Set<ClassElement> classes = | 109 Set<ClassElement> classes = |
| 112 rtiDependencies.putIfAbsent(element, () => new Set<ClassElement>()); | 110 rtiDependencies.putIfAbsent(element, () => new Set<ClassElement>()); |
| 113 classes.add(dependency); | 111 classes.add(dependency); |
| 114 } | 112 } |
| 115 | 113 |
| 116 bool needsRti(ClassElement cls) { | 114 bool needsRti(ClassElement cls) { |
| 117 return classesNeedingRti.contains(cls) || compiler.enabledRuntimeType; | 115 return classesNeedingRti.contains(cls) || compiler.enabledRuntimeType; |
| 118 } | 116 } |
| 119 | 117 |
| 120 void recordUserDefinedGetter(Element element) { | |
| 121 assert(element.isGetter()); | |
| 122 userDefinedGetters.add(element); | |
| 123 } | |
| 124 | |
| 125 void recordUserDefinedSetter(Element element) { | |
| 126 assert(element.isSetter()); | |
| 127 userDefinedSetters.add(element); | |
| 128 } | |
| 129 | |
| 130 bool hasAnyUserDefinedGetter(Selector selector) { | 118 bool hasAnyUserDefinedGetter(Selector selector) { |
| 131 return !userDefinedGetters.filter(selector).isEmpty; | 119 return allFunctions.filter(selector).any((each) => each.isGetter()); |
| 132 } | 120 } |
| 133 | 121 |
| 134 bool hasAnyUserDefinedSetter(Selector selector) { | 122 bool hasAnyUserDefinedSetter(Selector selector) { |
| 135 return !userDefinedSetters.filter(selector).isEmpty; | 123 return allFunctions.filter(selector).any((each) => each.isSetter()); |
| 136 } | 124 } |
| 137 | 125 |
| 138 // Returns whether a subclass of [superclass] implements [type]. | 126 // Returns whether a subclass of [superclass] implements [type]. |
| 139 bool hasAnySubclassThatImplements(ClassElement superclass, DartType type) { | 127 bool hasAnySubclassThatImplements(ClassElement superclass, DartType type) { |
| 140 Set<ClassElement> subclasses = typesImplementedBySubclasses[superclass]; | 128 Set<ClassElement> subclasses = typesImplementedBySubclasses[superclass]; |
| 141 if (subclasses == null) return false; | 129 if (subclasses == null) return false; |
| 142 return subclasses.contains(type.element); | 130 return subclasses.contains(type.element); |
| 143 } | 131 } |
| 144 | 132 |
| 145 bool hasNoOverridingMember(Element element) { | |
| 146 ClassElement cls = element.getEnclosingClass(); | |
| 147 Set<ClassElement> subclasses = compiler.world.subtypes[cls]; | |
| 148 // TODO(ngeoffray): Implement the full thing. | |
| 149 return subclasses == null || subclasses.isEmpty; | |
| 150 } | |
| 151 | |
| 152 void registerUsedElement(Element element) { | 133 void registerUsedElement(Element element) { |
| 153 if (element.isInstanceMember() && !element.isAbstract(compiler)) { | 134 if (element.isInstanceMember() && !element.isAbstract(compiler)) { |
| 154 if (element.isGetter()) { | 135 allFunctions.add(element); |
| 155 // We're collecting user-defined getters to let the codegen know which | |
| 156 // field accesses might have side effects. | |
| 157 recordUserDefinedGetter(element); | |
| 158 } else if (element.isSetter()) { | |
| 159 recordUserDefinedSetter(element); | |
| 160 } | |
| 161 } | 136 } |
| 162 } | 137 } |
| 163 | 138 |
| 164 /** | 139 VariableElement locateSingleField(Selector selector) { |
| 165 * Returns a [MemberSet] that contains the possible targets of the given | 140 Element result = locateSingleElement(selector); |
| 166 * [selector] on a receiver with the given [type]. This includes all sub | 141 return (result != null && result.isField()) |
|
ngeoffray
2013/02/18 08:35:34
Fits in one line?
kasperl
2013/02/18 09:47:07
Done.
| |
| 167 * types. | 142 ? result |
| 168 */ | 143 : null; |
| 169 MemberSet _memberSetFor(DartType type, Selector selector) { | |
| 170 assert(compiler != null); | |
| 171 ClassElement cls = type.element; | |
| 172 SourceString name = selector.name; | |
| 173 LibraryElement library = selector.library; | |
| 174 MemberSet result = new MemberSet(name); | |
| 175 Element element = cls.implementation.lookupSelector(selector); | |
| 176 if (element != null) result.add(element); | |
| 177 | |
| 178 bool isPrivate = name.isPrivate(); | |
| 179 Set<ClassElement> subtypesOfCls = subtypes[cls]; | |
| 180 if (subtypesOfCls != null) { | |
| 181 for (ClassElement sub in subtypesOfCls) { | |
| 182 // Private members from a different library are not visible. | |
| 183 if (isPrivate && sub.getLibrary() != library) continue; | |
| 184 element = sub.implementation.lookupLocalMember(name); | |
| 185 if (element != null) result.add(element); | |
| 186 } | |
| 187 } | |
| 188 return result; | |
| 189 } | 144 } |
| 190 | 145 |
| 191 /** | 146 Element locateSingleElement(Selector selector) { |
| 192 * Returns the field in [type] described by the given [selector]. | 147 Iterable<Element> targets = allFunctions.filter(selector); |
| 193 * If no such field exists, or a subclass overrides the field | 148 if (targets.length != 1) return null; |
| 194 * returns [:null:]. | 149 Element result = targets.first; |
| 195 */ | 150 ClassElement enclosing = result.getEnclosingClass(); |
| 196 VariableElement locateSingleField(DartType type, Selector selector) { | 151 DartType receiverType = selector.receiverType; |
| 197 ClassElement cls = type.element; | 152 ClassElement receiverTypeElement = (receiverType == null) |
| 198 Element result = cls.implementation.lookupSelector(selector); | 153 ? compiler.objectClass |
| 199 if (result == null) return null; | 154 : receiverType.element; |
| 200 if (!result.isField()) return null; | 155 return (receiverTypeElement.isSubclassOf(enclosing)) |
|
ngeoffray
2013/02/18 08:35:34
Is this to prevent from subtypes? If selector is n
kasperl
2013/02/18 09:47:07
Added a comment to explain what's going on.
| |
| 201 | 156 ? result |
| 202 // Verify that no subclass overrides the field. | 157 : null; |
| 203 MemberSet memberSet = _memberSetFor(type, selector); | |
| 204 if (memberSet.elements.length != 1) return null; | |
| 205 assert(memberSet.elements.contains(result)); | |
| 206 return result; | |
| 207 } | 158 } |
| 208 | 159 |
| 209 Set<ClassElement> findNoSuchMethodHolders(DartType type) { | 160 Iterable<ClassElement> locateNoSuchMethodHolders(Selector selector) { |
| 210 Set<ClassElement> result = new Set<ClassElement>(); | |
| 211 Selector noSuchMethodSelector = new Selector.noSuchMethod(); | 161 Selector noSuchMethodSelector = new Selector.noSuchMethod(); |
| 212 MemberSet memberSet = _memberSetFor(type, noSuchMethodSelector); | 162 DartType receiverType = selector.receiverType; |
| 213 for (Element element in memberSet.elements) { | 163 if (receiverType != null) { |
| 214 ClassElement holder = element.getEnclosingClass(); | 164 noSuchMethodSelector = new TypedSelector( |
| 215 if (!identical(holder, compiler.objectClass) && | 165 receiverType, selector.typeKind, noSuchMethodSelector); |
| 216 noSuchMethodSelector.applies(element, compiler)) { | |
| 217 result.add(holder); | |
| 218 } | |
| 219 } | 166 } |
| 220 return result; | 167 ClassElement objectClass = compiler.objectClass; |
| 168 return allFunctions | |
|
ngeoffray
2013/02/18 08:35:34
Move this to the FullFunctionSet? Looks like witho
| |
| 169 .filter(noSuchMethodSelector) | |
| 170 .map((Element member) => member.getEnclosingClass()) | |
| 171 .where((ClassElement holder) => !identical(holder, objectClass)); | |
| 221 } | 172 } |
| 222 } | 173 } |
| 223 | |
| 224 /** | |
| 225 * A [MemberSet] contains all the possible targets for a selector. | |
| 226 */ | |
| 227 class MemberSet { | |
| 228 final Set<Element> elements; | |
| 229 final SourceString name; | |
| 230 | |
| 231 MemberSet(SourceString this.name) : elements = new Set<Element>(); | |
| 232 | |
| 233 void add(Element element) { | |
| 234 elements.add(element); | |
| 235 } | |
| 236 | |
| 237 bool get isEmpty => elements.isEmpty; | |
| 238 } | |
| OLD | NEW |