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 part of dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
6 | 6 |
7 class MetadataCollector { | 7 class MetadataCollector { |
8 final Compiler _compiler; | 8 final Compiler _compiler; |
9 final Emitter _emitter; | 9 final Emitter _emitter; |
10 | 10 |
11 /// A list of JS expressions that represent metadata, parameter names and | 11 /// A list of JS expressions that represent metadata, parameter names and |
12 /// type variable types. | 12 /// type variable types. |
13 final List<String> globalMetadata = <String>[]; | 13 final List<jsAst.Expression> globalMetadata = <jsAst.Expression>[]; |
14 | 14 |
15 /// A map used to canonicalize the entries of globalMetadata. | 15 /// A map used to canonicalize the entries of globalMetadata. |
16 final Map<String, int> _globalMetadataMap = <String, int>{}; | 16 final Map<String, int> _globalMetadataMap = <String, int>{}; |
17 | 17 |
18 /// A map with lists of JS expressions, one list for each output unit. The | 18 /// A map with lists of JS expressions, one list for each output unit. The |
19 /// entries represent types including function types and typedefs. | 19 /// entries represent types including function types and typedefs. |
20 final Map<OutputUnit, List<String>> types = <OutputUnit, List<String>>{}; | 20 final Map<OutputUnit, List<jsAst.Expression>> types = |
| 21 <OutputUnit, List<jsAst.Expression>>{}; |
21 | 22 |
22 /// A map used to canonicalize the entries of types. | 23 /// A map used to canonicalize the entries of types. |
23 final Map<OutputUnit, Map<String, int>> _typesMap = | 24 final Map<OutputUnit, Map<String, int>> _typesMap = |
24 <OutputUnit, Map<String, int>>{}; | 25 <OutputUnit, Map<String, int>>{}; |
25 | 26 |
26 MetadataCollector(this._compiler, this._emitter); | 27 MetadataCollector(this._compiler, this._emitter); |
27 | 28 |
28 JavaScriptBackend get _backend => _compiler.backend; | 29 JavaScriptBackend get _backend => _compiler.backend; |
29 TypeVariableHandler get _typeVariableHandler => _backend.typeVariableHandler; | 30 TypeVariableHandler get _typeVariableHandler => _backend.typeVariableHandler; |
30 | 31 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 }); | 64 }); |
64 } | 65 } |
65 | 66 |
66 List<int> reifyDefaultArguments(FunctionElement function) { | 67 List<int> reifyDefaultArguments(FunctionElement function) { |
67 FunctionSignature signature = function.functionSignature; | 68 FunctionSignature signature = function.functionSignature; |
68 if (signature.optionalParameterCount == 0) return const []; | 69 if (signature.optionalParameterCount == 0) return const []; |
69 List<int> defaultValues = <int>[]; | 70 List<int> defaultValues = <int>[]; |
70 for (ParameterElement element in signature.optionalParameters) { | 71 for (ParameterElement element in signature.optionalParameters) { |
71 ConstantExpression constant = | 72 ConstantExpression constant = |
72 _backend.constants.getConstantForVariable(element); | 73 _backend.constants.getConstantForVariable(element); |
73 String stringRepresentation = (constant == null) | 74 jsAst.Expression expression = (constant == null) |
74 ? "null" | 75 ? null |
75 : jsAst.prettyPrint( | 76 : _emitter.constantReference(constant.value); |
76 _emitter.constantReference(constant.value), _compiler).getText(); | 77 defaultValues.add(addGlobalMetadata(expression)); |
77 defaultValues.add(addGlobalMetadata(stringRepresentation)); | |
78 } | 78 } |
79 return defaultValues; | 79 return defaultValues; |
80 } | 80 } |
81 | 81 |
82 int reifyMetadata(MetadataAnnotation annotation) { | 82 int reifyMetadata(MetadataAnnotation annotation) { |
83 ConstantExpression constant = | 83 ConstantExpression constant = |
84 _backend.constants.getConstantForMetadata(annotation); | 84 _backend.constants.getConstantForMetadata(annotation); |
85 if (constant == null) { | 85 if (constant == null) { |
86 _compiler.internalError(annotation, 'Annotation value is null.'); | 86 _compiler.internalError(annotation, 'Annotation value is null.'); |
87 return -1; | 87 return -1; |
88 } | 88 } |
89 return addGlobalMetadata( | 89 return addGlobalMetadata(_emitter.constantReference(constant.value)); |
90 jsAst.prettyPrint( | |
91 _emitter.constantReference(constant.value), _compiler).getText()); | |
92 } | 90 } |
93 | 91 |
94 int reifyType(DartType type, {bool ignoreTypeVariables: false}) { | 92 int reifyType(DartType type, {bool ignoreTypeVariables: false}) { |
95 return reifyTypeForOutputUnit(type, | 93 return reifyTypeForOutputUnit(type, |
96 _compiler.deferredLoadTask.mainOutputUnit, | 94 _compiler.deferredLoadTask.mainOutputUnit, |
97 ignoreTypeVariables: ignoreTypeVariables); | 95 ignoreTypeVariables: ignoreTypeVariables); |
98 } | 96 } |
99 | 97 |
100 int reifyTypeForOutputUnit(DartType type, OutputUnit outputUnit, | 98 int reifyTypeForOutputUnit(DartType type, OutputUnit outputUnit, |
101 {bool ignoreTypeVariables: false}) { | 99 {bool ignoreTypeVariables: false}) { |
102 jsAst.Expression representation = | 100 jsAst.Expression representation = |
103 _backend.rti.getTypeRepresentation( | 101 _backend.rti.getTypeRepresentation( |
104 type, | 102 type, |
105 (variable) { | 103 (variable) { |
106 if (ignoreTypeVariables) return new jsAst.LiteralNull(); | 104 if (ignoreTypeVariables) return new jsAst.LiteralNull(); |
107 return js.number( | 105 return js.number( |
108 _typeVariableHandler.reifyTypeVariable( | 106 _typeVariableHandler.reifyTypeVariable( |
109 variable.element)); | 107 variable.element)); |
110 }, | 108 }, |
111 (TypedefType typedef) { | 109 (TypedefType typedef) { |
112 return _backend.isAccessibleByReflection(typedef.element); | 110 return _backend.isAccessibleByReflection(typedef.element); |
113 }); | 111 }); |
114 | 112 |
115 return addTypeInOutputUnit( | 113 return addTypeInOutputUnit(representation, outputUnit); |
116 jsAst.prettyPrint(representation, _compiler).getText(), outputUnit); | |
117 } | 114 } |
118 | 115 |
119 int reifyName(String name) { | 116 int reifyName(String name) { |
120 return addGlobalMetadata('"$name"'); | 117 return addGlobalMetadata(js('"$name"')); |
121 } | 118 } |
122 | 119 |
123 int addGlobalMetadata(String string) { | 120 int addGlobalMetadata(jsAst.Expression expression) { |
| 121 // TODO(sigmund): consider adding an effient way to compare expressions |
| 122 String string = jsAst.prettyPrint(expression, _compiler).getText(); |
124 return _globalMetadataMap.putIfAbsent(string, () { | 123 return _globalMetadataMap.putIfAbsent(string, () { |
125 globalMetadata.add(string); | 124 globalMetadata.add(expression); |
126 return globalMetadata.length - 1; | 125 return globalMetadata.length - 1; |
127 }); | 126 }); |
128 } | 127 } |
129 | 128 |
130 int addTypeInOutputUnit(String compiledType, OutputUnit outputUnit) { | 129 int addTypeInOutputUnit(jsAst.Expression type, OutputUnit outputUnit) { |
| 130 String string = jsAst.prettyPrint(type, _compiler).getText(); |
131 if (_typesMap[outputUnit] == null) { | 131 if (_typesMap[outputUnit] == null) { |
132 _typesMap[outputUnit] = <String, int>{}; | 132 _typesMap[outputUnit] = <String, int>{}; |
133 } | 133 } |
134 return _typesMap[outputUnit].putIfAbsent(compiledType, () { | 134 return _typesMap[outputUnit].putIfAbsent(string, () { |
135 | 135 |
136 if (types[outputUnit] == null) | 136 if (types[outputUnit] == null) |
137 types[outputUnit] = <String>[]; | 137 types[outputUnit] = <jsAst.Expression>[]; |
138 | 138 |
139 types[outputUnit].add(compiledType); | 139 types[outputUnit].add(type); |
140 return types[outputUnit].length - 1; | 140 return types[outputUnit].length - 1; |
141 }); | 141 }); |
142 } | 142 } |
143 | 143 |
144 List<int> computeMetadata(FunctionElement element) { | 144 List<int> computeMetadata(FunctionElement element) { |
145 return _compiler.withCurrentElement(element, () { | 145 return _compiler.withCurrentElement(element, () { |
146 if (!_mustEmitMetadataFor(element)) return const <int>[]; | 146 if (!_mustEmitMetadataFor(element)) return const <int>[]; |
147 List<int> metadata = <int>[]; | 147 List<int> metadata = <int>[]; |
148 Link link = element.metadata; | 148 Link link = element.metadata; |
149 // TODO(ahe): Why is metadata sometimes null? | 149 // TODO(ahe): Why is metadata sometimes null? |
150 if (link != null) { | 150 if (link != null) { |
151 for (; !link.isEmpty; link = link.tail) { | 151 for (; !link.isEmpty; link = link.tail) { |
152 metadata.add(reifyMetadata(link.head)); | 152 metadata.add(reifyMetadata(link.head)); |
153 } | 153 } |
154 } | 154 } |
155 return metadata; | 155 return metadata; |
156 }); | 156 }); |
157 } | 157 } |
158 } | 158 } |
OLD | NEW |