| 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 library dart2js.js_emitter.metadata_collector; | 5 library dart2js.js_emitter.metadata_collector; |
| 6 | 6 |
| 7 import 'package:js_ast/src/precedence.dart' as js_precedence; | 7 import 'package:js_ast/src/precedence.dart' as js_precedence; |
| 8 | 8 |
| 9 import '../common.dart'; | 9 import '../common.dart'; |
| 10 import '../compiler.dart' show Compiler; | |
| 11 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
| 12 import '../elements/resolution_types.dart' | 11 import '../elements/resolution_types.dart' |
| 13 show ResolutionDartType, ResolutionTypedefType; | 12 show ResolutionDartType, ResolutionTypedefType; |
| 14 import '../deferred_load.dart' show OutputUnit; | 13 import '../deferred_load.dart' show DeferredLoadTask, OutputUnit; |
| 15 import '../elements/elements.dart' | 14 import '../elements/elements.dart' |
| 16 show | 15 show |
| 17 ClassElement, | 16 ClassElement, |
| 18 ConstructorElement, | 17 ConstructorElement, |
| 19 Element, | 18 Element, |
| 20 FieldElement, | 19 FieldElement, |
| 21 FunctionElement, | 20 FunctionElement, |
| 22 FunctionSignature, | 21 FunctionSignature, |
| 23 LibraryElement, | 22 LibraryElement, |
| 24 MemberElement, | 23 MemberElement, |
| 25 MethodElement, | 24 MethodElement, |
| 26 MetadataAnnotation, | 25 MetadataAnnotation, |
| 27 ParameterElement; | 26 ParameterElement; |
| 28 import '../js/js.dart' as jsAst; | 27 import '../js/js.dart' as jsAst; |
| 29 import '../js/js.dart' show js; | 28 import '../js/js.dart' show js; |
| 30 import '../js_backend/js_backend.dart' | 29 import '../js_backend/backend.dart' show RuntimeTypesEncoder; |
| 31 show JavaScriptBackend, TypeVariableCodegenAnalysis; | 30 import '../js_backend/constant_handler_javascript.dart'; |
| 31 import '../js_backend/mirrors_data.dart'; |
| 32 import '../js_backend/type_variable_handler.dart' |
| 33 show TypeVariableCodegenAnalysis; |
| 34 import '../options.dart'; |
| 32 | 35 |
| 33 import 'code_emitter_task.dart' show Emitter; | 36 import 'code_emitter_task.dart' show Emitter; |
| 34 | 37 |
| 35 /// Represents an entry's position in one of the global metadata arrays. | 38 /// Represents an entry's position in one of the global metadata arrays. |
| 36 /// | 39 /// |
| 37 /// [_rc] is used to count the number of references of the token in the | 40 /// [_rc] is used to count the number of references of the token in the |
| 38 /// ast for a program. | 41 /// ast for a program. |
| 39 /// [value] is the actual position, once they have been finalized. | 42 /// [value] is the actual position, once they have been finalized. |
| 40 abstract class _MetadataEntry extends jsAst.DeferredNumber | 43 abstract class _MetadataEntry extends jsAst.DeferredNumber |
| 41 implements Comparable, jsAst.ReferenceCountedAstNode { | 44 implements Comparable, jsAst.ReferenceCountedAstNode { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 | 131 |
| 129 jsAst.Expression get value { | 132 jsAst.Expression get value { |
| 130 assert(_value != null); | 133 assert(_value != null); |
| 131 return _value; | 134 return _value; |
| 132 } | 135 } |
| 133 | 136 |
| 134 int get precedenceLevel => js_precedence.PRIMARY; | 137 int get precedenceLevel => js_precedence.PRIMARY; |
| 135 } | 138 } |
| 136 | 139 |
| 137 class MetadataCollector implements jsAst.TokenFinalizer { | 140 class MetadataCollector implements jsAst.TokenFinalizer { |
| 138 final Compiler _compiler; | 141 final CompilerOptions _options; |
| 142 final DiagnosticReporter reporter; |
| 143 final DeferredLoadTask _deferredLoadTask; |
| 139 final Emitter _emitter; | 144 final Emitter _emitter; |
| 145 final JavaScriptConstantCompiler _constants; |
| 146 final TypeVariableCodegenAnalysis _typeVariableCodegenAnalysis; |
| 147 final MirrorsData _mirrorsData; |
| 148 final RuntimeTypesEncoder _rtiEncoder; |
| 140 | 149 |
| 141 /// A token for a list of expressions that represent metadata, parameter names | 150 /// A token for a list of expressions that represent metadata, parameter names |
| 142 /// and type variable types. | 151 /// and type variable types. |
| 143 final _MetadataList _globalMetadata = new _MetadataList(); | 152 final _MetadataList _globalMetadata = new _MetadataList(); |
| 144 jsAst.Expression get globalMetadata => _globalMetadata; | 153 jsAst.Expression get globalMetadata => _globalMetadata; |
| 145 | 154 |
| 146 /// A map used to canonicalize the entries of globalMetadata. | 155 /// A map used to canonicalize the entries of globalMetadata. |
| 147 Map<String, _BoundMetadataEntry> _globalMetadataMap; | 156 Map<String, _BoundMetadataEntry> _globalMetadataMap; |
| 148 | 157 |
| 149 /// A map with a token for a lists of JS expressions, one token for each | 158 /// A map with a token for a lists of JS expressions, one token for each |
| 150 /// output unit. Once finalized, the entries represent types including | 159 /// output unit. Once finalized, the entries represent types including |
| 151 /// function types and typedefs. | 160 /// function types and typedefs. |
| 152 Map<OutputUnit, _MetadataList> _typesTokens = | 161 Map<OutputUnit, _MetadataList> _typesTokens = |
| 153 new Map<OutputUnit, _MetadataList>(); | 162 new Map<OutputUnit, _MetadataList>(); |
| 154 | 163 |
| 155 jsAst.Expression getTypesForOutputUnit(OutputUnit outputUnit) { | 164 jsAst.Expression getTypesForOutputUnit(OutputUnit outputUnit) { |
| 156 return _typesTokens.putIfAbsent(outputUnit, () => new _MetadataList()); | 165 return _typesTokens.putIfAbsent(outputUnit, () => new _MetadataList()); |
| 157 } | 166 } |
| 158 | 167 |
| 159 /// A map used to canonicalize the entries of types. | 168 /// A map used to canonicalize the entries of types. |
| 160 Map<OutputUnit, Map<ResolutionDartType, _BoundMetadataEntry>> _typesMap = | 169 Map<OutputUnit, Map<ResolutionDartType, _BoundMetadataEntry>> _typesMap = |
| 161 <OutputUnit, Map<ResolutionDartType, _BoundMetadataEntry>>{}; | 170 <OutputUnit, Map<ResolutionDartType, _BoundMetadataEntry>>{}; |
| 162 | 171 |
| 163 MetadataCollector(this._compiler, this._emitter) { | 172 MetadataCollector( |
| 173 this._options, |
| 174 this.reporter, |
| 175 this._deferredLoadTask, |
| 176 this._emitter, |
| 177 this._constants, |
| 178 this._typeVariableCodegenAnalysis, |
| 179 this._mirrorsData, |
| 180 this._rtiEncoder) { |
| 164 _globalMetadataMap = new Map<String, _BoundMetadataEntry>(); | 181 _globalMetadataMap = new Map<String, _BoundMetadataEntry>(); |
| 165 } | 182 } |
| 166 | 183 |
| 167 JavaScriptBackend get _backend => _compiler.backend; | |
| 168 TypeVariableCodegenAnalysis get _typeVariableCodegenAnalysis => | |
| 169 _backend.typeVariableCodegenAnalysis; | |
| 170 DiagnosticReporter get reporter => _compiler.reporter; | |
| 171 | |
| 172 jsAst.Fun buildLibraryMetadataFunction(LibraryElement element) { | 184 jsAst.Fun buildLibraryMetadataFunction(LibraryElement element) { |
| 173 if (!_backend.mirrorsData.mustRetainMetadata || | 185 if (!_mirrorsData.mustRetainMetadata || |
| 174 !_backend.mirrorsData.isLibraryReferencedFromMirrorSystem(element)) { | 186 !_mirrorsData.isLibraryReferencedFromMirrorSystem(element)) { |
| 175 return null; | 187 return null; |
| 176 } | 188 } |
| 177 return _buildMetadataFunction(element); | 189 return _buildMetadataFunction(element); |
| 178 } | 190 } |
| 179 | 191 |
| 180 jsAst.Fun buildClassMetadataFunction(ClassElement element) { | 192 jsAst.Fun buildClassMetadataFunction(ClassElement element) { |
| 181 if (!_backend.mirrorsData.mustRetainMetadata || | 193 if (!_mirrorsData.mustRetainMetadata || |
| 182 !_backend.mirrorsData.isClassReferencedFromMirrorSystem(element)) { | 194 !_mirrorsData.isClassReferencedFromMirrorSystem(element)) { |
| 183 return null; | 195 return null; |
| 184 } | 196 } |
| 185 return _buildMetadataFunction(element); | 197 return _buildMetadataFunction(element); |
| 186 } | 198 } |
| 187 | 199 |
| 188 bool _mustEmitMetadataForMember(MemberElement element) { | 200 bool _mustEmitMetadataForMember(MemberElement element) { |
| 189 return _backend.mirrorsData.mustRetainMetadata && | 201 return _mirrorsData.mustRetainMetadata && |
| 190 _backend.mirrorsData.isMemberReferencedFromMirrorSystem(element); | 202 _mirrorsData.isMemberReferencedFromMirrorSystem(element); |
| 191 } | 203 } |
| 192 | 204 |
| 193 jsAst.Fun buildFieldMetadataFunction(FieldElement element) { | 205 jsAst.Fun buildFieldMetadataFunction(FieldElement element) { |
| 194 if (!_mustEmitMetadataForMember(element)) return null; | 206 if (!_mustEmitMetadataForMember(element)) return null; |
| 195 return _buildMetadataFunction(element); | 207 return _buildMetadataFunction(element); |
| 196 } | 208 } |
| 197 | 209 |
| 198 /// The metadata function returns the metadata associated with | 210 /// The metadata function returns the metadata associated with |
| 199 /// [element] in generated code. The metadata needs to be wrapped | 211 /// [element] in generated code. The metadata needs to be wrapped |
| 200 /// in a function as it refers to constants that may not have been | 212 /// in a function as it refers to constants that may not have been |
| 201 /// constructed yet. For example, a class is allowed to be | 213 /// constructed yet. For example, a class is allowed to be |
| 202 /// annotated with itself. The metadata function is used by | 214 /// annotated with itself. The metadata function is used by |
| 203 /// mirrors_patch to implement DeclarationMirror.metadata. | 215 /// mirrors_patch to implement DeclarationMirror.metadata. |
| 204 jsAst.Fun _buildMetadataFunction(Element element) { | 216 jsAst.Fun _buildMetadataFunction(Element element) { |
| 205 return reporter.withCurrentElement(element, () { | 217 return reporter.withCurrentElement(element, () { |
| 206 List<jsAst.Expression> metadata = <jsAst.Expression>[]; | 218 List<jsAst.Expression> metadata = <jsAst.Expression>[]; |
| 207 for (MetadataAnnotation annotation in element.metadata) { | 219 for (MetadataAnnotation annotation in element.metadata) { |
| 208 ConstantValue constant = | 220 ConstantValue constant = |
| 209 _backend.constants.getConstantValueForMetadata(annotation); | 221 _constants.getConstantValueForMetadata(annotation); |
| 210 if (constant == null) { | 222 if (constant == null) { |
| 211 reporter.internalError(annotation, 'Annotation value is null.'); | 223 reporter.internalError(annotation, 'Annotation value is null.'); |
| 212 } else { | 224 } else { |
| 213 metadata.add(_emitter.constantReference(constant)); | 225 metadata.add(_emitter.constantReference(constant)); |
| 214 } | 226 } |
| 215 } | 227 } |
| 216 if (metadata.isEmpty) return null; | 228 if (metadata.isEmpty) return null; |
| 217 return js( | 229 return js( |
| 218 'function() { return # }', new jsAst.ArrayInitializer(metadata)); | 230 'function() { return # }', new jsAst.ArrayInitializer(metadata)); |
| 219 }); | 231 }); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 248 } | 260 } |
| 249 } | 261 } |
| 250 } | 262 } |
| 251 | 263 |
| 252 List<jsAst.DeferredNumber> defaultValues = <jsAst.DeferredNumber>[]; | 264 List<jsAst.DeferredNumber> defaultValues = <jsAst.DeferredNumber>[]; |
| 253 for (ParameterElement element in signature.optionalParameters) { | 265 for (ParameterElement element in signature.optionalParameters) { |
| 254 ParameterElement parameter = | 266 ParameterElement parameter = |
| 255 (targetParameterMap == null) ? element : targetParameterMap[element]; | 267 (targetParameterMap == null) ? element : targetParameterMap[element]; |
| 256 ConstantValue constant = (parameter == null) | 268 ConstantValue constant = (parameter == null) |
| 257 ? null | 269 ? null |
| 258 : _backend.constants.getConstantValue(parameter.constant); | 270 : _constants.getConstantValue(parameter.constant); |
| 259 jsAst.Expression expression = (constant == null) | 271 jsAst.Expression expression = (constant == null) |
| 260 ? new jsAst.LiteralNull() | 272 ? new jsAst.LiteralNull() |
| 261 : _emitter.constantReference(constant); | 273 : _emitter.constantReference(constant); |
| 262 defaultValues.add(_addGlobalMetadata(expression)); | 274 defaultValues.add(_addGlobalMetadata(expression)); |
| 263 } | 275 } |
| 264 return defaultValues; | 276 return defaultValues; |
| 265 } | 277 } |
| 266 | 278 |
| 267 Map<ParameterElement, ParameterElement> | 279 Map<ParameterElement, ParameterElement> |
| 268 mapRedirectingFactoryConstructorOptionalParameters( | 280 mapRedirectingFactoryConstructorOptionalParameters( |
| (...skipping 23 matching lines...) Expand all Loading... |
| 292 map[element] = target | 304 map[element] = target |
| 293 .orderedOptionalParameters[i - target.requiredParameterCount]; | 305 .orderedOptionalParameters[i - target.requiredParameterCount]; |
| 294 } | 306 } |
| 295 ++i; | 307 ++i; |
| 296 } | 308 } |
| 297 } | 309 } |
| 298 return map; | 310 return map; |
| 299 } | 311 } |
| 300 | 312 |
| 301 jsAst.Expression reifyMetadata(MetadataAnnotation annotation) { | 313 jsAst.Expression reifyMetadata(MetadataAnnotation annotation) { |
| 302 ConstantValue constant = | 314 ConstantValue constant = _constants.getConstantValueForMetadata(annotation); |
| 303 _backend.constants.getConstantValueForMetadata(annotation); | |
| 304 if (constant == null) { | 315 if (constant == null) { |
| 305 reporter.internalError(annotation, 'Annotation value is null.'); | 316 reporter.internalError(annotation, 'Annotation value is null.'); |
| 306 return null; | 317 return null; |
| 307 } | 318 } |
| 308 return _addGlobalMetadata(_emitter.constantReference(constant)); | 319 return _addGlobalMetadata(_emitter.constantReference(constant)); |
| 309 } | 320 } |
| 310 | 321 |
| 311 jsAst.Expression reifyType(ResolutionDartType type, | 322 jsAst.Expression reifyType(ResolutionDartType type, |
| 312 {ignoreTypeVariables: false}) { | 323 {ignoreTypeVariables: false}) { |
| 313 return reifyTypeForOutputUnit( | 324 return reifyTypeForOutputUnit(type, _deferredLoadTask.mainOutputUnit, |
| 314 type, _compiler.deferredLoadTask.mainOutputUnit, | |
| 315 ignoreTypeVariables: ignoreTypeVariables); | 325 ignoreTypeVariables: ignoreTypeVariables); |
| 316 } | 326 } |
| 317 | 327 |
| 318 jsAst.Expression reifyTypeForOutputUnit( | 328 jsAst.Expression reifyTypeForOutputUnit( |
| 319 ResolutionDartType type, OutputUnit outputUnit, | 329 ResolutionDartType type, OutputUnit outputUnit, |
| 320 {ignoreTypeVariables: false}) { | 330 {ignoreTypeVariables: false}) { |
| 321 return addTypeInOutputUnit(type, outputUnit, | 331 return addTypeInOutputUnit(type, outputUnit, |
| 322 ignoreTypeVariables: ignoreTypeVariables); | 332 ignoreTypeVariables: ignoreTypeVariables); |
| 323 } | 333 } |
| 324 | 334 |
| 325 jsAst.Expression reifyName(String name) { | 335 jsAst.Expression reifyName(String name) { |
| 326 return _addGlobalMetadata(js.string(name)); | 336 return _addGlobalMetadata(js.string(name)); |
| 327 } | 337 } |
| 328 | 338 |
| 329 jsAst.Expression reifyExpression(jsAst.Expression expression) { | 339 jsAst.Expression reifyExpression(jsAst.Expression expression) { |
| 330 return _addGlobalMetadata(expression); | 340 return _addGlobalMetadata(expression); |
| 331 } | 341 } |
| 332 | 342 |
| 333 Placeholder getMetadataPlaceholder([debug]) { | 343 Placeholder getMetadataPlaceholder([debug]) { |
| 334 return new _ForwardingMetadataEntry(debug); | 344 return new _ForwardingMetadataEntry(debug); |
| 335 } | 345 } |
| 336 | 346 |
| 337 _MetadataEntry _addGlobalMetadata(jsAst.Node node) { | 347 _MetadataEntry _addGlobalMetadata(jsAst.Node node) { |
| 338 String nameToKey(jsAst.Name name) => "${name.key}"; | 348 String nameToKey(jsAst.Name name) => "${name.key}"; |
| 339 String printed = | 349 String printed = |
| 340 jsAst.prettyPrint(node, _compiler, renamerForNames: nameToKey); | 350 jsAst.prettyPrint(node, _options, renamerForNames: nameToKey); |
| 341 return _globalMetadataMap.putIfAbsent(printed, () { | 351 return _globalMetadataMap.putIfAbsent(printed, () { |
| 342 return new _BoundMetadataEntry(node); | 352 return new _BoundMetadataEntry(node); |
| 343 }); | 353 }); |
| 344 } | 354 } |
| 345 | 355 |
| 346 jsAst.Expression _computeTypeRepresentation(ResolutionDartType type, | 356 jsAst.Expression _computeTypeRepresentation(ResolutionDartType type, |
| 347 {ignoreTypeVariables: false}) { | 357 {ignoreTypeVariables: false}) { |
| 348 jsAst.Expression representation = | 358 jsAst.Expression representation = |
| 349 _backend.rtiEncoder.getTypeRepresentation(type, (variable) { | 359 _rtiEncoder.getTypeRepresentation(_emitter, type, (variable) { |
| 350 if (ignoreTypeVariables) return new jsAst.LiteralNull(); | 360 if (ignoreTypeVariables) return new jsAst.LiteralNull(); |
| 351 return _typeVariableCodegenAnalysis.reifyTypeVariable(variable.element); | 361 return _typeVariableCodegenAnalysis.reifyTypeVariable(variable.element); |
| 352 }, (ResolutionTypedefType typedef) { | 362 }, (ResolutionTypedefType typedef) { |
| 353 return _backend.mirrorsData | 363 return _mirrorsData.isTypedefAccessibleByReflection(typedef.element); |
| 354 .isTypedefAccessibleByReflection(typedef.element); | |
| 355 }); | 364 }); |
| 356 | 365 |
| 357 if (representation is jsAst.LiteralString) { | 366 if (representation is jsAst.LiteralString) { |
| 358 // We don't want the representation to be a string, since we use | 367 // We don't want the representation to be a string, since we use |
| 359 // strings as indicator for non-initialized types in the lazy emitter. | 368 // strings as indicator for non-initialized types in the lazy emitter. |
| 360 reporter.internalError( | 369 reporter.internalError( |
| 361 NO_LOCATION_SPANNABLE, 'reified types should not be strings.'); | 370 NO_LOCATION_SPANNABLE, 'reified types should not be strings.'); |
| 362 } | 371 } |
| 363 | 372 |
| 364 return representation; | 373 return representation; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 if (token is _ForwardingMetadataEntry && !token.isBound) { | 463 if (token is _ForwardingMetadataEntry && !token.isBound) { |
| 455 _foundUnboundToken = true; | 464 _foundUnboundToken = true; |
| 456 } | 465 } |
| 457 } | 466 } |
| 458 | 467 |
| 459 bool findUnboundPlaceholders(jsAst.Node node) { | 468 bool findUnboundPlaceholders(jsAst.Node node) { |
| 460 node.accept(this); | 469 node.accept(this); |
| 461 return _foundUnboundToken; | 470 return _foundUnboundToken; |
| 462 } | 471 } |
| 463 } | 472 } |
| OLD | NEW |