| 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 tree_ir_tracer; | 5 library tree_ir_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 'tree_ir_nodes.dart'; | 9 import 'tree_ir_nodes.dart'; |
| 10 import 'optimization/optimization.dart'; | 10 import 'optimization/optimization.dart'; |
| 11 | 11 |
| 12 class Block { | 12 class Block { |
| 13 Label label; | 13 Label label; |
| 14 int index; | 14 int index; |
| 15 /// Mixed list of [Statement] and [Block]. | 15 /// Mixed list of [Statement] and [Block]. |
| 16 /// A [Block] represents a synthetic goto statement. | 16 /// A [Block] represents a synthetic goto statement. |
| 17 final List statements = []; | 17 final List statements = []; |
| 18 final List<Block> predecessors = <Block>[]; | 18 final List<Block> predecessors = <Block>[]; |
| 19 final List<Block> successors = <Block>[]; | 19 final List<Block> successors = <Block>[]; |
| 20 | 20 |
| 21 /// The catch block associated with the immediately enclosing try block or |
| 22 /// `null` if not inside a try block. |
| 23 Block catcher; |
| 24 |
| 21 String get name => 'B$index'; | 25 String get name => 'B$index'; |
| 22 | 26 |
| 23 Block([this.label]); | 27 Block([this.label]); |
| 24 | 28 |
| 25 void addEdgeTo(Block successor) { | 29 void addEdgeTo(Block successor) { |
| 26 successors.add(successor); | 30 successors.add(successor); |
| 27 successor.predecessors.add(this); | 31 successor.predecessors.add(this); |
| 28 } | 32 } |
| 29 } | 33 } |
| 30 | 34 |
| 31 class BlockCollector extends StatementVisitor { | 35 class BlockCollector extends StatementVisitor { |
| 32 // Accumulate a list of blocks. The current block is the last block in | 36 // Accumulate a list of blocks. The current block is the last block in |
| 33 // the list. | 37 // the list. |
| 34 final List<Block> blocks = [new Block()..index = 0]; | 38 final List<Block> blocks = [new Block()..index = 0]; |
| 35 | 39 |
| 36 // Map tree [Label]s (break or continue targets) and [Statement]s | 40 // Map tree [Label]s (break or continue targets) and [Statement]s |
| 37 // (if targets) to blocks. | 41 // (if targets) to blocks. |
| 38 final Map<Label, Block> breakTargets = <Label, Block>{}; | 42 final Map<Label, Block> breakTargets = <Label, Block>{}; |
| 39 final Map<Label, Block> continueTargets = <Label, Block>{}; | 43 final Map<Label, Block> continueTargets = <Label, Block>{}; |
| 40 final Map<Statement, Block> ifTargets = <Statement, Block>{}; | 44 final Map<Statement, Block> substatements = <Statement, Block>{}; |
| 45 |
| 46 Block catcher; |
| 41 | 47 |
| 42 void _addStatement(Statement statement) { | 48 void _addStatement(Statement statement) { |
| 43 blocks.last.statements.add(statement); | 49 blocks.last.statements.add(statement); |
| 44 } | 50 } |
| 45 void _addGotoStatement(Block target) { | 51 void _addGotoStatement(Block target) { |
| 46 blocks.last.statements.add(target); | 52 blocks.last.statements.add(target); |
| 47 } | 53 } |
| 48 | 54 |
| 49 void _addBlock(Block block) { | 55 void _addBlock(Block block) { |
| 50 block.index = blocks.length; | 56 block.index = blocks.length; |
| 57 block.catcher = catcher; |
| 51 blocks.add(block); | 58 blocks.add(block); |
| 52 } | 59 } |
| 53 | 60 |
| 54 void collect(ExecutableDefinition node) { | 61 void collect(ExecutableDefinition node) { |
| 55 if (node.body != null) { | 62 if (node.body != null) { |
| 56 if (node is ConstructorDefinition) { | 63 if (node is ConstructorDefinition) { |
| 57 for (Initializer initializer in node.initializers) { | 64 for (Initializer initializer in node.initializers) { |
| 58 if (initializer is FieldInitializer) { | 65 if (initializer is FieldInitializer) { |
| 59 visitStatement(initializer.body); | 66 visitStatement(initializer.body); |
| 60 } | 67 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 88 | 95 |
| 89 visitContinue(Continue node) { | 96 visitContinue(Continue node) { |
| 90 _addStatement(node); | 97 _addStatement(node); |
| 91 blocks.last.addEdgeTo(continueTargets[node.target]); | 98 blocks.last.addEdgeTo(continueTargets[node.target]); |
| 92 } | 99 } |
| 93 | 100 |
| 94 visitIf(If node) { | 101 visitIf(If node) { |
| 95 _addStatement(node); | 102 _addStatement(node); |
| 96 Block thenTarget = new Block(); | 103 Block thenTarget = new Block(); |
| 97 Block elseTarget = new Block(); | 104 Block elseTarget = new Block(); |
| 98 ifTargets[node.thenStatement] = thenTarget; | 105 substatements[node.thenStatement] = thenTarget; |
| 99 ifTargets[node.elseStatement] = elseTarget; | 106 substatements[node.elseStatement] = elseTarget; |
| 100 blocks.last.addEdgeTo(thenTarget); | 107 blocks.last.addEdgeTo(thenTarget); |
| 101 blocks.last.addEdgeTo(elseTarget); | 108 blocks.last.addEdgeTo(elseTarget); |
| 102 _addBlock(thenTarget); | 109 _addBlock(thenTarget); |
| 103 visitStatement(node.thenStatement); | 110 visitStatement(node.thenStatement); |
| 104 _addBlock(elseTarget); | 111 _addBlock(elseTarget); |
| 105 visitStatement(node.elseStatement); | 112 visitStatement(node.elseStatement); |
| 106 } | 113 } |
| 107 | 114 |
| 108 visitWhileTrue(WhileTrue node) { | 115 visitWhileTrue(WhileTrue node) { |
| 109 Block continueTarget = new Block(); | 116 Block continueTarget = new Block(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 130 whileBlock.addEdgeTo(bodyBlock); | 137 whileBlock.addEdgeTo(bodyBlock); |
| 131 whileBlock.addEdgeTo(nextBlock); | 138 whileBlock.addEdgeTo(nextBlock); |
| 132 | 139 |
| 133 continueTargets[node.label] = bodyBlock; | 140 continueTargets[node.label] = bodyBlock; |
| 134 _addBlock(bodyBlock); | 141 _addBlock(bodyBlock); |
| 135 visitStatement(node.body); | 142 visitStatement(node.body); |
| 136 | 143 |
| 137 _addBlock(nextBlock); | 144 _addBlock(nextBlock); |
| 138 visitStatement(node.next); | 145 visitStatement(node.next); |
| 139 | 146 |
| 140 ifTargets[node.body] = bodyBlock; | 147 substatements[node.body] = bodyBlock; |
| 141 ifTargets[node.next] = nextBlock; | 148 substatements[node.next] = nextBlock; |
| 142 } | 149 } |
| 143 | 150 |
| 144 visitTry(Try node) { | 151 visitTry(Try node) { |
| 145 // It's not obvious how we want to represent try statements here. | 152 _addStatement(node); |
| 146 // TODO(kmillikin). | 153 Block tryBlock = new Block(); |
| 154 Block catchBlock = new Block(); |
| 155 |
| 156 Block oldCatcher = catcher; |
| 157 catcher = catchBlock; |
| 158 _addBlock(tryBlock); |
| 159 visitStatement(node.tryBody); |
| 160 catcher = oldCatcher; |
| 161 |
| 162 _addBlock(catchBlock); |
| 163 visitStatement(node.catchBody); |
| 164 |
| 165 substatements[node.tryBody] = tryBlock; |
| 166 substatements[node.catchBody] = catchBlock; |
| 147 } | 167 } |
| 148 | 168 |
| 149 visitExpressionStatement(ExpressionStatement node) { | 169 visitExpressionStatement(ExpressionStatement node) { |
| 150 _addStatement(node); | 170 _addStatement(node); |
| 151 visitStatement(node.next); | 171 visitStatement(node.next); |
| 152 } | 172 } |
| 153 | 173 |
| 154 visitFunctionDeclaration(FunctionDeclaration node) { | 174 visitFunctionDeclaration(FunctionDeclaration node) { |
| 155 _addStatement(node); | 175 _addStatement(node); |
| 156 visitStatement(node.next); | 176 visitStatement(node.next); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 tag("locals", () { | 225 tag("locals", () { |
| 206 printProperty("size", 0); | 226 printProperty("size", 0); |
| 207 printProperty("method", "None"); | 227 printProperty("method", "None"); |
| 208 }); | 228 }); |
| 209 }); | 229 }); |
| 210 tag("HIR", () { | 230 tag("HIR", () { |
| 211 if (block.label != null) { | 231 if (block.label != null) { |
| 212 printStatement(null, | 232 printStatement(null, |
| 213 "Label ${block.name}, useCount=${block.label.useCount}"); | 233 "Label ${block.name}, useCount=${block.label.useCount}"); |
| 214 } | 234 } |
| 235 if (block.catcher != null) { |
| 236 printStatement(null, 'Catch exceptions at ${block.catcher.name}'); |
| 237 } |
| 215 block.statements.forEach(visitBlockMember); | 238 block.statements.forEach(visitBlockMember); |
| 216 }); | 239 }); |
| 217 }); | 240 }); |
| 218 } | 241 } |
| 219 | 242 |
| 220 void visitBlockMember(member) { | 243 void visitBlockMember(member) { |
| 221 if (member is Block) { | 244 if (member is Block) { |
| 222 printStatement(null, "goto block B${member.name}"); | 245 printStatement(null, "goto block B${member.name}"); |
| 223 } else { | 246 } else { |
| 224 assert(member is Statement); | 247 assert(member is Statement); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 printStatement(null, "break ${collector.breakTargets[node.target].name}"); | 279 printStatement(null, "break ${collector.breakTargets[node.target].name}"); |
| 257 } | 280 } |
| 258 | 281 |
| 259 visitContinue(Continue node) { | 282 visitContinue(Continue node) { |
| 260 printStatement(null, | 283 printStatement(null, |
| 261 "continue ${collector.continueTargets[node.target].name}"); | 284 "continue ${collector.continueTargets[node.target].name}"); |
| 262 } | 285 } |
| 263 | 286 |
| 264 visitIf(If node) { | 287 visitIf(If node) { |
| 265 String condition = expr(node.condition); | 288 String condition = expr(node.condition); |
| 266 String thenTarget = collector.ifTargets[node.thenStatement].name; | 289 String thenTarget = collector.substatements[node.thenStatement].name; |
| 267 String elseTarget = collector.ifTargets[node.elseStatement].name; | 290 String elseTarget = collector.substatements[node.elseStatement].name; |
| 268 printStatement(null, "if $condition then $thenTarget else $elseTarget"); | 291 printStatement(null, "if $condition then $thenTarget else $elseTarget"); |
| 269 } | 292 } |
| 270 | 293 |
| 271 visitWhileTrue(WhileTrue node) { | 294 visitWhileTrue(WhileTrue node) { |
| 272 printStatement(null, "while true do"); | 295 printStatement(null, "while true do"); |
| 273 } | 296 } |
| 274 | 297 |
| 275 visitWhileCondition(WhileCondition node) { | 298 visitWhileCondition(WhileCondition node) { |
| 276 String bodyTarget = collector.ifTargets[node.body].name; | 299 String bodyTarget = collector.substatements[node.body].name; |
| 277 String nextTarget = collector.ifTargets[node.next].name; | 300 String nextTarget = collector.substatements[node.next].name; |
| 278 printStatement(null, "while ${expr(node.condition)}"); | 301 printStatement(null, "while ${expr(node.condition)}"); |
| 279 printStatement(null, "do $bodyTarget"); | 302 printStatement(null, "do $bodyTarget"); |
| 280 printStatement(null, "then $nextTarget" ); | 303 printStatement(null, "then $nextTarget" ); |
| 281 } | 304 } |
| 282 | 305 |
| 283 visitTry(Try node) { | 306 visitTry(Try node) { |
| 284 // It's not obvious how we want to represent try statements here. | 307 String tryTarget = collector.substatements[node.tryBody].name; |
| 285 // TODO(kmillikin). | 308 String catchParams = node.catchParameters.map(names.varName).join(','); |
| 309 String catchTarget = collector.substatements[node.catchBody].name; |
| 310 printStatement(null, 'try $tryTarget catch($catchParams) $catchTarget'); |
| 286 } | 311 } |
| 287 | 312 |
| 288 visitExpressionStatement(ExpressionStatement node) { | 313 visitExpressionStatement(ExpressionStatement node) { |
| 289 printStatement(null, expr(node.expression)); | 314 printStatement(null, expr(node.expression)); |
| 290 } | 315 } |
| 291 | 316 |
| 292 visitFunctionDeclaration(FunctionDeclaration node) { | 317 visitFunctionDeclaration(FunctionDeclaration node) { |
| 293 printStatement(null, 'function ${node.definition.element.name}'); | 318 printStatement(null, 'function ${node.definition.element.name}'); |
| 294 } | 319 } |
| 295 | 320 |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 String prefix = v.element == null ? 'v' : '${v.element.name}_'; | 509 String prefix = v.element == null ? 'v' : '${v.element.name}_'; |
| 485 while (name == null || _usedNames.contains(name)) { | 510 while (name == null || _usedNames.contains(name)) { |
| 486 name = "$prefix${_counter++}"; | 511 name = "$prefix${_counter++}"; |
| 487 } | 512 } |
| 488 _names[v] = name; | 513 _names[v] = name; |
| 489 _usedNames.add(name); | 514 _usedNames.add(name); |
| 490 } | 515 } |
| 491 return name; | 516 return name; |
| 492 } | 517 } |
| 493 } | 518 } |
| OLD | NEW |