| 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 library dart_backend.tracer; | 5 library dart_backend.tracer; |
| 6 | 6 |
| 7 import 'dart:async' show EventSink; | 7 import 'dart:async' show EventSink; |
| 8 import '../tracer.dart'; | 8 import '../tracer.dart'; |
| 9 import 'dart_tree.dart'; | 9 import 'dart_tree.dart'; |
| 10 | 10 |
| 11 class Block { | 11 class Block { |
| 12 int index; | 12 int index; |
| 13 final List<Statement> statements = <Statement>[]; | 13 final Label label; |
| 14 /// Mixed list of [Statement] and [Block]. |
| 15 /// A [Block] represents a synthetic goto statement. |
| 16 final List statements = []; |
| 14 final List<Block> predecessors = <Block>[]; | 17 final List<Block> predecessors = <Block>[]; |
| 15 final List<Block> successors = <Block>[]; | 18 final List<Block> successors = <Block>[]; |
| 16 | 19 |
| 17 String get name => 'B$index'; | 20 String get name => 'B$index'; |
| 18 | 21 |
| 22 Block([this.label]); |
| 23 |
| 19 void addEdgeTo(Block successor) { | 24 void addEdgeTo(Block successor) { |
| 20 successors.add(successor); | 25 successors.add(successor); |
| 21 successor.predecessors.add(this); | 26 successor.predecessors.add(this); |
| 22 } | 27 } |
| 23 } | 28 } |
| 24 | 29 |
| 25 class BlockCollector extends Visitor { | 30 class BlockCollector extends Visitor { |
| 26 // Accumulate a list of blocks. The current block is the last block in | 31 // Accumulate a list of blocks. The current block is the last block in |
| 27 // the list. | 32 // the list. |
| 28 final List<Block> blocks = [new Block()..index = 0]; | 33 final List<Block> blocks = [new Block()..index = 0]; |
| 29 | 34 |
| 30 // Map tree [Label]s (break or continue targets) and [Statement]s | 35 // Map tree [Label]s (break or continue targets) and [Statement]s |
| 31 // (if targets) to blocks. | 36 // (if targets) to blocks. |
| 32 final Map<Label, Block> breakTargets = <Label, Block>{}; | 37 final Map<Label, Block> breakTargets = <Label, Block>{}; |
| 33 final Map<Label, Block> continueTargets = <Label, Block>{}; | 38 final Map<Label, Block> continueTargets = <Label, Block>{}; |
| 34 final Map<Statement, Block> ifTargets = <Statement, Block>{}; | 39 final Map<Statement, Block> ifTargets = <Statement, Block>{}; |
| 35 | 40 |
| 36 void _addStatement(Statement statement) { | 41 void _addStatement(Statement statement) { |
| 37 blocks.last.statements.add(statement); | 42 blocks.last.statements.add(statement); |
| 38 } | 43 } |
| 44 void _addGotoStatement(Block target) { |
| 45 blocks.last.statements.add(target); |
| 46 } |
| 39 | 47 |
| 40 void _addBlock(Block block) { | 48 void _addBlock(Block block) { |
| 41 block.index = blocks.length; | 49 block.index = blocks.length; |
| 42 blocks.add(block); | 50 blocks.add(block); |
| 43 } | 51 } |
| 44 | 52 |
| 45 void collect(FunctionDefinition function) { | 53 void collect(FunctionDefinition function) { |
| 46 visitStatement(function.body); | 54 visitStatement(function.body); |
| 47 } | 55 } |
| 48 | 56 |
| 49 visitVariable(Variable node) {} | 57 visitVariable(Variable node) {} |
| 50 visitInvokeStatic(InvokeStatic node) {} | 58 visitInvokeStatic(InvokeStatic node) {} |
| 51 visitInvokeMethod(InvokeMethod node) {} | 59 visitInvokeMethod(InvokeMethod node) {} |
| 52 visitInvokeConstructor(InvokeConstructor node) {} | 60 visitInvokeConstructor(InvokeConstructor node) {} |
| 53 visitConcatenateStrings(ConcatenateStrings node) {} | 61 visitConcatenateStrings(ConcatenateStrings node) {} |
| 54 visitLiteralList(LiteralList node) {} | 62 visitLiteralList(LiteralList node) {} |
| 55 visitLiteralMap(LiteralMap node) {} | 63 visitLiteralMap(LiteralMap node) {} |
| 56 visitInvokeConstConstructor(InvokeConstConstructor node) {} | 64 visitInvokeConstConstructor(InvokeConstConstructor node) {} |
| 57 visitConstant(Constant node) {} | 65 visitConstant(Constant node) {} |
| 58 visitConditional(Conditional node) {} | 66 visitConditional(Conditional node) {} |
| 59 visitLogicalOperator(LogicalOperator node) {} | 67 visitLogicalOperator(LogicalOperator node) {} |
| 60 visitNot(Not node) {} | 68 visitNot(Not node) {} |
| 61 | 69 |
| 62 visitLabeledStatement(LabeledStatement node) { | 70 visitLabeledStatement(LabeledStatement node) { |
| 63 Block target = new Block(); | 71 Block target = new Block(node.label); |
| 64 breakTargets[node.label] = target; | 72 breakTargets[node.label] = target; |
| 65 visitStatement(node.body); | 73 visitStatement(node.body); |
| 66 _addBlock(target); | 74 _addBlock(target); |
| 67 visitStatement(node.next); | 75 visitStatement(node.next); |
| 68 } | 76 } |
| 69 | 77 |
| 70 visitAssign(Assign node) { | 78 visitAssign(Assign node) { |
| 71 _addStatement(node); | 79 _addStatement(node); |
| 72 visitStatement(node.next); | 80 visitStatement(node.next); |
| 73 } | 81 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 93 ifTargets[node.thenStatement] = thenTarget; | 101 ifTargets[node.thenStatement] = thenTarget; |
| 94 ifTargets[node.elseStatement] = elseTarget; | 102 ifTargets[node.elseStatement] = elseTarget; |
| 95 blocks.last.addEdgeTo(thenTarget); | 103 blocks.last.addEdgeTo(thenTarget); |
| 96 blocks.last.addEdgeTo(elseTarget); | 104 blocks.last.addEdgeTo(elseTarget); |
| 97 _addBlock(thenTarget); | 105 _addBlock(thenTarget); |
| 98 visitStatement(node.thenStatement); | 106 visitStatement(node.thenStatement); |
| 99 _addBlock(elseTarget); | 107 _addBlock(elseTarget); |
| 100 visitStatement(node.elseStatement); | 108 visitStatement(node.elseStatement); |
| 101 } | 109 } |
| 102 | 110 |
| 103 visitWhile(While node) { | 111 visitWhileTrue(WhileTrue node) { |
| 104 Block continueTarget = new Block(); | 112 Block continueTarget = new Block(); |
| 113 _addGotoStatement(continueTarget); |
| 114 |
| 105 continueTargets[node.label] = continueTarget; | 115 continueTargets[node.label] = continueTarget; |
| 106 blocks.last.addEdgeTo(continueTarget); | 116 blocks.last.addEdgeTo(continueTarget); |
| 107 _addBlock(continueTarget); | 117 _addBlock(continueTarget); |
| 108 _addStatement(node); | 118 _addStatement(node); |
| 109 visitStatement(node.body); | 119 visitStatement(node.body); |
| 110 } | 120 } |
| 111 | 121 |
| 122 visitWhileCondition(WhileCondition node) { |
| 123 Block whileBlock = new Block(); |
| 124 _addGotoStatement(whileBlock); |
| 125 |
| 126 _addBlock(whileBlock); |
| 127 _addStatement(node); |
| 128 whileBlock.statements.add(node); |
| 129 blocks.last.addEdgeTo(whileBlock); |
| 130 |
| 131 Block bodyBlock = new Block(); |
| 132 Block nextBlock = new Block(); |
| 133 whileBlock.addEdgeTo(bodyBlock); |
| 134 whileBlock.addEdgeTo(nextBlock); |
| 135 |
| 136 continueTargets[node.label] = bodyBlock; |
| 137 _addBlock(bodyBlock); |
| 138 visitStatement(node.body); |
| 139 |
| 140 _addBlock(nextBlock); |
| 141 visitStatement(node.next); |
| 142 |
| 143 ifTargets[node.body] = bodyBlock; |
| 144 ifTargets[node.next] = nextBlock; |
| 145 } |
| 146 |
| 112 visitExpressionStatement(ExpressionStatement node) { | 147 visitExpressionStatement(ExpressionStatement node) { |
| 113 _addStatement(node); | 148 _addStatement(node); |
| 114 visitStatement(node.next); | 149 visitStatement(node.next); |
| 115 } | 150 } |
| 116 } | 151 } |
| 117 | 152 |
| 118 class TreeTracer extends TracerUtil with Visitor { | 153 class TreeTracer extends TracerUtil with StatementVisitor { |
| 119 final EventSink<String> output; | 154 final EventSink<String> output; |
| 120 | 155 |
| 121 TreeTracer(this.output); | 156 TreeTracer(this.output); |
| 122 | 157 |
| 123 Names names; | 158 Names names; |
| 124 BlockCollector collector; | 159 BlockCollector collector; |
| 125 int statementCounter; | 160 int statementCounter; |
| 126 | 161 |
| 127 void traceGraph(String name, FunctionDefinition function) { | 162 void traceGraph(String name, FunctionDefinition function) { |
| 128 names = new Names(); | 163 names = new Names(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 146 printProperty("successors", block.successors.map((b) => b.name)); | 181 printProperty("successors", block.successors.map((b) => b.name)); |
| 147 printEmptyProperty("xhandlers"); | 182 printEmptyProperty("xhandlers"); |
| 148 printEmptyProperty("flags"); | 183 printEmptyProperty("flags"); |
| 149 tag("states", () { | 184 tag("states", () { |
| 150 tag("locals", () { | 185 tag("locals", () { |
| 151 printProperty("size", 0); | 186 printProperty("size", 0); |
| 152 printProperty("method", "None"); | 187 printProperty("method", "None"); |
| 153 }); | 188 }); |
| 154 }); | 189 }); |
| 155 tag("HIR", () { | 190 tag("HIR", () { |
| 156 block.statements.forEach(visitStatement); | 191 if (block.label != null) { |
| 192 printStatement(null, |
| 193 "Label ${block.name}, useCount=${block.label.useCount}"); |
| 194 } |
| 195 block.statements.forEach(visitBlockMember); |
| 157 }); | 196 }); |
| 158 }); | 197 }); |
| 159 } | 198 } |
| 160 | 199 |
| 200 void visitBlockMember(member) { |
| 201 if (member is Block) { |
| 202 printStatement(null, "goto block B${member.name}"); |
| 203 } else { |
| 204 assert(member is Statement); |
| 205 visitStatement(member); |
| 206 } |
| 207 } |
| 208 |
| 161 void printStatement(String name, String contents) { | 209 void printStatement(String name, String contents) { |
| 162 int bci = 0; | 210 int bci = 0; |
| 163 int uses = 0; | 211 int uses = 0; |
| 164 if (name == null) { | 212 if (name == null) { |
| 165 name = 'x${statementCounter++}'; | 213 name = 'x${statementCounter++}'; |
| 166 } | 214 } |
| 167 addIndent(); | 215 addIndent(); |
| 168 add("$bci $uses $name $contents <|@\n"); | 216 add("$bci $uses $name $contents <|@\n"); |
| 169 } | 217 } |
| 170 | 218 |
| 171 visitVariable(Variable node) { | |
| 172 printStatement(null, "dead-use ${names.varName(node)}"); | |
| 173 } | |
| 174 | |
| 175 visitInvokeStatic(InvokeStatic node) { | |
| 176 printStatement(null, expr(node)); | |
| 177 } | |
| 178 | |
| 179 visitConstant(Constant node) { | |
| 180 printStatement(null, "dead-use ${node.value}"); | |
| 181 } | |
| 182 | |
| 183 visitLabeledStatement(LabeledStatement node) { | 219 visitLabeledStatement(LabeledStatement node) { |
| 184 // These do not get added to a block's list of statements. | 220 // These do not get added to a block's list of statements. |
| 185 } | 221 } |
| 186 | 222 |
| 187 visitAssign(Assign node) { | 223 visitAssign(Assign node) { |
| 188 String name = names.varName(node.variable); | 224 String name = names.varName(node.variable); |
| 189 String rhs = expr(node.definition); | 225 String rhs = expr(node.definition); |
| 190 printStatement(name, "let $name = $rhs"); | 226 printStatement(name, "let $name = $rhs"); |
| 191 } | 227 } |
| 192 | 228 |
| 193 visitInvokeMethod(InvokeMethod node) { | |
| 194 printStatement(null, expr(node)); | |
| 195 } | |
| 196 | |
| 197 visitInvokeConstructor(InvokeConstructor node) { | |
| 198 printStatement(null, expr(node)); | |
| 199 } | |
| 200 | |
| 201 visitConcatenateStrings(ConcatenateStrings node) { | |
| 202 printStatement(null, expr(node)); | |
| 203 } | |
| 204 | |
| 205 visitLiteralList(LiteralList node) { | |
| 206 printStatement(null, expr(node)); | |
| 207 } | |
| 208 | |
| 209 visitLiteralMap(LiteralMap node) { | |
| 210 printStatement(null, expr(node)); | |
| 211 } | |
| 212 | |
| 213 visitInvokeConstConstructor(InvokeConstConstructor node) { | |
| 214 printStatement(null, expr(node)); | |
| 215 } | |
| 216 | |
| 217 visitConditional(Conditional node) { | |
| 218 printStatement(null, expr(node)); | |
| 219 } | |
| 220 | |
| 221 visitLogicalOperator(LogicalOperator node) { | |
| 222 printStatement(null, expr(node)); | |
| 223 } | |
| 224 | |
| 225 visitNot(Not node) { | |
| 226 printStatement(null, expr(node)); | |
| 227 } | |
| 228 | |
| 229 visitReturn(Return node) { | 229 visitReturn(Return node) { |
| 230 printStatement(null, "return ${expr(node.value)}"); | 230 printStatement(null, "return ${expr(node.value)}"); |
| 231 } | 231 } |
| 232 | 232 |
| 233 visitBreak(Break node) { | 233 visitBreak(Break node) { |
| 234 printStatement(null, "break ${collector.breakTargets[node.target].name}"); | 234 printStatement(null, "break ${collector.breakTargets[node.target].name}"); |
| 235 } | 235 } |
| 236 | 236 |
| 237 visitContinue(Continue node) { | 237 visitContinue(Continue node) { |
| 238 printStatement(null, | 238 printStatement(null, |
| 239 "continue ${collector.breakTargets[node.target].name}"); | 239 "continue ${collector.breakTargets[node.target].name}"); |
| 240 } | 240 } |
| 241 | 241 |
| 242 visitIf(If node) { | 242 visitIf(If node) { |
| 243 String condition = expr(node.condition); | 243 String condition = expr(node.condition); |
| 244 String thenTarget = collector.ifTargets[node.thenStatement].name; | 244 String thenTarget = collector.ifTargets[node.thenStatement].name; |
| 245 String elseTarget = collector.ifTargets[node.elseStatement].name; | 245 String elseTarget = collector.ifTargets[node.elseStatement].name; |
| 246 printStatement(null, "if $condition then $thenTarget else $elseTarget"); | 246 printStatement(null, "if $condition then $thenTarget else $elseTarget"); |
| 247 } | 247 } |
| 248 | 248 |
| 249 visitWhile(While node) { | 249 visitWhileTrue(WhileTrue node) { |
| 250 printStatement(null, "while true do"); | 250 printStatement(null, "while true do"); |
| 251 } | 251 } |
| 252 | 252 |
| 253 visitWhileCondition(WhileCondition node) { |
| 254 String bodyTarget = collector.ifTargets[node.body].name; |
| 255 String nextTarget = collector.ifTargets[node.next].name; |
| 256 printStatement(null, "while ${expr(node.condition)}"); |
| 257 printStatement(null, "do $bodyTarget"); |
| 258 printStatement(null, "then $nextTarget" ); |
| 259 } |
| 260 |
| 253 visitExpressionStatement(ExpressionStatement node) { | 261 visitExpressionStatement(ExpressionStatement node) { |
| 254 visitExpression(node.expression); | 262 printStatement(null, expr(node.expression)); |
| 255 } | 263 } |
| 256 | 264 |
| 257 String expr(Expression e) { | 265 String expr(Expression e) { |
| 258 return e.accept(new SubexpressionVisitor(names)); | 266 return e.accept(new SubexpressionVisitor(names)); |
| 259 } | 267 } |
| 260 } | 268 } |
| 261 | 269 |
| 262 class SubexpressionVisitor extends Visitor<String, String> { | 270 class SubexpressionVisitor extends ExpressionVisitor<String> { |
| 263 Names names; | 271 Names names; |
| 264 | 272 |
| 265 SubexpressionVisitor(this.names); | 273 SubexpressionVisitor(this.names); |
| 266 | 274 |
| 267 String visitVariable(Variable node) { | 275 String visitVariable(Variable node) { |
| 268 return names.varName(node); | 276 return names.varName(node); |
| 269 } | 277 } |
| 270 | 278 |
| 271 String formatArguments(Invoke node) { | 279 String formatArguments(Invoke node) { |
| 272 List<String> args = new List<String>(); | 280 List<String> args = new List<String>(); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 } | 373 } |
| 366 | 374 |
| 367 String visitNot(Not node) { | 375 String visitNot(Not node) { |
| 368 String operand = visitExpression(node.operand); | 376 String operand = visitExpression(node.operand); |
| 369 if (usesInfixNotation(node.operand)) { | 377 if (usesInfixNotation(node.operand)) { |
| 370 operand = '($operand)'; | 378 operand = '($operand)'; |
| 371 } | 379 } |
| 372 return '!$operand'; | 380 return '!$operand'; |
| 373 } | 381 } |
| 374 | 382 |
| 375 // Note: There should not be statements in the context of expressions. | |
| 376 String visitStatement(Statement node) { | |
| 377 return "$node statement in expression context"; | |
| 378 } | |
| 379 | |
| 380 String visitLabeledStatement(LabeledStatement node) => visitStatement(node); | |
| 381 String visitAssign(Assign node) => visitStatement(node); | |
| 382 String visitReturn(Return node) => visitStatement(node); | |
| 383 String visitBreak(Break node) => visitStatement(node); | |
| 384 String visitContinue(Continue node) => visitStatement(node); | |
| 385 String visitIf(If node) => visitStatement(node); | |
| 386 String visitWhile(While node) => visitStatement(node); | |
| 387 String visitExpressionStatement(ExpressionStatement node) { | |
| 388 return visitStatement(node); | |
| 389 } | |
| 390 } | 383 } |
| 391 | 384 |
| 392 /** | 385 /** |
| 393 * Invents (and remembers) names for Variables that do not have an associated | 386 * Invents (and remembers) names for Variables that do not have an associated |
| 394 * identifier. | 387 * identifier. |
| 395 * | 388 * |
| 396 * In case a variable is named v0, v1, etc, it may be assigned a different | 389 * In case a variable is named v0, v1, etc, it may be assigned a different |
| 397 * name to avoid clashing with a previously synthesized variable name. | 390 * name to avoid clashing with a previously synthesized variable name. |
| 398 */ | 391 */ |
| 399 class Names { | 392 class Names { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 410 } | 403 } |
| 411 while (name == null || _usedNames.contains(name)) { | 404 while (name == null || _usedNames.contains(name)) { |
| 412 name = "v${_counter++}"; | 405 name = "v${_counter++}"; |
| 413 } | 406 } |
| 414 _names[v] = name; | 407 _names[v] = name; |
| 415 _usedNames.add(name); | 408 _usedNames.add(name); |
| 416 } | 409 } |
| 417 return name; | 410 return name; |
| 418 } | 411 } |
| 419 } | 412 } |
| OLD | NEW |