| 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 |