| 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 import '../../dart2jslib.dart'; | 13 import '../../dart2jslib.dart'; |
| 14 import '../../cps_ir/cps_ir_nodes.dart' as cps; | 14 import '../../cps_ir/cps_ir_nodes.dart' as cps; |
| 15 import '../../cps_ir/cps_ir_builder.dart'; | 15 import '../../cps_ir/cps_ir_builder.dart'; |
| 16 import '../../cps_ir/cps_ir_integrity.dart'; |
| 16 import '../../tree_ir/tree_ir_nodes.dart' as tree_ir; | 17 import '../../tree_ir/tree_ir_nodes.dart' as tree_ir; |
| 17 import '../../types/types.dart' show TypeMask, UnionTypeMask, FlatTypeMask, | 18 import '../../types/types.dart' show TypeMask, UnionTypeMask, FlatTypeMask, |
| 18 ForwardingTypeMask; | 19 ForwardingTypeMask; |
| 19 import '../../elements/elements.dart'; | 20 import '../../elements/elements.dart'; |
| 20 import '../../js/js.dart' as js; | 21 import '../../js/js.dart' as js; |
| 21 import '../../io/source_information.dart' show StartEndSourceInformation; | 22 import '../../io/source_information.dart' show StartEndSourceInformation; |
| 22 import '../../tree_ir/tree_ir_builder.dart' as tree_builder; | 23 import '../../tree_ir/tree_ir_builder.dart' as tree_builder; |
| 23 import '../../dart_backend/backend_ast_emitter.dart' as backend_ast_emitter; | 24 import '../../dart_backend/backend_ast_emitter.dart' as backend_ast_emitter; |
| 24 import '../../cps_ir/optimizers.dart'; | 25 import '../../cps_ir/optimizers.dart'; |
| 26 import '../../cps_ir/optimizers.dart' as cps_opt; |
| 25 import '../../tracer.dart'; | 27 import '../../tracer.dart'; |
| 26 import '../../js_backend/codegen/codegen.dart'; | 28 import '../../js_backend/codegen/codegen.dart'; |
| 27 import '../../ssa/ssa.dart' as ssa; | 29 import '../../ssa/ssa.dart' as ssa; |
| 28 import '../../tree_ir/optimization/optimization.dart'; | 30 import '../../tree_ir/optimization/optimization.dart'; |
| 31 import '../../tree_ir/optimization/optimization.dart' as tree_opt; |
| 32 import '../../tree_ir/tree_ir_integrity.dart'; |
| 29 import '../../cps_ir/cps_ir_nodes_sexpr.dart'; | 33 import '../../cps_ir/cps_ir_nodes_sexpr.dart'; |
| 30 import 'js_tree_builder.dart'; | 34 import 'js_tree_builder.dart'; |
| 31 | 35 |
| 32 class CpsFunctionCompiler implements FunctionCompiler { | 36 class CpsFunctionCompiler implements FunctionCompiler { |
| 33 final ConstantSystem constantSystem; | 37 final ConstantSystem constantSystem; |
| 34 final Compiler compiler; | 38 final Compiler compiler; |
| 35 final Glue glue; | 39 final Glue glue; |
| 36 | 40 |
| 37 TypeSystem types; | 41 TypeSystem types; |
| 38 | 42 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 return "null"; | 132 return "null"; |
| 129 } | 133 } |
| 130 String suffix = (type.isExact ? "" : "+") + (type.isNullable ? "?" : "!"); | 134 String suffix = (type.isExact ? "" : "+") + (type.isNullable ? "?" : "!"); |
| 131 return '${type.base.name}$suffix'; | 135 return '${type.base.name}$suffix'; |
| 132 } else if (type is ForwardingTypeMask) { | 136 } else if (type is ForwardingTypeMask) { |
| 133 return formatTypeMask(type.forwardTo); | 137 return formatTypeMask(type.forwardTo); |
| 134 } | 138 } |
| 135 throw 'unsupported: $type'; | 139 throw 'unsupported: $type'; |
| 136 } | 140 } |
| 137 | 141 |
| 142 void dumpTypedIR(cps.FunctionDefinition cpsNode, |
| 143 TypePropagator<TypeMask> typePropagator) { |
| 144 if (PRINT_TYPED_IR_FILTER != null && |
| 145 PRINT_TYPED_IR_FILTER.matchAsPrefix(cpsNode.element.name) != null) { |
| 146 String printType(nodeOrRef, String s) { |
| 147 cps.Node node = nodeOrRef is cps.Reference |
| 148 ? nodeOrRef.definition |
| 149 : nodeOrRef; |
| 150 var type = typePropagator.getType(node); |
| 151 return type == null ? s : "$s:${formatTypeMask(type.type)}"; |
| 152 } |
| 153 DEBUG_MODE = true; |
| 154 print(new SExpressionStringifier(printType).visit(cpsNode)); |
| 155 } |
| 156 } |
| 157 |
| 158 static bool checkCpsIntegrity(cps.ExecutableDefinition node) { |
| 159 new CheckCpsIntegrity().check(node); |
| 160 return true; // So this can be used from assert(). |
| 161 } |
| 162 |
| 138 cps.FunctionDefinition optimizeCpsIR(cps.FunctionDefinition cpsNode) { | 163 cps.FunctionDefinition optimizeCpsIR(cps.FunctionDefinition cpsNode) { |
| 139 // Transformations on the CPS IR. | 164 // Transformations on the CPS IR. |
| 165 void applyCpsPass(String name, |
| 166 cps_opt.Pass pass) { |
| 167 pass.rewrite(cpsNode); |
| 168 traceGraph(name, cpsNode); |
| 169 assert(checkCpsIntegrity(cpsNode)); |
| 170 } |
| 140 | 171 |
| 141 TypePropagator typePropagator = new TypePropagator<TypeMask>( | 172 TypePropagator typePropagator = new TypePropagator<TypeMask>( |
| 142 compiler.types, | 173 compiler.types, |
| 143 constantSystem, | 174 constantSystem, |
| 144 new TypeMaskSystem(compiler), | 175 new TypeMaskSystem(compiler), |
| 145 compiler.internalError); | 176 compiler.internalError); |
| 146 typePropagator.rewrite(cpsNode); | 177 applyCpsPass("Sparse constant propagation", typePropagator); |
| 147 traceGraph("Sparse constant propagation", cpsNode); | 178 dumpTypedIR(cpsNode, typePropagator); |
| 148 | 179 applyCpsPass("Redundant phi elimination", new RedundantPhiEliminator()); |
| 149 if (PRINT_TYPED_IR_FILTER != null && | 180 applyCpsPass("Shrinking reductions", new ShrinkingReducer()); |
| 150 PRINT_TYPED_IR_FILTER.matchAsPrefix(cpsNode.element.name) != null) { | |
| 151 String printType(cps.Node node, String s) { | |
| 152 var type = typePropagator.getType(node); | |
| 153 return type == null ? s : "$s:${formatTypeMask(type.type)}"; | |
| 154 } | |
| 155 DEBUG_MODE = true; | |
| 156 print(new SExpressionStringifier(printType).visit(cpsNode)); | |
| 157 } | |
| 158 | |
| 159 new RedundantPhiEliminator().rewrite(cpsNode); | |
| 160 traceGraph("Redundant phi elimination", cpsNode); | |
| 161 new ShrinkingReducer().rewrite(cpsNode); | |
| 162 traceGraph("Shrinking reductions", cpsNode); | |
| 163 | 181 |
| 164 // Do not rewrite the IR after variable allocation. Allocation | 182 // Do not rewrite the IR after variable allocation. Allocation |
| 165 // makes decisions based on an approximation of IR variable live | 183 // makes decisions based on an approximation of IR variable live |
| 166 // ranges that can be invalidated by transforming the IR. | 184 // ranges that can be invalidated by transforming the IR. |
| 167 new cps.RegisterAllocator().visit(cpsNode); | 185 new cps.RegisterAllocator().visit(cpsNode); |
| 168 return cpsNode; | 186 return cpsNode; |
| 169 } | 187 } |
| 170 | 188 |
| 171 tree_ir.FunctionDefinition compileToTreeIR(cps.FunctionDefinition cpsNode) { | 189 tree_ir.FunctionDefinition compileToTreeIR(cps.FunctionDefinition cpsNode) { |
| 172 tree_builder.Builder builder = new JsTreeBuilder( | 190 tree_builder.Builder builder = new JsTreeBuilder( |
| 173 compiler.internalError, compiler.identicalFunction, glue); | 191 compiler.internalError, compiler.identicalFunction, glue); |
| 174 tree_ir.FunctionDefinition treeNode = builder.buildFunction(cpsNode); | 192 tree_ir.FunctionDefinition treeNode = builder.buildFunction(cpsNode); |
| 175 assert(treeNode != null); | 193 assert(treeNode != null); |
| 176 traceGraph('Tree builder', treeNode); | 194 traceGraph('Tree builder', treeNode); |
| 195 assert(checkTreeIntegrity(treeNode)); |
| 177 return treeNode; | 196 return treeNode; |
| 178 } | 197 } |
| 179 | 198 |
| 180 tree_ir.FunctionDefinition optimizeTreeIR( | 199 static bool checkTreeIntegrity(tree_ir.ExecutableDefinition node) { |
| 181 tree_ir.FunctionDefinition treeNode) { | 200 new CheckTreeIntegrity().check(node); |
| 182 // Transformations on the Tree IR. | 201 return true; // So this can be used from assert(). |
| 183 new StatementRewriter().rewrite(treeNode); | 202 } |
| 184 traceGraph('Statement rewriter', treeNode); | 203 |
| 185 new CopyPropagator().rewrite(treeNode); | 204 tree_ir.FunctionDefinition optimizeTreeIR(tree_ir.FunctionDefinition node) { |
| 186 traceGraph('Copy propagation', treeNode); | 205 void applyTreePass(String name, tree_opt.Pass pass) { |
| 187 new LoopRewriter().rewrite(treeNode); | 206 pass.rewrite(node); |
| 188 traceGraph('Loop rewriter', treeNode); | 207 traceGraph(name, node); |
| 189 new LogicalRewriter().rewrite(treeNode); | 208 assert(checkTreeIntegrity(node)); |
| 190 traceGraph('Logical rewriter', treeNode); | 209 } |
| 191 new backend_ast_emitter.UnshadowParameters().unshadow(treeNode); | 210 |
| 192 traceGraph('Unshadow parameters', treeNode); | 211 applyTreePass('Statement rewriter', new StatementRewriter()); |
| 193 return treeNode; | 212 applyTreePass('Copy propagation', new CopyPropagator()); |
| 213 applyTreePass('Loop rewriter', new LoopRewriter()); |
| 214 applyTreePass('Logical rewriter', new LogicalRewriter()); |
| 215 |
| 216 return node; |
| 194 } | 217 } |
| 195 | 218 |
| 196 js.Fun compileToJavaScript(CodegenWorkItem work, | 219 js.Fun compileToJavaScript(CodegenWorkItem work, |
| 197 tree_ir.FunctionDefinition definition) { | 220 tree_ir.FunctionDefinition definition) { |
| 198 CodeGenerator codeGen = new CodeGenerator(glue, work.registry); | 221 CodeGenerator codeGen = new CodeGenerator(glue, work.registry); |
| 199 | 222 |
| 200 return attachPosition(codeGen.buildFunction(definition), work.element); | 223 return attachPosition(codeGen.buildFunction(definition), work.element); |
| 201 } | 224 } |
| 202 | 225 |
| 203 Iterable<CompilerTask> get tasks { | 226 Iterable<CompilerTask> get tasks { |
| 204 // TODO(sigurdm): Make a better list of tasks. | 227 // TODO(sigurdm): Make a better list of tasks. |
| 205 return <CompilerTask>[irBuilderTask]..addAll(fallbackCompiler.tasks); | 228 return <CompilerTask>[irBuilderTask]..addAll(fallbackCompiler.tasks); |
| 206 } | 229 } |
| 207 | 230 |
| 208 js.Node attachPosition(js.Node node, AstElement element) { | 231 js.Node attachPosition(js.Node node, AstElement element) { |
| 209 return node.withSourceInformation( | 232 return node.withSourceInformation( |
| 210 StartEndSourceInformation.computeSourceInformation(element)); | 233 StartEndSourceInformation.computeSourceInformation(element)); |
| 211 } | 234 } |
| 212 } | 235 } |
| OLD | NEW |