Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 import '../common/resolution.dart'; | 5 //import '../common/resolution.dart'; |
|
Siggi Cherem (dart-lang)
2017/06/01 22:28:43
delete (and below)
Johnni Winther
2017/06/02 11:17:24
Done.
| |
| 6 import '../common_elements.dart'; | 6 import '../common_elements.dart'; |
| 7 import '../constants/constant_system.dart'; | 7 import '../constants/constant_system.dart'; |
| 8 import '../constants/values.dart'; | 8 import '../constants/values.dart'; |
| 9 import '../elements/elements.dart'; | 9 //import '../elements/elements.dart'; |
| 10 import '../elements/entities.dart'; | 10 import '../elements/entities.dart'; |
| 11 import '../elements/resolution_types.dart'; | 11 import '../elements/types.dart'; |
| 12 import '../universe/call_structure.dart'; | 12 import '../universe/call_structure.dart'; |
| 13 import '../universe/use.dart' show ConstantUse, StaticUse; | 13 import '../universe/use.dart' show ConstantUse, StaticUse; |
| 14 import '../universe/world_impact.dart' | 14 import '../universe/world_impact.dart' |
| 15 show WorldImpact, StagedWorldImpactBuilder; | 15 show WorldImpact, StagedWorldImpactBuilder; |
| 16 import 'backend_usage.dart' show BackendUsageBuilder; | 16 import 'backend_usage.dart' show BackendUsageBuilder; |
| 17 import 'native_data.dart'; | 17 import 'native_data.dart'; |
| 18 | 18 |
| 19 /** | 19 /** |
| 20 * Support for Custom Elements. | 20 * Support for Custom Elements. |
| 21 * | 21 * |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 48 * final tag; | 48 * final tag; |
| 49 * Component(this.tag); | 49 * Component(this.tag); |
| 50 * void register() => document.register(T, tag); | 50 * void register() => document.register(T, tag); |
| 51 * } | 51 * } |
| 52 * const Component<FancyButton>('x-fancy-button').register(); | 52 * const Component<FancyButton>('x-fancy-button').register(); |
| 53 * | 53 * |
| 54 * In these cases we conservatively generate all viable entries in the table. | 54 * In these cases we conservatively generate all viable entries in the table. |
| 55 */ | 55 */ |
| 56 abstract class CustomElementsAnalysisBase { | 56 abstract class CustomElementsAnalysisBase { |
| 57 final NativeBasicData _nativeData; | 57 final NativeBasicData _nativeData; |
| 58 final Resolution _resolution; | 58 final ElementEnvironment _elementEnvironment; |
| 59 final CommonElements _commonElements; | 59 final CommonElements _commonElements; |
| 60 | 60 |
| 61 CustomElementsAnalysisBase( | 61 CustomElementsAnalysisBase( |
| 62 this._resolution, this._commonElements, this._nativeData); | 62 this._elementEnvironment, this._commonElements, this._nativeData); |
| 63 | 63 |
| 64 CustomElementsAnalysisJoin get join; | 64 CustomElementsAnalysisJoin get join; |
| 65 | 65 |
| 66 void registerInstantiatedClass(ClassElement classElement) { | 66 void registerInstantiatedClass(ClassEntity cls) { |
| 67 classElement.ensureResolved(_resolution); | 67 if (!_nativeData.isNativeOrExtendsNative(cls)) return; |
| 68 if (!_nativeData.isNativeOrExtendsNative(classElement)) return; | 68 if (_elementEnvironment.isUnnamedMixinApplication(cls)) return; |
| 69 if (classElement.isMixinApplication) return; | 69 if (cls.isAbstract) return; |
| 70 if (classElement.isAbstract) return; | |
| 71 // JsInterop classes are opaque interfaces without a concrete | 70 // JsInterop classes are opaque interfaces without a concrete |
| 72 // implementation. | 71 // implementation. |
| 73 if (_nativeData.isJsInteropClass(classElement)) return; | 72 if (_nativeData.isJsInteropClass(cls)) return; |
| 74 join.instantiatedClasses.add(classElement); | 73 join.instantiatedClasses.add(cls); |
| 75 } | 74 } |
| 76 | 75 |
| 77 void registerStaticUse(MemberEntity element) { | 76 void registerStaticUse(MemberEntity element) { |
| 78 assert(element != null); | 77 assert(element != null); |
| 79 if (element == _commonElements.findIndexForNativeSubclassType) { | 78 if (element == _commonElements.findIndexForNativeSubclassType) { |
| 80 join.demanded = true; | 79 join.demanded = true; |
| 81 } | 80 } |
| 82 } | 81 } |
| 83 | 82 |
| 84 /// Computes the [WorldImpact] of the classes registered since last flush. | 83 /// Computes the [WorldImpact] of the classes registered since last flush. |
| 85 WorldImpact flush() => join.flush(); | 84 WorldImpact flush() => join.flush(); |
| 86 } | 85 } |
| 87 | 86 |
| 88 class CustomElementsResolutionAnalysis extends CustomElementsAnalysisBase { | 87 class CustomElementsResolutionAnalysis extends CustomElementsAnalysisBase { |
| 89 final CustomElementsAnalysisJoin join; | 88 final CustomElementsAnalysisJoin join; |
| 90 | 89 |
| 91 CustomElementsResolutionAnalysis( | 90 CustomElementsResolutionAnalysis( |
| 92 Resolution resolution, | |
| 93 ConstantSystem constantSystem, | 91 ConstantSystem constantSystem, |
| 92 ElementEnvironment elementEnvironment, | |
| 94 CommonElements commonElements, | 93 CommonElements commonElements, |
| 95 NativeBasicData nativeData, | 94 NativeBasicData nativeData, |
| 96 BackendUsageBuilder backendUsageBuilder) | 95 BackendUsageBuilder backendUsageBuilder) |
| 97 : join = new CustomElementsAnalysisJoin( | 96 : join = new CustomElementsAnalysisJoin( |
| 98 resolution, constantSystem, commonElements, nativeData, | 97 constantSystem, elementEnvironment, commonElements, nativeData, |
| 99 backendUsageBuilder: backendUsageBuilder), | 98 backendUsageBuilder: backendUsageBuilder), |
| 100 super(resolution, commonElements, nativeData) { | 99 super(elementEnvironment, commonElements, nativeData) { |
| 101 // TODO(sra): Remove this work-around. We should mark allClassesSelected in | 100 // TODO(sra): Remove this work-around. We should mark allClassesSelected in |
| 102 // both joins only when we see a construct generating an unknown [Type] but | 101 // both joins only when we see a construct generating an unknown [Type] but |
| 103 // we can't currently recognize all cases. In particular, the work-around | 102 // we can't currently recognize all cases. In particular, the work-around |
| 104 // for the unimplemented `ClassMirror.reflectedType` is not recognizable. | 103 // for the unimplemented `ClassMirror.reflectedType` is not recognizable. |
| 105 // TODO(12607): Match on [ClassMirror.reflectedType] | 104 // TODO(12607): Match on [ClassMirror.reflectedType] |
| 106 join.allClassesSelected = true; | 105 join.allClassesSelected = true; |
| 107 } | 106 } |
| 108 | 107 |
| 109 void registerTypeLiteral(ResolutionDartType type) { | 108 void registerTypeLiteral(DartType type) { |
| 110 if (type.isInterfaceType) { | 109 if (type.isInterfaceType) { |
| 111 // TODO(sra): If we had a flow query from the type literal expression to | 110 // TODO(sra): If we had a flow query from the type literal expression to |
| 112 // the Type argument of the metadata lookup, we could tell if this type | 111 // the Type argument of the metadata lookup, we could tell if this type |
| 113 // literal is really a demand for the metadata. | 112 // literal is really a demand for the metadata. |
| 114 join.selectedClasses.add(type.element); | 113 InterfaceType interfaceType = type; |
| 114 join.selectedClasses.add(interfaceType.element); | |
| 115 } else if (type.isTypeVariable) { | 115 } else if (type.isTypeVariable) { |
| 116 // This is a type parameter of a parameterized class. | 116 // This is a type parameter of a parameterized class. |
| 117 // TODO(sra): Is there a way to determine which types are bound to the | 117 // TODO(sra): Is there a way to determine which types are bound to the |
| 118 // parameter? | 118 // parameter? |
| 119 join.allClassesSelected = true; | 119 join.allClassesSelected = true; |
| 120 } | 120 } |
| 121 } | 121 } |
| 122 } | 122 } |
| 123 | 123 |
| 124 class CustomElementsCodegenAnalysis extends CustomElementsAnalysisBase { | 124 class CustomElementsCodegenAnalysis extends CustomElementsAnalysisBase { |
| 125 final CustomElementsAnalysisJoin join; | 125 final CustomElementsAnalysisJoin join; |
| 126 | 126 |
| 127 CustomElementsCodegenAnalysis( | 127 CustomElementsCodegenAnalysis( |
| 128 Resolution resolution, | |
| 129 ConstantSystem constantSystem, | 128 ConstantSystem constantSystem, |
| 130 CommonElements commonElements, | 129 CommonElements commonElements, |
| 130 ElementEnvironment elementEnvironment, | |
| 131 NativeBasicData nativeData) | 131 NativeBasicData nativeData) |
| 132 : join = new CustomElementsAnalysisJoin( | 132 : join = new CustomElementsAnalysisJoin( |
| 133 resolution, constantSystem, commonElements, nativeData), | 133 constantSystem, elementEnvironment, commonElements, nativeData), |
| 134 super(resolution, commonElements, nativeData) { | 134 super(elementEnvironment, commonElements, nativeData) { |
| 135 // TODO(sra): Remove this work-around. We should mark allClassesSelected in | 135 // TODO(sra): Remove this work-around. We should mark allClassesSelected in |
| 136 // both joins only when we see a construct generating an unknown [Type] but | 136 // both joins only when we see a construct generating an unknown [Type] but |
| 137 // we can't currently recognize all cases. In particular, the work-around | 137 // we can't currently recognize all cases. In particular, the work-around |
| 138 // for the unimplemented `ClassMirror.reflectedType` is not recognizable. | 138 // for the unimplemented `ClassMirror.reflectedType` is not recognizable. |
| 139 // TODO(12607): Match on [ClassMirror.reflectedType] | 139 // TODO(12607): Match on [ClassMirror.reflectedType] |
| 140 join.allClassesSelected = true; | 140 join.allClassesSelected = true; |
| 141 } | 141 } |
| 142 | 142 |
| 143 void registerTypeConstant(ClassElement element) { | 143 void registerTypeConstant(ClassEntity cls) { |
| 144 assert(element.isClass); | 144 join.selectedClasses.add(cls); |
| 145 join.selectedClasses.add(element); | |
| 146 } | 145 } |
| 147 | 146 |
| 148 bool get needsTable => join.demanded; | 147 bool get needsTable => join.demanded; |
| 149 | 148 |
| 150 bool needsClass(ClassElement classElement) => | 149 bool needsClass(ClassEntity cls) => join.activeClasses.contains(cls); |
| 151 join.activeClasses.contains(classElement); | |
| 152 | 150 |
| 153 List<ConstructorElement> constructors(ClassElement classElement) => | 151 List<ConstructorEntity> constructors(ClassEntity cls) => |
| 154 join.computeEscapingConstructors(classElement); | 152 join.computeEscapingConstructors(cls); |
| 155 } | 153 } |
| 156 | 154 |
| 157 class CustomElementsAnalysisJoin { | 155 class CustomElementsAnalysisJoin { |
| 158 final Resolution _resolution; | |
| 159 final ConstantSystem _constantSystem; | 156 final ConstantSystem _constantSystem; |
| 157 final ElementEnvironment _elementEnvironment; | |
| 160 final CommonElements _commonElements; | 158 final CommonElements _commonElements; |
| 161 final NativeBasicData _nativeData; | 159 final NativeBasicData _nativeData; |
| 162 final BackendUsageBuilder _backendUsageBuilder; | 160 final BackendUsageBuilder _backendUsageBuilder; |
| 163 | 161 |
| 164 final bool forResolution; | 162 final bool forResolution; |
| 165 | 163 |
| 166 final StagedWorldImpactBuilder impactBuilder = new StagedWorldImpactBuilder(); | 164 final StagedWorldImpactBuilder impactBuilder = new StagedWorldImpactBuilder(); |
| 167 | 165 |
| 168 // Classes that are candidates for needing constructors. Classes are moved to | 166 // Classes that are candidates for needing constructors. Classes are moved to |
| 169 // [activeClasses] when we know they need constructors. | 167 // [activeClasses] when we know they need constructors. |
| 170 final instantiatedClasses = new Set<ClassElement>(); | 168 final Set<ClassEntity> instantiatedClasses = new Set<ClassEntity>(); |
| 171 | 169 |
| 172 // Classes explicitly named. | 170 // Classes explicitly named. |
| 173 final selectedClasses = new Set<ClassElement>(); | 171 final Set<ClassEntity> selectedClasses = new Set<ClassEntity>(); |
| 174 | 172 |
| 175 // True if we must conservatively include all extension classes. | 173 // True if we must conservatively include all extension classes. |
| 176 bool allClassesSelected = false; | 174 bool allClassesSelected = false; |
| 177 | 175 |
| 178 // Did we see a demand for the data? | 176 // Did we see a demand for the data? |
| 179 bool demanded = false; | 177 bool demanded = false; |
| 180 | 178 |
| 181 // ClassesOutput: classes requiring metadata. | 179 // ClassesOutput: classes requiring metadata. |
| 182 final activeClasses = new Set<ClassElement>(); | 180 final Set<ClassEntity> activeClasses = new Set<ClassEntity>(); |
| 183 | 181 |
| 184 CustomElementsAnalysisJoin(this._resolution, this._constantSystem, | 182 CustomElementsAnalysisJoin(this._constantSystem, this._elementEnvironment, |
| 185 this._commonElements, this._nativeData, | 183 this._commonElements, this._nativeData, |
| 186 {BackendUsageBuilder backendUsageBuilder}) | 184 {BackendUsageBuilder backendUsageBuilder}) |
| 187 : this._backendUsageBuilder = backendUsageBuilder, | 185 : this._backendUsageBuilder = backendUsageBuilder, |
| 188 this.forResolution = backendUsageBuilder != null; | 186 this.forResolution = backendUsageBuilder != null; |
| 189 | 187 |
| 190 WorldImpact flush() { | 188 WorldImpact flush() { |
| 191 if (!demanded) return const WorldImpact(); | 189 if (!demanded) return const WorldImpact(); |
| 192 var newActiveClasses = new Set<ClassElement>(); | 190 var newActiveClasses = new Set<ClassEntity>(); |
| 193 for (ClassElement classElement in instantiatedClasses) { | 191 for (ClassEntity cls in instantiatedClasses) { |
| 194 bool isNative = _nativeData.isNativeClass(classElement); | 192 bool isNative = _nativeData.isNativeClass(cls); |
| 195 bool isExtension = | 193 bool isExtension = !isNative && _nativeData.isNativeOrExtendsNative(cls); |
| 196 !isNative && _nativeData.isNativeOrExtendsNative(classElement); | |
| 197 // Generate table entries for native classes that are explicitly named and | 194 // Generate table entries for native classes that are explicitly named and |
| 198 // extensions that fix our criteria. | 195 // extensions that fix our criteria. |
| 199 if ((isNative && selectedClasses.contains(classElement)) || | 196 if ((isNative && selectedClasses.contains(cls)) || |
| 200 (isExtension && | 197 (isExtension && |
| 201 (allClassesSelected || selectedClasses.contains(classElement)))) { | 198 (allClassesSelected || selectedClasses.contains(cls)))) { |
| 202 newActiveClasses.add(classElement); | 199 newActiveClasses.add(cls); |
| 203 Iterable<ConstructorElement> escapingConstructors = | 200 Iterable<ConstructorEntity> escapingConstructors = |
| 204 computeEscapingConstructors(classElement); | 201 computeEscapingConstructors(cls); |
| 205 for (ConstructorElement constructor in escapingConstructors) { | 202 for (ConstructorEntity constructor in escapingConstructors) { |
| 206 impactBuilder.registerStaticUse(new StaticUse.constructorInvoke( | 203 impactBuilder.registerStaticUse(new StaticUse.constructorInvoke( |
| 207 constructor, CallStructure.NO_ARGS)); | 204 constructor, CallStructure.NO_ARGS)); |
| 208 } | 205 } |
| 209 if (forResolution) { | 206 if (forResolution) { |
| 210 escapingConstructors | 207 escapingConstructors |
| 211 .forEach(_backendUsageBuilder.registerGlobalFunctionDependency); | 208 .forEach(_backendUsageBuilder.registerGlobalFunctionDependency); |
| 212 } | 209 } |
| 213 // Force the generaton of the type constant that is the key to an entry | 210 // Force the generaton of the type constant that is the key to an entry |
| 214 // in the generated table. | 211 // in the generated table. |
| 215 ConstantValue constant = _makeTypeConstant(classElement); | 212 ConstantValue constant = _makeTypeConstant(cls); |
| 216 impactBuilder | 213 impactBuilder |
| 217 .registerConstantUse(new ConstantUse.customElements(constant)); | 214 .registerConstantUse(new ConstantUse.customElements(constant)); |
| 218 } | 215 } |
| 219 } | 216 } |
| 220 activeClasses.addAll(newActiveClasses); | 217 activeClasses.addAll(newActiveClasses); |
| 221 instantiatedClasses.removeAll(newActiveClasses); | 218 instantiatedClasses.removeAll(newActiveClasses); |
| 222 return impactBuilder.flush(); | 219 return impactBuilder.flush(); |
| 223 } | 220 } |
| 224 | 221 |
| 225 TypeConstantValue _makeTypeConstant(ClassElement element) { | 222 TypeConstantValue _makeTypeConstant(ClassEntity cls) { |
| 226 ResolutionDartType elementType = element.rawType; | 223 DartType type = _elementEnvironment.getRawType(cls); |
| 227 return _constantSystem.createType(_commonElements, elementType); | 224 return _constantSystem.createType(_commonElements, type); |
| 228 } | 225 } |
| 229 | 226 |
| 230 List<ConstructorElement> computeEscapingConstructors( | 227 List<ConstructorEntity> computeEscapingConstructors(ClassEntity cls) { |
| 231 ClassElement classElement) { | 228 List<ConstructorEntity> result = <ConstructorEntity>[]; |
| 232 List<ConstructorElement> result = <ConstructorElement>[]; | |
| 233 // Only classes that extend native classes have constructors in the table. | 229 // Only classes that extend native classes have constructors in the table. |
| 234 // We could refine this to classes that extend Element, but that would break | 230 // We could refine this to classes that extend Element, but that would break |
| 235 // the tests and there is no sane reason to subclass other native classes. | 231 // the tests and there is no sane reason to subclass other native classes. |
| 236 if (_nativeData.isNativeClass(classElement)) return result; | 232 if (_nativeData.isNativeClass(cls)) return result; |
| 237 | 233 |
| 238 void selectGenerativeConstructors(ClassElement enclosing, Element member) { | 234 _elementEnvironment.forEachConstructor(cls, |
| 239 if (member.isGenerativeConstructor) { | 235 (ConstructorEntity constructor) { |
| 236 if (constructor.isGenerativeConstructor) { | |
| 240 // Ignore constructors that cannot be called with zero arguments. | 237 // Ignore constructors that cannot be called with zero arguments. |
| 241 ConstructorElement constructor = member; | 238 if (constructor.parameterStructure.requiredParameters == 0) { |
| 242 constructor.computeType(_resolution); | 239 result.add(constructor); |
|
Siggi Cherem (dart-lang)
2017/06/01 22:28:43
is computeType not needed anymore?
Johnni Winther
2017/06/02 11:17:24
Good call, it might.
| |
| 243 FunctionSignature parameters = constructor.functionSignature; | |
| 244 if (parameters.requiredParameterCount == 0) { | |
| 245 result.add(member); | |
| 246 } | 240 } |
| 247 } | 241 } |
| 248 } | 242 }); |
| 249 | |
| 250 classElement.forEachMember(selectGenerativeConstructors, | |
| 251 includeBackendMembers: false, includeSuperAndInjectedMembers: false); | |
| 252 return result; | 243 return result; |
| 253 } | 244 } |
| 254 } | 245 } |
| OLD | NEW |