OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 js_backend; | 5 part of js_backend; |
6 | 6 |
7 /// [ConstantCompilerTask] for compilation of constants for the JavaScript | 7 /// [ConstantCompilerTask] for compilation of constants for the JavaScript |
8 /// backend. | 8 /// backend. |
9 /// | 9 /// |
10 /// Since this task needs to distinguish between frontend and backend constants | 10 /// Since this task needs to distinguish between frontend and backend constants |
11 /// the actual compilation of the constants is forwarded to a | 11 /// the actual compilation of the constants is forwarded to a |
12 /// [DartConstantCompiler] for the frontend interpretation of the constants and | 12 /// [DartConstantCompiler] for the frontend interpretation of the constants and |
13 /// to a [JavaScriptConstantCompiler] for the backend interpretation. | 13 /// to a [JavaScriptConstantCompiler] for the backend interpretation. |
14 class JavaScriptConstantTask extends ConstantCompilerTask { | 14 class JavaScriptConstantTask extends ConstantCompilerTask { |
15 DartConstantCompiler dartConstantCompiler; | 15 DartConstantCompiler dartConstantCompiler; |
16 JavaScriptConstantCompiler jsConstantCompiler; | 16 JavaScriptConstantCompiler jsConstantCompiler; |
17 | 17 |
18 JavaScriptConstantTask(Compiler compiler) | 18 JavaScriptConstantTask(Compiler compiler) |
19 : this.dartConstantCompiler = new DartConstantCompiler(compiler), | 19 : this.dartConstantCompiler = new DartConstantCompiler(compiler), |
20 this.jsConstantCompiler = | 20 this.jsConstantCompiler = new JavaScriptConstantCompiler(compiler), |
21 new JavaScriptConstantCompiler(compiler), | |
22 super(compiler); | 21 super(compiler); |
23 | 22 |
24 String get name => 'ConstantHandler'; | 23 String get name => 'ConstantHandler'; |
25 | 24 |
26 @override | 25 @override |
27 ConstantSystem get constantSystem => dartConstantCompiler.constantSystem; | 26 ConstantSystem get constantSystem => dartConstantCompiler.constantSystem; |
28 | 27 |
29 @override | 28 @override |
30 ConstantValue getConstantValue(ConstantExpression expression) { | 29 ConstantValue getConstantValue(ConstantExpression expression) { |
31 return dartConstantCompiler.getConstantValue(expression); | 30 return dartConstantCompiler.getConstantValue(expression); |
(...skipping 27 matching lines...) Expand all Loading... |
59 }); | 58 }); |
60 } | 59 } |
61 | 60 |
62 void compileVariable(VariableElement element) { | 61 void compileVariable(VariableElement element) { |
63 measure(() { | 62 measure(() { |
64 jsConstantCompiler.compileVariable(element); | 63 jsConstantCompiler.compileVariable(element); |
65 }); | 64 }); |
66 } | 65 } |
67 | 66 |
68 ConstantExpression compileNode(Node node, TreeElements elements, | 67 ConstantExpression compileNode(Node node, TreeElements elements, |
69 {bool enforceConst: true}) { | 68 {bool enforceConst: true}) { |
70 return measure(() { | 69 return measure(() { |
71 ConstantExpression result = | 70 ConstantExpression result = dartConstantCompiler |
72 dartConstantCompiler.compileNode(node, elements, | 71 .compileNode(node, elements, enforceConst: enforceConst); |
73 enforceConst: enforceConst); | |
74 jsConstantCompiler.compileNode(node, elements, | 72 jsConstantCompiler.compileNode(node, elements, |
75 enforceConst: enforceConst); | 73 enforceConst: enforceConst); |
76 return result; | 74 return result; |
77 }); | 75 }); |
78 } | 76 } |
79 | 77 |
80 ConstantExpression compileMetadata(MetadataAnnotation metadata, | 78 ConstantExpression compileMetadata( |
81 Node node, | 79 MetadataAnnotation metadata, Node node, TreeElements elements) { |
82 TreeElements elements) { | |
83 return measure(() { | 80 return measure(() { |
84 ConstantExpression constant = | 81 ConstantExpression constant = |
85 dartConstantCompiler.compileMetadata(metadata, node, elements); | 82 dartConstantCompiler.compileMetadata(metadata, node, elements); |
86 jsConstantCompiler.compileMetadata(metadata, node, elements); | 83 jsConstantCompiler.compileMetadata(metadata, node, elements); |
87 return constant; | 84 return constant; |
88 }); | 85 }); |
89 } | 86 } |
90 | 87 |
91 // TODO(johnniwinther): Remove this when values are computed from the | 88 // TODO(johnniwinther): Remove this when values are computed from the |
92 // expressions. | 89 // expressions. |
93 @override | 90 @override |
94 void copyConstantValues(JavaScriptConstantTask task) { | 91 void copyConstantValues(JavaScriptConstantTask task) { |
95 jsConstantCompiler.constantValueMap.addAll( | 92 jsConstantCompiler.constantValueMap |
96 task.jsConstantCompiler.constantValueMap); | 93 .addAll(task.jsConstantCompiler.constantValueMap); |
97 dartConstantCompiler.constantValueMap.addAll( | 94 dartConstantCompiler.constantValueMap |
98 task.dartConstantCompiler.constantValueMap); | 95 .addAll(task.dartConstantCompiler.constantValueMap); |
99 } | 96 } |
100 } | 97 } |
101 | 98 |
102 /** | 99 /** |
103 * The [JavaScriptConstantCompiler] is used to keep track of compile-time | 100 * The [JavaScriptConstantCompiler] is used to keep track of compile-time |
104 * constants, initializations of global and static fields, and default values of | 101 * constants, initializations of global and static fields, and default values of |
105 * optional parameters for the JavaScript interpretation of constants. | 102 * optional parameters for the JavaScript interpretation of constants. |
106 */ | 103 */ |
107 class JavaScriptConstantCompiler extends ConstantCompilerBase | 104 class JavaScriptConstantCompiler extends ConstantCompilerBase |
108 implements BackendConstantEnvironment { | 105 implements BackendConstantEnvironment { |
109 | |
110 /** Set of all registered compiled constants. */ | 106 /** Set of all registered compiled constants. */ |
111 final Set<ConstantValue> compiledConstants = new Set<ConstantValue>(); | 107 final Set<ConstantValue> compiledConstants = new Set<ConstantValue>(); |
112 | 108 |
113 // TODO(johnniwinther): Move this to the backend constant handler. | 109 // TODO(johnniwinther): Move this to the backend constant handler. |
114 /** Caches the statics where the initial value cannot be eagerly compiled. */ | 110 /** Caches the statics where the initial value cannot be eagerly compiled. */ |
115 final Set<VariableElement> lazyStatics = new Set<VariableElement>(); | 111 final Set<VariableElement> lazyStatics = new Set<VariableElement>(); |
116 | 112 |
117 // Constants computed for constant expressions. | 113 // Constants computed for constant expressions. |
118 final Map<Node, ConstantExpression> nodeConstantMap = | 114 final Map<Node, ConstantExpression> nodeConstantMap = |
119 new Map<Node, ConstantExpression>(); | 115 new Map<Node, ConstantExpression>(); |
120 | 116 |
121 // Constants computed for metadata. | 117 // Constants computed for metadata. |
122 final Map<MetadataAnnotation, ConstantExpression> metadataConstantMap = | 118 final Map<MetadataAnnotation, ConstantExpression> metadataConstantMap = |
123 new Map<MetadataAnnotation, ConstantExpression>(); | 119 new Map<MetadataAnnotation, ConstantExpression>(); |
124 | 120 |
125 JavaScriptConstantCompiler(Compiler compiler) | 121 JavaScriptConstantCompiler(Compiler compiler) |
126 : super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM); | 122 : super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM); |
127 | 123 |
128 ConstantExpression compileVariableWithDefinitions(VariableElement element, | 124 ConstantExpression compileVariableWithDefinitions( |
129 TreeElements definitions, | 125 VariableElement element, TreeElements definitions, |
130 {bool isConst: false, | 126 {bool isConst: false, bool checkType: true}) { |
131 bool checkType: true}) { | |
132 if (!isConst && lazyStatics.contains(element)) { | 127 if (!isConst && lazyStatics.contains(element)) { |
133 return null; | 128 return null; |
134 } | 129 } |
135 ConstantExpression value = super.compileVariableWithDefinitions( | 130 ConstantExpression value = super.compileVariableWithDefinitions( |
136 element, definitions, isConst: isConst, checkType: checkType); | 131 element, definitions, |
| 132 isConst: isConst, checkType: checkType); |
137 if (!isConst && value == null) { | 133 if (!isConst && value == null) { |
138 lazyStatics.add(element); | 134 lazyStatics.add(element); |
139 } | 135 } |
140 return value; | 136 return value; |
141 } | 137 } |
142 | 138 |
143 void addCompileTimeConstantForEmission(ConstantValue constant) { | 139 void addCompileTimeConstantForEmission(ConstantValue constant) { |
144 compiledConstants.add(constant); | 140 compiledConstants.add(constant); |
145 } | 141 } |
146 | 142 |
147 /** | 143 /** |
148 * Returns an [Iterable] of static non final fields that need to be | 144 * Returns an [Iterable] of static non final fields that need to be |
149 * initialized. The fields list must be evaluated in order since they might | 145 * initialized. The fields list must be evaluated in order since they might |
150 * depend on each other. | 146 * depend on each other. |
151 */ | 147 */ |
152 Iterable<VariableElement> getStaticNonFinalFieldsForEmission() { | 148 Iterable<VariableElement> getStaticNonFinalFieldsForEmission() { |
153 return initialVariableValues.keys.where((element) { | 149 return initialVariableValues.keys.where((element) { |
154 return element.kind == ElementKind.FIELD && | 150 return element.kind == ElementKind.FIELD && |
155 !element.isInstanceMember && | 151 !element.isInstanceMember && |
156 !element.modifiers.isFinal && | 152 !element.modifiers.isFinal && |
157 // The const fields are all either emitted elsewhere or inlined. | 153 // The const fields are all either emitted elsewhere or inlined. |
158 !element.modifiers.isConst; | 154 !element.modifiers.isConst; |
159 }); | 155 }); |
160 } | 156 } |
161 | 157 |
162 List<VariableElement> getLazilyInitializedFieldsForEmission() { | 158 List<VariableElement> getLazilyInitializedFieldsForEmission() { |
163 return new List<VariableElement>.from(lazyStatics); | 159 return new List<VariableElement>.from(lazyStatics); |
164 } | 160 } |
165 | 161 |
166 /** | 162 /** |
167 * Returns a list of constants topologically sorted so that dependencies | 163 * Returns a list of constants topologically sorted so that dependencies |
168 * appear before the dependent constant. [preSortCompare] is a comparator | 164 * appear before the dependent constant. [preSortCompare] is a comparator |
(...skipping 26 matching lines...) Expand all Loading... |
195 ConstantValue getInitialValueFor(VariableElement element) { | 191 ConstantValue getInitialValueFor(VariableElement element) { |
196 ConstantExpression initialValue = | 192 ConstantExpression initialValue = |
197 initialVariableValues[element.declaration]; | 193 initialVariableValues[element.declaration]; |
198 if (initialValue == null) { | 194 if (initialValue == null) { |
199 reporter.internalError(element, "No initial value for given element."); | 195 reporter.internalError(element, "No initial value for given element."); |
200 } | 196 } |
201 return getConstantValue(initialValue); | 197 return getConstantValue(initialValue); |
202 } | 198 } |
203 | 199 |
204 ConstantExpression compileNode(Node node, TreeElements elements, | 200 ConstantExpression compileNode(Node node, TreeElements elements, |
205 {bool enforceConst: true}) { | 201 {bool enforceConst: true}) { |
206 return compileNodeWithDefinitions(node, elements, isConst: enforceConst); | 202 return compileNodeWithDefinitions(node, elements, isConst: enforceConst); |
207 } | 203 } |
208 | 204 |
209 ConstantExpression compileNodeWithDefinitions(Node node, | 205 ConstantExpression compileNodeWithDefinitions( |
210 TreeElements definitions, | 206 Node node, TreeElements definitions, |
211 {bool isConst: true}) { | 207 {bool isConst: true}) { |
212 ConstantExpression constant = nodeConstantMap[node]; | 208 ConstantExpression constant = nodeConstantMap[node]; |
213 if (constant != null && getConstantValue(constant) != null) { | 209 if (constant != null && getConstantValue(constant) != null) { |
214 return constant; | 210 return constant; |
215 } | 211 } |
216 constant = | 212 constant = |
217 super.compileNodeWithDefinitions(node, definitions, isConst: isConst); | 213 super.compileNodeWithDefinitions(node, definitions, isConst: isConst); |
218 if (constant != null) { | 214 if (constant != null) { |
219 nodeConstantMap[node] = constant; | 215 nodeConstantMap[node] = constant; |
220 } | 216 } |
221 return constant; | 217 return constant; |
222 } | 218 } |
223 | 219 |
224 ConstantValue getConstantValueForNode(Node node, TreeElements definitions) { | 220 ConstantValue getConstantValueForNode(Node node, TreeElements definitions) { |
225 return getConstantValue(getConstantForNode(node, definitions)); | 221 return getConstantValue(getConstantForNode(node, definitions)); |
226 } | 222 } |
227 | 223 |
228 ConstantExpression getConstantForNode(Node node, TreeElements definitions) { | 224 ConstantExpression getConstantForNode(Node node, TreeElements definitions) { |
229 ConstantExpression constant = nodeConstantMap[node]; | 225 ConstantExpression constant = nodeConstantMap[node]; |
230 if (constant != null) { | 226 if (constant != null) { |
231 return constant; | 227 return constant; |
232 } | 228 } |
233 return definitions.getConstant(node); | 229 return definitions.getConstant(node); |
234 } | 230 } |
235 | 231 |
236 ConstantValue getConstantValueForMetadata(MetadataAnnotation metadata) { | 232 ConstantValue getConstantValueForMetadata(MetadataAnnotation metadata) { |
237 return getConstantValue(metadataConstantMap[metadata]); | 233 return getConstantValue(metadataConstantMap[metadata]); |
238 } | 234 } |
239 | 235 |
240 ConstantExpression compileMetadata( | 236 ConstantExpression compileMetadata( |
241 MetadataAnnotation metadata, | 237 MetadataAnnotation metadata, Node node, TreeElements elements) { |
242 Node node, | |
243 TreeElements elements) { | |
244 ConstantExpression constant = | 238 ConstantExpression constant = |
245 super.compileMetadata(metadata, node, elements); | 239 super.compileMetadata(metadata, node, elements); |
246 metadataConstantMap[metadata] = constant; | 240 metadataConstantMap[metadata] = constant; |
247 return constant; | 241 return constant; |
248 } | 242 } |
249 | 243 |
250 void forgetElement(Element element) { | 244 void forgetElement(Element element) { |
251 super.forgetElement(element); | 245 super.forgetElement(element); |
252 const ForgetConstantElementVisitor().visit(element, this); | 246 const ForgetConstantElementVisitor().visit(element, this); |
253 if (element is AstElement && element.hasNode) { | 247 if (element is AstElement && element.hasNode) { |
254 element.node.accept(new ForgetConstantNodeVisitor(this)); | 248 element.node.accept(new ForgetConstantNodeVisitor(this)); |
255 } | 249 } |
256 } | 250 } |
257 } | 251 } |
258 | 252 |
259 class ForgetConstantElementVisitor | 253 class ForgetConstantElementVisitor |
260 extends BaseElementVisitor<dynamic, JavaScriptConstantCompiler> { | 254 extends BaseElementVisitor<dynamic, JavaScriptConstantCompiler> { |
261 const ForgetConstantElementVisitor(); | 255 const ForgetConstantElementVisitor(); |
262 | 256 |
263 void visitElement(Element e, JavaScriptConstantCompiler constants) { | 257 void visitElement(Element e, JavaScriptConstantCompiler constants) { |
264 for (MetadataAnnotation data in e.implementation.metadata) { | 258 for (MetadataAnnotation data in e.implementation.metadata) { |
265 constants.metadataConstantMap.remove(data); | 259 constants.metadataConstantMap.remove(data); |
266 if (data.hasNode) { | 260 if (data.hasNode) { |
267 data.node.accept(new ForgetConstantNodeVisitor(constants)); | 261 data.node.accept(new ForgetConstantNodeVisitor(constants)); |
268 } | 262 } |
269 } | 263 } |
270 } | 264 } |
271 | 265 |
272 void visitFunctionElement(FunctionElement e, | 266 void visitFunctionElement( |
273 JavaScriptConstantCompiler constants) { | 267 FunctionElement e, JavaScriptConstantCompiler constants) { |
274 super.visitFunctionElement(e, constants); | 268 super.visitFunctionElement(e, constants); |
275 if (e.hasFunctionSignature) { | 269 if (e.hasFunctionSignature) { |
276 e.functionSignature.forEachParameter((p) => visit(p, constants)); | 270 e.functionSignature.forEachParameter((p) => visit(p, constants)); |
277 } | 271 } |
278 } | 272 } |
279 } | 273 } |
280 | 274 |
281 class ForgetConstantNodeVisitor extends Visitor { | 275 class ForgetConstantNodeVisitor extends Visitor { |
282 final JavaScriptConstantCompiler constants; | 276 final JavaScriptConstantCompiler constants; |
283 | 277 |
284 ForgetConstantNodeVisitor(this.constants); | 278 ForgetConstantNodeVisitor(this.constants); |
285 | 279 |
286 void visitNode(Node node) { | 280 void visitNode(Node node) { |
287 node.visitChildren(this); | 281 node.visitChildren(this); |
288 constants.nodeConstantMap.remove(node); | 282 constants.nodeConstantMap.remove(node); |
289 | 283 |
290 // TODO(ahe): This doesn't belong here. Rename this class and generalize. | 284 // TODO(ahe): This doesn't belong here. Rename this class and generalize. |
291 var closureClassMap = | 285 var closureClassMap = constants |
292 constants.compiler.closureToClassMapper.closureMappingCache | 286 .compiler.closureToClassMapper.closureMappingCache |
293 .remove(node); | 287 .remove(node); |
294 if (closureClassMap != null) { | 288 if (closureClassMap != null) { |
295 closureClassMap.removeMyselfFrom( | 289 closureClassMap |
296 constants.compiler.enqueuer.codegen.universe); | 290 .removeMyselfFrom(constants.compiler.enqueuer.codegen.universe); |
297 } | 291 } |
298 } | 292 } |
299 } | 293 } |
OLD | NEW |