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 |