| 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'; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 // TODO(karlklose): remove this fallback when we do not need it for | 77 // TODO(karlklose): remove this fallback when we do not need it for |
| 78 // testing anymore. | 78 // testing anymore. |
| 79 if (false) { | 79 if (false) { |
| 80 compiler.log('Using SSA compiler for platform element $element'); | 80 compiler.log('Using SSA compiler for platform element $element'); |
| 81 return fallbackCompiler.compile(work); | 81 return fallbackCompiler.compile(work); |
| 82 } | 82 } |
| 83 | 83 |
| 84 if (tracer != null) { | 84 if (tracer != null) { |
| 85 tracer.traceCompilation(element.name, null); | 85 tracer.traceCompilation(element.name, null); |
| 86 } | 86 } |
| 87 cps.FunctionDefinition cpsFunction = compileToCpsIR(element); | 87 cps.FunctionDefinition cpsFunction = compileToCpsIr(element); |
| 88 cpsFunction = optimizeCpsIR(cpsFunction); | 88 cpsFunction = optimizeCpsIr(cpsFunction); |
| 89 tree_ir.FunctionDefinition treeFunction = compileToTreeIR(cpsFunction); | 89 tree_ir.FunctionDefinition treeFunction = compileToTreeIr(cpsFunction); |
| 90 treeFunction = optimizeTreeIR(treeFunction); | 90 treeFunction = optimizeTreeIr(treeFunction); |
| 91 return compileToJavaScript(work, treeFunction); | 91 return compileToJavaScript(work, treeFunction); |
| 92 } on CodegenBailout catch (e) { | 92 } on CodegenBailout catch (e) { |
| 93 String message = "Unable to compile $element with the new compiler.\n" | 93 String message = "Unable to compile $element with the new compiler.\n" |
| 94 " Reason: ${e.message}"; | 94 " Reason: ${e.message}"; |
| 95 compiler.internalError(element, message); | 95 compiler.internalError(element, message); |
| 96 } | 96 } |
| 97 }); | 97 }); |
| 98 } | 98 } |
| 99 | 99 |
| 100 void giveUp(String reason) { | 100 void giveUp(String reason) { |
| 101 throw new CodegenBailout(null, reason); | 101 throw new CodegenBailout(null, reason); |
| 102 } | 102 } |
| 103 | 103 |
| 104 void traceGraph(String title, var irObject) { | 104 void traceGraph(String title, var irObject) { |
| 105 if (tracer != null) { | 105 if (tracer != null) { |
| 106 tracer.traceGraph(title, irObject); | 106 tracer.traceGraph(title, irObject); |
| 107 } | 107 } |
| 108 } | 108 } |
| 109 | 109 |
| 110 cps.FunctionDefinition compileToCpsIR(AstElement element) { | 110 void applyCpsPass(cps_opt.Pass pass, cps.FunctionDefinition cpsFunction) { |
| 111 cps.FunctionDefinition cpsNode = irBuilderTask.buildNode(element); | 111 pass.rewrite(cpsFunction); |
| 112 if (cpsNode == null) { | 112 traceGraph(pass.passName, cpsFunction); |
| 113 dumpTypedIr(pass.passName, cpsFunction); |
| 114 assert(checkCpsIntegrity(cpsFunction)); |
| 115 } |
| 116 |
| 117 cps.FunctionDefinition compileToCpsIr(AstElement element) { |
| 118 cps.FunctionDefinition cpsFunction = irBuilderTask.buildNode(element); |
| 119 if (cpsFunction == null) { |
| 113 if (irBuilderTask.bailoutMessage == null) { | 120 if (irBuilderTask.bailoutMessage == null) { |
| 114 giveUp('unable to build cps definition of $element'); | 121 giveUp('unable to build cps definition of $element'); |
| 115 } else { | 122 } else { |
| 116 giveUp(irBuilderTask.bailoutMessage); | 123 giveUp(irBuilderTask.bailoutMessage); |
| 117 } | 124 } |
| 118 } | 125 } |
| 119 traceGraph("IR Builder", cpsNode); | 126 traceGraph('IR Builder', cpsFunction); |
| 127 dumpTypedIr('IR Builder', cpsFunction); |
| 120 // Eliminating redundant phis before the unsugaring pass will make it | 128 // Eliminating redundant phis before the unsugaring pass will make it |
| 121 // insert fewer getInterceptor calls. | 129 // insert fewer getInterceptor calls. |
| 122 new RedundantPhiEliminator().rewrite(cpsNode); | 130 applyCpsPass(new RedundantPhiEliminator(), cpsFunction); |
| 123 traceGraph("Redundant phi elimination", cpsNode); | 131 applyCpsPass(new UnsugarVisitor(glue), cpsFunction); |
| 124 new UnsugarVisitor(glue).rewrite(cpsNode); | 132 return cpsFunction; |
| 125 traceGraph("Unsugaring", cpsNode); | |
| 126 return cpsNode; | |
| 127 } | 133 } |
| 128 | 134 |
| 129 static const Pattern PRINT_TYPED_IR_FILTER = null; | 135 static const Pattern PRINT_TYPED_IR_FILTER = null; |
| 130 | 136 |
| 131 String formatTypeMask(TypeMask type) { | 137 String formatTypeMask(TypeMask type) { |
| 132 if (type is UnionTypeMask) { | 138 if (type is UnionTypeMask) { |
| 133 return '[${type.disjointMasks.map(formatTypeMask).join(', ')}]'; | 139 return '[${type.disjointMasks.map(formatTypeMask).join(', ')}]'; |
| 134 } else if (type is FlatTypeMask) { | 140 } else if (type is FlatTypeMask) { |
| 135 if (type.isEmpty) { | 141 if (type.isEmpty) { |
| 136 return "null"; | 142 return "null"; |
| 137 } | 143 } |
| 138 String suffix = (type.isExact ? "" : "+") + (type.isNullable ? "?" : "!"); | 144 String suffix = (type.isExact ? "" : "+") + (type.isNullable ? "?" : "!"); |
| 139 return '${type.base.name}$suffix'; | 145 return '${type.base.name}$suffix'; |
| 140 } else if (type is ForwardingTypeMask) { | 146 } else if (type is ForwardingTypeMask) { |
| 141 return formatTypeMask(type.forwardTo); | 147 return formatTypeMask(type.forwardTo); |
| 142 } | 148 } |
| 143 throw 'unsupported: $type'; | 149 throw 'unsupported: $type'; |
| 144 } | 150 } |
| 145 | 151 |
| 146 void dumpTypedIR(cps.FunctionDefinition cpsNode, | 152 void dumpTypedIr(String passName, cps.FunctionDefinition cpsFunction) { |
| 147 TypePropagator typePropagator) { | |
| 148 if (PRINT_TYPED_IR_FILTER != null && | 153 if (PRINT_TYPED_IR_FILTER != null && |
| 149 PRINT_TYPED_IR_FILTER.matchAsPrefix(cpsNode.element.name) != null) { | 154 PRINT_TYPED_IR_FILTER.matchAsPrefix(cpsFunction.element.name) != null) { |
| 150 String printType(nodeOrRef, String s) { | 155 String printType(nodeOrRef, String s) { |
| 151 cps.Node node = nodeOrRef is cps.Reference | 156 cps.Node node = nodeOrRef is cps.Reference |
| 152 ? nodeOrRef.definition | 157 ? nodeOrRef.definition |
| 153 : nodeOrRef; | 158 : nodeOrRef; |
| 154 return node is cps.Variable && node.type != null | 159 return node is cps.Variable && node.type != null |
| 155 ? '$s:${formatTypeMask(node.type)}' | 160 ? '$s:${formatTypeMask(node.type)}' |
| 156 : s; | 161 : s; |
| 157 } | 162 } |
| 158 DEBUG_MODE = true; | 163 DEBUG_MODE = true; |
| 159 print(new SExpressionStringifier(printType).visit(cpsNode)); | 164 print(';;; ==== After $passName ===='); |
| 165 print(new SExpressionStringifier(printType).visit(cpsFunction)); |
| 160 } | 166 } |
| 161 } | 167 } |
| 162 | 168 |
| 163 static bool checkCpsIntegrity(cps.FunctionDefinition node) { | 169 static bool checkCpsIntegrity(cps.FunctionDefinition node) { |
| 164 new CheckCpsIntegrity().check(node); | 170 new CheckCpsIntegrity().check(node); |
| 165 return true; // So this can be used from assert(). | 171 return true; // So this can be used from assert(). |
| 166 } | 172 } |
| 167 | 173 |
| 168 cps.FunctionDefinition optimizeCpsIR(cps.FunctionDefinition cpsNode) { | 174 cps.FunctionDefinition optimizeCpsIr(cps.FunctionDefinition cpsFunction) { |
| 169 // Transformations on the CPS IR. | |
| 170 void applyCpsPass(cps_opt.Pass pass) { | |
| 171 pass.rewrite(cpsNode); | |
| 172 traceGraph(pass.passName, cpsNode); | |
| 173 assert(checkCpsIntegrity(cpsNode)); | |
| 174 } | |
| 175 | |
| 176 TypeMaskSystem typeSystem = new TypeMaskSystem(compiler); | 175 TypeMaskSystem typeSystem = new TypeMaskSystem(compiler); |
| 177 | 176 |
| 178 applyCpsPass(new RedundantJoinEliminator()); | 177 applyCpsPass(new RedundantJoinEliminator(), cpsFunction); |
| 179 applyCpsPass(new RedundantPhiEliminator()); | 178 applyCpsPass(new RedundantPhiEliminator(), cpsFunction); |
| 180 applyCpsPass(new InsertRefinements(typeSystem)); | 179 applyCpsPass(new InsertRefinements(typeSystem), cpsFunction); |
| 181 TypePropagator typePropagator = | 180 applyCpsPass(new TypePropagator(compiler, typeSystem, this), cpsFunction); |
| 182 new TypePropagator(compiler, typeSystem, this); | 181 applyCpsPass(new RemoveRefinements(), cpsFunction); |
| 183 applyCpsPass(typePropagator); | 182 applyCpsPass(new ShrinkingReducer(), cpsFunction); |
| 184 dumpTypedIR(cpsNode, typePropagator); | 183 applyCpsPass(new ScalarReplacer(compiler), cpsFunction); |
| 185 applyCpsPass(new RemoveRefinements()); | 184 applyCpsPass(new MutableVariableEliminator(), cpsFunction); |
| 186 applyCpsPass(new ShrinkingReducer()); | 185 applyCpsPass(new RedundantJoinEliminator(), cpsFunction); |
| 187 applyCpsPass(new ScalarReplacer(compiler)); | 186 applyCpsPass(new RedundantPhiEliminator(), cpsFunction); |
| 188 applyCpsPass(new MutableVariableEliminator()); | 187 applyCpsPass(new ShrinkingReducer(), cpsFunction); |
| 189 applyCpsPass(new RedundantJoinEliminator()); | 188 applyCpsPass(new LoopInvariantCodeMotion(), cpsFunction); |
| 190 applyCpsPass(new RedundantPhiEliminator()); | 189 applyCpsPass(new ShareInterceptors(), cpsFunction); |
| 191 applyCpsPass(new ShrinkingReducer()); | 190 applyCpsPass(new ShrinkingReducer(), cpsFunction); |
| 192 applyCpsPass(new LoopInvariantCodeMotion()); | |
| 193 applyCpsPass(new ShareInterceptors()); | |
| 194 applyCpsPass(new ShrinkingReducer()); | |
| 195 | 191 |
| 196 return cpsNode; | 192 return cpsFunction; |
| 197 } | 193 } |
| 198 | 194 |
| 199 tree_ir.FunctionDefinition compileToTreeIR(cps.FunctionDefinition cpsNode) { | 195 tree_ir.FunctionDefinition compileToTreeIr(cps.FunctionDefinition cpsNode) { |
| 200 tree_builder.Builder builder = new tree_builder.Builder( | 196 tree_builder.Builder builder = new tree_builder.Builder( |
| 201 compiler.internalError); | 197 compiler.internalError); |
| 202 tree_ir.FunctionDefinition treeNode = builder.buildFunction(cpsNode); | 198 tree_ir.FunctionDefinition treeNode = builder.buildFunction(cpsNode); |
| 203 assert(treeNode != null); | 199 assert(treeNode != null); |
| 204 traceGraph('Tree builder', treeNode); | 200 traceGraph('Tree builder', treeNode); |
| 205 assert(checkTreeIntegrity(treeNode)); | 201 assert(checkTreeIntegrity(treeNode)); |
| 206 return treeNode; | 202 return treeNode; |
| 207 } | 203 } |
| 208 | 204 |
| 209 static bool checkTreeIntegrity(tree_ir.FunctionDefinition node) { | 205 static bool checkTreeIntegrity(tree_ir.FunctionDefinition node) { |
| 210 new CheckTreeIntegrity().check(node); | 206 new CheckTreeIntegrity().check(node); |
| 211 return true; // So this can be used from assert(). | 207 return true; // So this can be used from assert(). |
| 212 } | 208 } |
| 213 | 209 |
| 214 tree_ir.FunctionDefinition optimizeTreeIR(tree_ir.FunctionDefinition node) { | 210 tree_ir.FunctionDefinition optimizeTreeIr(tree_ir.FunctionDefinition node) { |
| 215 void applyTreePass(tree_opt.Pass pass) { | 211 void applyTreePass(tree_opt.Pass pass) { |
| 216 pass.rewrite(node); | 212 pass.rewrite(node); |
| 217 traceGraph(pass.passName, node); | 213 traceGraph(pass.passName, node); |
| 218 assert(checkTreeIntegrity(node)); | 214 assert(checkTreeIntegrity(node)); |
| 219 } | 215 } |
| 220 | 216 |
| 221 applyTreePass(new StatementRewriter()); | 217 applyTreePass(new StatementRewriter()); |
| 222 applyTreePass(new VariableMerger()); | 218 applyTreePass(new VariableMerger()); |
| 223 applyTreePass(new LoopRewriter()); | 219 applyTreePass(new LoopRewriter()); |
| 224 applyTreePass(new LogicalRewriter()); | 220 applyTreePass(new LogicalRewriter()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 243 // TODO(sigurdm): Make a better list of tasks. | 239 // TODO(sigurdm): Make a better list of tasks. |
| 244 return <CompilerTask>[irBuilderTask]..addAll(fallbackCompiler.tasks); | 240 return <CompilerTask>[irBuilderTask]..addAll(fallbackCompiler.tasks); |
| 245 } | 241 } |
| 246 | 242 |
| 247 js.Node attachPosition(js.Node node, AstElement element) { | 243 js.Node attachPosition(js.Node node, AstElement element) { |
| 248 return node.withSourceInformation( | 244 return node.withSourceInformation( |
| 249 sourceInformationFactory.createBuilderForContext(element) | 245 sourceInformationFactory.createBuilderForContext(element) |
| 250 .buildDeclaration(element)); | 246 .buildDeclaration(element)); |
| 251 } | 247 } |
| 252 } | 248 } |
| OLD | NEW |