| 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 /// Generate code using the cps-based IR pipeline. | 5 /// Generate code using the cps-based IR pipeline. |
| 6 library code_generator_task; | 6 library code_generator_task; |
| 7 | 7 |
| 8 import 'glue.dart'; | 8 import 'glue.dart'; |
| 9 import 'codegen.dart'; | 9 import 'codegen.dart'; |
| 10 import 'unsugar.dart'; | 10 import 'unsugar.dart'; |
| 11 | 11 |
| 12 import '../js_backend.dart'; | 12 import '../js_backend.dart'; |
| 13 | 13 |
| 14 import '../../common.dart'; | 14 import '../../common.dart'; |
| 15 import '../../common/codegen.dart' show | 15 import '../../common/codegen.dart' show CodegenWorkItem; |
| 16 CodegenWorkItem; | 16 import '../../common/tasks.dart' show CompilerTask, GenericTask; |
| 17 import '../../common/tasks.dart' show | 17 import '../../compiler.dart' show Compiler; |
| 18 CompilerTask, | |
| 19 GenericTask; | |
| 20 import '../../compiler.dart' show | |
| 21 Compiler; | |
| 22 import '../../constants/constant_system.dart'; | 18 import '../../constants/constant_system.dart'; |
| 23 import '../../cps_ir/cps_ir_builder_task.dart'; | 19 import '../../cps_ir/cps_ir_builder_task.dart'; |
| 24 import '../../cps_ir/cps_ir_nodes.dart' as cps; | 20 import '../../cps_ir/cps_ir_nodes.dart' as cps; |
| 25 import '../../cps_ir/cps_ir_nodes_sexpr.dart'; | 21 import '../../cps_ir/cps_ir_nodes_sexpr.dart'; |
| 26 import '../../cps_ir/cps_ir_integrity.dart'; | 22 import '../../cps_ir/cps_ir_integrity.dart'; |
| 27 import '../../cps_ir/optimizers.dart'; | 23 import '../../cps_ir/optimizers.dart'; |
| 28 import '../../cps_ir/optimizers.dart' as cps_opt; | 24 import '../../cps_ir/optimizers.dart' as cps_opt; |
| 29 import '../../cps_ir/type_mask_system.dart'; | 25 import '../../cps_ir/type_mask_system.dart'; |
| 30 import '../../cps_ir/finalize.dart' show Finalize; | 26 import '../../cps_ir/finalize.dart' show Finalize; |
| 31 import '../../diagnostics/invariant.dart' show | 27 import '../../diagnostics/invariant.dart' show DEBUG_MODE; |
| 32 DEBUG_MODE; | |
| 33 import '../../elements/elements.dart'; | 28 import '../../elements/elements.dart'; |
| 34 import '../../js/js.dart' as js; | 29 import '../../js/js.dart' as js; |
| 35 import '../../js_backend/codegen/codegen.dart'; | 30 import '../../js_backend/codegen/codegen.dart'; |
| 36 import '../../io/source_information.dart' show | 31 import '../../io/source_information.dart' show SourceInformationStrategy; |
| 37 SourceInformationStrategy; | |
| 38 import '../../tree_ir/tree_ir_builder.dart' as tree_builder; | 32 import '../../tree_ir/tree_ir_builder.dart' as tree_builder; |
| 39 import '../../tracer.dart'; | 33 import '../../tracer.dart'; |
| 40 import '../../ssa/ssa.dart' as ssa; | 34 import '../../ssa/ssa.dart' as ssa; |
| 41 import '../../tree_ir/optimization/optimization.dart'; | 35 import '../../tree_ir/optimization/optimization.dart'; |
| 42 import '../../tree_ir/optimization/optimization.dart' as tree_opt; | 36 import '../../tree_ir/optimization/optimization.dart' as tree_opt; |
| 43 import '../../tree_ir/tree_ir_integrity.dart'; | 37 import '../../tree_ir/tree_ir_integrity.dart'; |
| 44 import '../../tree_ir/tree_ir_nodes.dart' as tree_ir; | 38 import '../../tree_ir/tree_ir_nodes.dart' as tree_ir; |
| 45 import '../../types/types.dart' show | 39 import '../../types/types.dart' |
| 46 FlatTypeMask, | 40 show FlatTypeMask, ForwardingTypeMask, TypeMask, UnionTypeMask; |
| 47 ForwardingTypeMask, | |
| 48 TypeMask, | |
| 49 UnionTypeMask; | |
| 50 | 41 |
| 51 class CpsFunctionCompiler implements FunctionCompiler { | 42 class CpsFunctionCompiler implements FunctionCompiler { |
| 52 final ConstantSystem constantSystem; | 43 final ConstantSystem constantSystem; |
| 53 // TODO(karlklose): remove the compiler. | 44 // TODO(karlklose): remove the compiler. |
| 54 final Compiler compiler; | 45 final Compiler compiler; |
| 55 final Glue glue; | 46 final Glue glue; |
| 56 final SourceInformationStrategy sourceInformationFactory; | 47 final SourceInformationStrategy sourceInformationFactory; |
| 57 | 48 |
| 58 // TODO(karlklose,sigurdm): remove and update dart-doc of [compile]. | 49 // TODO(karlklose,sigurdm): remove and update dart-doc of [compile]. |
| 59 final FunctionCompiler fallbackCompiler; | 50 final FunctionCompiler fallbackCompiler; |
| 60 TypeMaskSystem typeSystem; | 51 TypeMaskSystem typeSystem; |
| 61 | 52 |
| 62 Tracer get tracer => compiler.tracer; | 53 Tracer get tracer => compiler.tracer; |
| 63 | 54 |
| 64 final IrBuilderTask cpsBuilderTask; | 55 final IrBuilderTask cpsBuilderTask; |
| 65 final GenericTask cpsOptimizationTask; | 56 final GenericTask cpsOptimizationTask; |
| 66 final GenericTask treeBuilderTask; | 57 final GenericTask treeBuilderTask; |
| 67 final GenericTask treeOptimizationTask; | 58 final GenericTask treeOptimizationTask; |
| 68 | 59 |
| 69 Inliner inliner; | 60 Inliner inliner; |
| 70 | 61 |
| 71 CpsFunctionCompiler(Compiler compiler, JavaScriptBackend backend, | 62 CpsFunctionCompiler(Compiler compiler, JavaScriptBackend backend, |
| 72 SourceInformationStrategy sourceInformationFactory) | 63 SourceInformationStrategy sourceInformationFactory) |
| 73 : fallbackCompiler = | 64 : fallbackCompiler = |
| 74 new ssa.SsaFunctionCompiler(backend, sourceInformationFactory), | 65 new ssa.SsaFunctionCompiler(backend, sourceInformationFactory), |
| 75 cpsBuilderTask = new IrBuilderTask(compiler, sourceInformationFactory), | 66 cpsBuilderTask = new IrBuilderTask(compiler, sourceInformationFactory), |
| 76 sourceInformationFactory = sourceInformationFactory, | 67 sourceInformationFactory = sourceInformationFactory, |
| 77 constantSystem = backend.constantSystem, | 68 constantSystem = backend.constantSystem, |
| 78 compiler = compiler, | 69 compiler = compiler, |
| 79 glue = new Glue(compiler), | 70 glue = new Glue(compiler), |
| 80 cpsOptimizationTask = new GenericTask('CPS optimization', compiler), | 71 cpsOptimizationTask = new GenericTask('CPS optimization', compiler), |
| 81 treeBuilderTask = new GenericTask('Tree builder', compiler), | 72 treeBuilderTask = new GenericTask('Tree builder', compiler), |
| 82 treeOptimizationTask = new GenericTask('Tree optimization', compiler) { | 73 treeOptimizationTask = new GenericTask('Tree optimization', compiler) { |
| 83 inliner = new Inliner(this); | 74 inliner = new Inliner(this); |
| 84 } | 75 } |
| 85 | 76 |
| 86 String get name => 'CPS Ir pipeline'; | 77 String get name => 'CPS Ir pipeline'; |
| 87 | 78 |
| 88 JavaScriptBackend get backend => compiler.backend; | 79 JavaScriptBackend get backend => compiler.backend; |
| 89 | 80 |
| 90 DiagnosticReporter get reporter => compiler.reporter; | 81 DiagnosticReporter get reporter => compiler.reporter; |
| 91 | 82 |
| 92 /// Generates JavaScript code for `work.element`. | 83 /// Generates JavaScript code for `work.element`. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 | 128 |
| 138 /// For debugging purposes, replace a call to [applyCpsPass] with a call | 129 /// For debugging purposes, replace a call to [applyCpsPass] with a call |
| 139 /// to [debugCpsPass] to check that this pass is idempotent. | 130 /// to [debugCpsPass] to check that this pass is idempotent. |
| 140 /// | 131 /// |
| 141 /// This runs [pass] followed by shrinking reductions, and then checks that | 132 /// This runs [pass] followed by shrinking reductions, and then checks that |
| 142 /// one more run of [pass] does not change the IR. The intermediate shrinking | 133 /// one more run of [pass] does not change the IR. The intermediate shrinking |
| 143 /// reductions pass is omitted if [pass] itself is shrinking reductions. | 134 /// reductions pass is omitted if [pass] itself is shrinking reductions. |
| 144 /// | 135 /// |
| 145 /// If [targetName] is given, functions whose name contains that substring | 136 /// If [targetName] is given, functions whose name contains that substring |
| 146 /// will be dumped out if the idempotency test fails. | 137 /// will be dumped out if the idempotency test fails. |
| 147 void debugCpsPass(cps_opt.Pass makePass(), | 138 void debugCpsPass(cps_opt.Pass makePass(), cps.FunctionDefinition cpsFunction, |
| 148 cps.FunctionDefinition cpsFunction, | 139 [String targetName]) { |
| 149 [String targetName]) { | |
| 150 String original = stringify(cpsFunction); | 140 String original = stringify(cpsFunction); |
| 151 cps_opt.Pass pass = makePass(); | 141 cps_opt.Pass pass = makePass(); |
| 152 pass.rewrite(cpsFunction); | 142 pass.rewrite(cpsFunction); |
| 153 assert(checkCpsIntegrity(cpsFunction, pass.passName)); | 143 assert(checkCpsIntegrity(cpsFunction, pass.passName)); |
| 154 if (pass is! ShrinkingReducer) { | 144 if (pass is! ShrinkingReducer) { |
| 155 new ShrinkingReducer().rewrite(cpsFunction); | 145 new ShrinkingReducer().rewrite(cpsFunction); |
| 156 } | 146 } |
| 157 String before = stringify(cpsFunction); | 147 String before = stringify(cpsFunction); |
| 158 makePass().rewrite(cpsFunction); | 148 makePass().rewrite(cpsFunction); |
| 159 String after = stringify(cpsFunction); | 149 String after = stringify(cpsFunction); |
| 160 if (before != after) { | 150 if (before != after) { |
| 161 print('SExpression changed for ${cpsFunction.element}'); | 151 print('SExpression changed for ${cpsFunction.element}'); |
| 162 if (targetName != null && '${cpsFunction.element}'.contains(targetName)) { | 152 if (targetName != null && '${cpsFunction.element}'.contains(targetName)) { |
| 163 print(original); | 153 print(original); |
| 164 print('\n-->\n'); | 154 print('\n-->\n'); |
| 165 print(before); | 155 print(before); |
| 166 print('\n-->\n'); | 156 print('\n-->\n'); |
| 167 print(after); | 157 print(after); |
| 168 compiler.outputProvider('original', 'dump')..add(original)..close(); | 158 compiler.outputProvider('original', 'dump') |
| 169 compiler.outputProvider('before', 'dump')..add(before)..close(); | 159 ..add(original) |
| 170 compiler.outputProvider('after', 'dump')..add(after)..close(); | 160 ..close(); |
| 161 compiler.outputProvider('before', 'dump') |
| 162 ..add(before) |
| 163 ..close(); |
| 164 compiler.outputProvider('after', 'dump') |
| 165 ..add(after) |
| 166 ..close(); |
| 171 } | 167 } |
| 172 } | 168 } |
| 173 traceGraph(pass.passName, cpsFunction); | 169 traceGraph(pass.passName, cpsFunction); |
| 174 dumpTypedIr(pass.passName, cpsFunction); | 170 dumpTypedIr(pass.passName, cpsFunction); |
| 175 } | 171 } |
| 176 | 172 |
| 177 void applyCpsPass(cps_opt.Pass pass, cps.FunctionDefinition cpsFunction) { | 173 void applyCpsPass(cps_opt.Pass pass, cps.FunctionDefinition cpsFunction) { |
| 178 cpsOptimizationTask.measureSubtask(pass.passName, () { | 174 cpsOptimizationTask.measureSubtask(pass.passName, () { |
| 179 pass.rewrite(cpsFunction); | 175 pass.rewrite(cpsFunction); |
| 180 }); | 176 }); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 } else if (type is ForwardingTypeMask) { | 219 } else if (type is ForwardingTypeMask) { |
| 224 return formatTypeMask(type.forwardTo); | 220 return formatTypeMask(type.forwardTo); |
| 225 } | 221 } |
| 226 throw 'unsupported: $type'; | 222 throw 'unsupported: $type'; |
| 227 } | 223 } |
| 228 | 224 |
| 229 void dumpTypedIr(String passName, cps.FunctionDefinition cpsFunction) { | 225 void dumpTypedIr(String passName, cps.FunctionDefinition cpsFunction) { |
| 230 if (PRINT_TYPED_IR_FILTER != null && | 226 if (PRINT_TYPED_IR_FILTER != null && |
| 231 PRINT_TYPED_IR_FILTER.matchAsPrefix(cpsFunction.element.name) != null) { | 227 PRINT_TYPED_IR_FILTER.matchAsPrefix(cpsFunction.element.name) != null) { |
| 232 String printType(nodeOrRef, String s) { | 228 String printType(nodeOrRef, String s) { |
| 233 cps.Node node = nodeOrRef is cps.Reference | 229 cps.Node node = |
| 234 ? nodeOrRef.definition | 230 nodeOrRef is cps.Reference ? nodeOrRef.definition : nodeOrRef; |
| 235 : nodeOrRef; | |
| 236 return node is cps.Variable && node.type != null | 231 return node is cps.Variable && node.type != null |
| 237 ? '$s:${formatTypeMask(node.type)}' | 232 ? '$s:${formatTypeMask(node.type)}' |
| 238 : s; | 233 : s; |
| 239 } | 234 } |
| 240 DEBUG_MODE = true; | 235 DEBUG_MODE = true; |
| 241 print(';;; ==== After $passName ===='); | 236 print(';;; ==== After $passName ===='); |
| 242 print(new SExpressionStringifier(printType).visit(cpsFunction)); | 237 print(new SExpressionStringifier(printType).visit(cpsFunction)); |
| 243 } | 238 } |
| 244 } | 239 } |
| 245 | 240 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 applyCpsPass(new UpdateRefinements(typeSystem), cpsFunction); | 282 applyCpsPass(new UpdateRefinements(typeSystem), cpsFunction); |
| 288 applyCpsPass(new ShrinkingReducer(), cpsFunction); | 283 applyCpsPass(new ShrinkingReducer(), cpsFunction); |
| 289 applyCpsPass(new OptimizeInterceptors(backend, typeSystem), cpsFunction); | 284 applyCpsPass(new OptimizeInterceptors(backend, typeSystem), cpsFunction); |
| 290 applyCpsPass(new BackwardNullCheckRemover(typeSystem), cpsFunction); | 285 applyCpsPass(new BackwardNullCheckRemover(typeSystem), cpsFunction); |
| 291 applyCpsPass(new ShrinkingReducer(), cpsFunction); | 286 applyCpsPass(new ShrinkingReducer(), cpsFunction); |
| 292 }); | 287 }); |
| 293 } | 288 } |
| 294 | 289 |
| 295 tree_ir.FunctionDefinition compileToTreeIr(cps.FunctionDefinition cpsNode) { | 290 tree_ir.FunctionDefinition compileToTreeIr(cps.FunctionDefinition cpsNode) { |
| 296 applyCpsPass(new Finalize(backend), cpsNode); | 291 applyCpsPass(new Finalize(backend), cpsNode); |
| 297 tree_builder.Builder builder = new tree_builder.Builder( | 292 tree_builder.Builder builder = |
| 298 reporter.internalError, glue); | 293 new tree_builder.Builder(reporter.internalError, glue); |
| 299 tree_ir.FunctionDefinition treeNode = | 294 tree_ir.FunctionDefinition treeNode = |
| 300 treeBuilderTask.measure(() => builder.buildFunction(cpsNode)); | 295 treeBuilderTask.measure(() => builder.buildFunction(cpsNode)); |
| 301 assert(treeNode != null); | 296 assert(treeNode != null); |
| 302 traceGraph('Tree builder', treeNode); | 297 traceGraph('Tree builder', treeNode); |
| 303 assert(checkTreeIntegrity(treeNode)); | 298 assert(checkTreeIntegrity(treeNode)); |
| 304 return treeNode; | 299 return treeNode; |
| 305 } | 300 } |
| 306 | 301 |
| 307 bool checkTreeIntegrity(tree_ir.FunctionDefinition node) { | 302 bool checkTreeIntegrity(tree_ir.FunctionDefinition node) { |
| 308 treeOptimizationTask.measureSubtask('Check integrity', () { | 303 treeOptimizationTask.measureSubtask('Check integrity', () { |
| 309 new CheckTreeIntegrity().check(node); | 304 new CheckTreeIntegrity().check(node); |
| 310 }); | 305 }); |
| 311 return true; // So this can be used from assert(). | 306 return true; // So this can be used from assert(). |
| 312 } | 307 } |
| 313 | 308 |
| 314 tree_ir.FunctionDefinition optimizeTreeIr(tree_ir.FunctionDefinition node) { | 309 tree_ir.FunctionDefinition optimizeTreeIr(tree_ir.FunctionDefinition node) { |
| 315 void applyTreePass(tree_opt.Pass pass) { | 310 void applyTreePass(tree_opt.Pass pass) { |
| 316 treeOptimizationTask.measureSubtask(pass.passName, () { | 311 treeOptimizationTask.measureSubtask(pass.passName, () { |
| 317 pass.rewrite(node); | 312 pass.rewrite(node); |
| 318 }); | 313 }); |
| 319 traceGraph(pass.passName, node); | 314 traceGraph(pass.passName, node); |
| 320 assert(checkTreeIntegrity(node)); | 315 assert(checkTreeIntegrity(node)); |
| 321 } | 316 } |
| 322 | 317 |
| 323 treeOptimizationTask.measure(() { | 318 treeOptimizationTask.measure(() { |
| 324 applyTreePass(new StatementRewriter()); | 319 applyTreePass(new StatementRewriter()); |
| 325 applyTreePass(new VariableMerger(minifying: | 320 applyTreePass( |
| 326 compiler.options.enableMinification)); | 321 new VariableMerger(minifying: compiler.options.enableMinification)); |
| 327 applyTreePass(new LoopRewriter()); | 322 applyTreePass(new LoopRewriter()); |
| 328 applyTreePass(new LogicalRewriter()); | 323 applyTreePass(new LogicalRewriter()); |
| 329 applyTreePass(new PullIntoInitializers()); | 324 applyTreePass(new PullIntoInitializers()); |
| 330 }); | 325 }); |
| 331 | 326 |
| 332 return node; | 327 return node; |
| 333 } | 328 } |
| 334 | 329 |
| 335 js.Fun compileToJavaScript(CodegenWorkItem work, | 330 js.Fun compileToJavaScript( |
| 336 tree_ir.FunctionDefinition definition) { | 331 CodegenWorkItem work, tree_ir.FunctionDefinition definition) { |
| 337 CodeGenerator codeGen = new CodeGenerator(glue, work.registry); | 332 CodeGenerator codeGen = new CodeGenerator(glue, work.registry); |
| 338 Element element = work.element; | 333 Element element = work.element; |
| 339 js.Fun code = codeGen.buildFunction(definition); | 334 js.Fun code = codeGen.buildFunction(definition); |
| 340 if (element is FunctionElement && element.asyncMarker != AsyncMarker.SYNC) { | 335 if (element is FunctionElement && element.asyncMarker != AsyncMarker.SYNC) { |
| 341 code = backend.rewriteAsync(element, code); | 336 code = backend.rewriteAsync(element, code); |
| 342 work.registry.registerAsyncMarker(element); | 337 work.registry.registerAsyncMarker(element); |
| 343 } | 338 } |
| 344 return attachPosition(code, element); | 339 return attachPosition(code, element); |
| 345 } | 340 } |
| 346 | 341 |
| 347 Iterable<CompilerTask> get tasks { | 342 Iterable<CompilerTask> get tasks { |
| 348 return <CompilerTask>[ | 343 return <CompilerTask>[ |
| 349 cpsBuilderTask, | 344 cpsBuilderTask, |
| 350 cpsOptimizationTask, | 345 cpsOptimizationTask, |
| 351 treeBuilderTask, | 346 treeBuilderTask, |
| 352 treeOptimizationTask] | 347 treeOptimizationTask |
| 353 ..addAll(fallbackCompiler.tasks); | 348 ]..addAll(fallbackCompiler.tasks); |
| 354 } | 349 } |
| 355 | 350 |
| 356 js.Node attachPosition(js.Node node, AstElement element) { | 351 js.Node attachPosition(js.Node node, AstElement element) { |
| 357 return node.withSourceInformation( | 352 return node.withSourceInformation(sourceInformationFactory |
| 358 sourceInformationFactory.createBuilderForContext(element) | 353 .createBuilderForContext(element) |
| 359 .buildDeclaration(element)); | 354 .buildDeclaration(element)); |
| 360 } | 355 } |
| 361 } | 356 } |
| OLD | NEW |