| 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'; | |
| 11 | 10 |
| 12 class Block { | 11 class Block { |
| 13 Label label; | 12 Label label; |
| 14 int index; | 13 int index; |
| 15 /// Mixed list of [Statement] and [Block]. | 14 /// Mixed list of [Statement] and [Block]. |
| 16 /// A [Block] represents a synthetic goto statement. | 15 /// A [Block] represents a synthetic goto statement. |
| 17 final List statements = []; | 16 final List statements = []; |
| 18 final List<Block> predecessors = <Block>[]; | 17 final List<Block> predecessors = <Block>[]; |
| 19 final List<Block> successors = <Block>[]; | 18 final List<Block> successors = <Block>[]; |
| 20 | 19 |
| 21 /// The catch block associated with the immediately enclosing try block or | 20 /// The catch block associated with the immediately enclosing try block or |
| 22 /// `null` if not inside a try block. | 21 /// `null` if not inside a try block. |
| 23 Block catcher; | 22 Block catcher; |
| 24 | 23 |
| 24 /// True if this block is the entry point to one of the bodies |
| 25 /// (constructors can have multiple bodies). |
| 26 bool isEntryPoint = false; |
| 27 |
| 25 String get name => 'B$index'; | 28 String get name => 'B$index'; |
| 26 | 29 |
| 27 Block([this.label]); | 30 Block([this.label]); |
| 28 | 31 |
| 29 void addEdgeTo(Block successor) { | 32 void addEdgeTo(Block successor) { |
| 30 successors.add(successor); | 33 successors.add(successor); |
| 31 successor.predecessors.add(this); | 34 successor.predecessors.add(this); |
| 32 } | 35 } |
| 33 } | 36 } |
| 34 | 37 |
| 35 class BlockCollector extends StatementVisitor { | 38 class BlockCollector extends StatementVisitor { |
| 36 // Accumulate a list of blocks. The current block is the last block in | 39 // Accumulate a list of blocks. The current block is the last block in |
| 37 // the list. | 40 // the list. |
| 38 final List<Block> blocks = [new Block()..index = 0]; | 41 final List<Block> blocks = []; |
| 39 | 42 |
| 40 // Map tree [Label]s (break or continue targets) and [Statement]s | 43 // Map tree [Label]s (break or continue targets) and [Statement]s |
| 41 // (if targets) to blocks. | 44 // (if targets) to blocks. |
| 42 final Map<Label, Block> breakTargets = <Label, Block>{}; | 45 final Map<Label, Block> breakTargets = <Label, Block>{}; |
| 43 final Map<Label, Block> continueTargets = <Label, Block>{}; | 46 final Map<Label, Block> continueTargets = <Label, Block>{}; |
| 44 final Map<Statement, Block> substatements = <Statement, Block>{}; | 47 final Map<Statement, Block> substatements = <Statement, Block>{}; |
| 45 | 48 |
| 46 Block catcher; | 49 Block catcher; |
| 47 | 50 |
| 48 void _addStatement(Statement statement) { | 51 void _addStatement(Statement statement) { |
| 49 blocks.last.statements.add(statement); | 52 blocks.last.statements.add(statement); |
| 50 } | 53 } |
| 51 void _addGotoStatement(Block target) { | 54 void _addGotoStatement(Block target) { |
| 52 blocks.last.statements.add(target); | 55 blocks.last.statements.add(target); |
| 53 } | 56 } |
| 54 | 57 |
| 55 void _addBlock(Block block) { | 58 void _addBlock(Block block) { |
| 56 block.index = blocks.length; | 59 block.index = blocks.length; |
| 57 block.catcher = catcher; | 60 block.catcher = catcher; |
| 58 blocks.add(block); | 61 blocks.add(block); |
| 59 } | 62 } |
| 60 | 63 |
| 61 void collect(ExecutableDefinition node) { | 64 void collect(RootNode node) { |
| 62 if (node.body != null) { | 65 node.forEachBody((Statement body) { |
| 63 if (node is ConstructorDefinition) { | 66 _addBlock(new Block()..isEntryPoint = true); |
| 64 for (Initializer initializer in node.initializers) { | 67 visitStatement(body); |
| 65 if (initializer is FieldInitializer) { | 68 }); |
| 66 visitStatement(initializer.body); | |
| 67 } | |
| 68 } | |
| 69 } | |
| 70 visitStatement(node.body); | |
| 71 } | |
| 72 } | 69 } |
| 73 | 70 |
| 74 visitLabeledStatement(LabeledStatement node) { | 71 visitLabeledStatement(LabeledStatement node) { |
| 75 Block target = new Block(node.label); | 72 Block target = new Block(node.label); |
| 76 breakTargets[node.label] = target; | 73 breakTargets[node.label] = target; |
| 77 visitStatement(node.body); | 74 visitStatement(node.body); |
| 78 _addBlock(target); | 75 _addBlock(target); |
| 79 visitStatement(node.next); | 76 visitStatement(node.next); |
| 80 } | 77 } |
| 81 | 78 |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 visitStatement(node.next); | 173 visitStatement(node.next); |
| 177 } | 174 } |
| 178 | 175 |
| 179 visitSetField(SetField node) { | 176 visitSetField(SetField node) { |
| 180 _addStatement(node); | 177 _addStatement(node); |
| 181 visitStatement(node.next); | 178 visitStatement(node.next); |
| 182 } | 179 } |
| 183 | 180 |
| 184 } | 181 } |
| 185 | 182 |
| 186 class TreeTracer extends TracerUtil with StatementVisitor, PassMixin { | 183 class TreeTracer extends TracerUtil with StatementVisitor { |
| 187 // TODO(asgerf): Fix visitors so we don't have to use PassMixin here. | |
| 188 String get passName => null; | 184 String get passName => null; |
| 189 | 185 |
| 190 final EventSink<String> output; | 186 final EventSink<String> output; |
| 191 | 187 |
| 192 TreeTracer(this.output); | 188 TreeTracer(this.output); |
| 193 | 189 |
| 190 List<Variable> parameters; |
| 194 Names names; | 191 Names names; |
| 195 BlockCollector collector; | 192 BlockCollector collector; |
| 196 int statementCounter; | 193 int statementCounter; |
| 197 | 194 |
| 198 void traceGraph(String name, ExecutableDefinition node) { | 195 void traceGraph(String name, RootNode node) { |
| 199 if (node is FunctionDefinition && node.isAbstract) return; | 196 if (node.isEmpty) return; |
| 200 if (node is FieldDefinition && node.body == null) return; | 197 parameters = node.parameters; |
| 201 tag("cfg", () { | 198 tag("cfg", () { |
| 202 printProperty("name", name); | 199 printProperty("name", name); |
| 203 rewrite(node); | 200 printRootNode(node); |
| 204 collector.blocks.forEach(printBlock); | 201 collector.blocks.forEach(printBlock); |
| 205 }); | 202 }); |
| 206 } | 203 } |
| 207 | 204 |
| 208 @override | 205 void printRootNode(RootNode node) { |
| 209 void rewriteExecutableDefinition(ExecutableDefinition node) { | |
| 210 collector = new BlockCollector(); | 206 collector = new BlockCollector(); |
| 211 names = new Names(); | 207 names = new Names(); |
| 212 statementCounter = 0; | 208 statementCounter = 0; |
| 213 collector = new BlockCollector(); | 209 collector = new BlockCollector(); |
| 214 collector.collect(node); | 210 collector.collect(node); |
| 215 collector.blocks.forEach(printBlock); | 211 collector.blocks.forEach(printBlock); |
| 216 } | 212 } |
| 217 | 213 |
| 218 void printBlock(Block block) { | 214 void printBlock(Block block) { |
| 219 tag("block", () { | 215 tag("block", () { |
| 220 printProperty("name", block.name); | 216 printProperty("name", block.name); |
| 221 printProperty("from_bci", -1); | 217 printProperty("from_bci", -1); |
| 222 printProperty("to_bci", -1); | 218 printProperty("to_bci", -1); |
| 223 printProperty("predecessors", block.predecessors.map((b) => b.name)); | 219 printProperty("predecessors", block.predecessors.map((b) => b.name)); |
| 224 printProperty("successors", block.successors.map((b) => b.name)); | 220 printProperty("successors", block.successors.map((b) => b.name)); |
| 225 printEmptyProperty("xhandlers"); | 221 printEmptyProperty("xhandlers"); |
| 226 printEmptyProperty("flags"); | 222 printEmptyProperty("flags"); |
| 227 tag("states", () { | 223 tag("states", () { |
| 228 tag("locals", () { | 224 tag("locals", () { |
| 229 printProperty("size", 0); | 225 printProperty("size", 0); |
| 230 printProperty("method", "None"); | 226 printProperty("method", "None"); |
| 231 }); | 227 }); |
| 232 }); | 228 }); |
| 233 tag("HIR", () { | 229 tag("HIR", () { |
| 230 if (block.isEntryPoint) { |
| 231 String params = parameters.map(names.varName).join(', '); |
| 232 printStatement(null, 'Entry ($params)'); |
| 233 } |
| 234 if (block.label != null) { | 234 if (block.label != null) { |
| 235 printStatement(null, | 235 printStatement(null, |
| 236 "Label ${block.name}, useCount=${block.label.useCount}"); | 236 "Label ${block.name}, useCount=${block.label.useCount}"); |
| 237 } | 237 } |
| 238 if (block.catcher != null) { | 238 if (block.catcher != null) { |
| 239 printStatement(null, 'Catch exceptions at ${block.catcher.name}'); | 239 printStatement(null, 'Catch exceptions at ${block.catcher.name}'); |
| 240 } | 240 } |
| 241 block.statements.forEach(visitBlockMember); | 241 block.statements.forEach(visitBlockMember); |
| 242 }); | 242 }); |
| 243 }); | 243 }); |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 String prefix = v.element == null ? 'v' : '${v.element.name}_'; | 528 String prefix = v.element == null ? 'v' : '${v.element.name}_'; |
| 529 while (name == null || _usedNames.contains(name)) { | 529 while (name == null || _usedNames.contains(name)) { |
| 530 name = "$prefix${_counter++}"; | 530 name = "$prefix${_counter++}"; |
| 531 } | 531 } |
| 532 _names[v] = name; | 532 _names[v] = name; |
| 533 _usedNames.add(name); | 533 _usedNames.add(name); |
| 534 } | 534 } |
| 535 return name; | 535 return name; |
| 536 } | 536 } |
| 537 } | 537 } |
| OLD | NEW |