| 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 dart2js.ir_tracer; | 5 library dart2js.ir_tracer; |
| 6 | 6 |
| 7 import 'dart:async' show EventSink; | 7 import 'dart:async' show EventSink; |
| 8 | 8 |
| 9 import 'cps_ir_nodes.dart' as cps_ir hide Function; | 9 import 'cps_ir_nodes.dart' as cps_ir hide Function; |
| 10 import '../tracer.dart'; | 10 import '../tracer.dart'; |
| 11 | 11 |
| 12 /** | 12 /** |
| 13 * If true, show LetCont expressions in output. | 13 * If true, show LetCont expressions in output. |
| 14 */ | 14 */ |
| 15 const bool IR_TRACE_LET_CONT = false; | 15 const bool IR_TRACE_LET_CONT = false; |
| 16 | 16 |
| 17 class IRTracer extends TracerUtil implements cps_ir.Visitor { | 17 class IRTracer extends TracerUtil implements cps_ir.Visitor { |
| 18 EventSink<String> output; | 18 EventSink<String> output; |
| 19 | 19 |
| 20 IRTracer(this.output); | 20 IRTracer(this.output); |
| 21 | 21 |
| 22 visit(cps_ir.Node node) => node.accept(this); | 22 visit(cps_ir.Node node) => node.accept(this); |
| 23 | 23 |
| 24 void traceGraph(String name, cps_ir.ExecutableDefinition graph) { | 24 void traceGraph(String name, cps_ir.RootNode node) { |
| 25 if (node.isEmpty) return; // Don't bother printing an empty trace. |
| 25 tag("cfg", () { | 26 tag("cfg", () { |
| 26 printProperty("name", name); | 27 printProperty("name", name); |
| 27 visit(graph); | 28 |
| 29 names = new Names(); |
| 30 BlockCollector builder = new BlockCollector(names); |
| 31 builder.visit(node); |
| 32 |
| 33 for (Block block in builder.entries) { |
| 34 printBlock(block, entryPointParameters: node.parameters); |
| 35 } |
| 36 for (Block block in builder.cont2block.values) { |
| 37 printBlock(block); |
| 38 } |
| 39 names = null; |
| 28 }); | 40 }); |
| 29 } | 41 } |
| 30 | 42 |
| 31 // Temporary field used during tree walk | 43 // Temporary field used during tree walk |
| 32 Names names; | 44 Names names; |
| 33 | 45 |
| 34 printDefinition(cps_ir.ExecutableDefinition node) { | |
| 35 names = new Names(); | |
| 36 BlockCollector builder = new BlockCollector(names); | |
| 37 builder.visit(node); | |
| 38 | |
| 39 for (Block block in builder.entries) { | |
| 40 printBlock(block); | |
| 41 } | |
| 42 for (Block block in builder.cont2block.values) { | |
| 43 printBlock(block); | |
| 44 } | |
| 45 names = null; | |
| 46 } | |
| 47 | |
| 48 visitFieldDefinition(cps_ir.FieldDefinition node) { | 46 visitFieldDefinition(cps_ir.FieldDefinition node) { |
| 49 if (node.hasInitializer) { | 47 unexpectedNode(node); |
| 50 printDefinition(node); | |
| 51 } | |
| 52 } | 48 } |
| 53 | 49 |
| 54 visitFunctionDefinition(cps_ir.FunctionDefinition node) { | 50 visitFunctionDefinition(cps_ir.FunctionDefinition node) { |
| 55 if (node.isAbstract) return; | 51 unexpectedNode(node); |
| 56 printDefinition(node); | |
| 57 } | 52 } |
| 58 | 53 |
| 59 visitConstructorDefinition(cps_ir.ConstructorDefinition node) { | 54 visitConstructorDefinition(cps_ir.ConstructorDefinition node) { |
| 60 if (node.isAbstract) return; | 55 unexpectedNode(node); |
| 61 printDefinition(node); | 56 } |
| 57 |
| 58 visitFieldInitializer(cps_ir.FieldInitializer node) { |
| 59 unexpectedNode(node); |
| 60 } |
| 61 |
| 62 visitSuperInitializer(cps_ir.SuperInitializer node) { |
| 63 unexpectedNode(node); |
| 64 } |
| 65 |
| 66 visitBody(cps_ir.Body node) { |
| 67 unexpectedNode(node); |
| 62 } | 68 } |
| 63 | 69 |
| 64 // Bodies and initializers are not visited. They contain continuations which | 70 // Bodies and initializers are not visited. They contain continuations which |
| 65 // are found by a BlockCollector, then those continuations are processed by | 71 // are found by a BlockCollector, then those continuations are processed by |
| 66 // this visitor. | 72 // this visitor. |
| 67 unexpectedNode(cps_ir.Node node) { | 73 unexpectedNode(cps_ir.Node node) { |
| 68 throw 'The IR tracer reached an unexpected IR instruction: $node'; | 74 throw 'The IR tracer reached an unexpected IR instruction: $node'; |
| 69 } | 75 } |
| 70 | 76 |
| 71 visitRunnableBody(cps_ir.RunnableBody node) { | |
| 72 unexpectedNode(node); | |
| 73 } | |
| 74 visitFieldInitializer(cps_ir.FieldInitializer node) { | |
| 75 unexpectedNode(node); | |
| 76 } | |
| 77 visitSuperInitializer(cps_ir.SuperInitializer node) { | |
| 78 unexpectedNode(node); | |
| 79 } | |
| 80 | 77 |
| 81 int countUses(cps_ir.Definition definition) { | 78 int countUses(cps_ir.Definition definition) { |
| 82 int count = 0; | 79 int count = 0; |
| 83 cps_ir.Reference ref = definition.firstRef; | 80 cps_ir.Reference ref = definition.firstRef; |
| 84 while (ref != null) { | 81 while (ref != null) { |
| 85 ++count; | 82 ++count; |
| 86 ref = ref.next; | 83 ref = ref.next; |
| 87 } | 84 } |
| 88 return count; | 85 return count; |
| 89 } | 86 } |
| 90 | 87 |
| 91 printBlock(Block block) { | 88 /// If [entryPointParameters] is given, this block is an entry point |
| 89 /// and [entryPointParameters] is the list of function parameters. |
| 90 printBlock(Block block, {List<cps_ir.Definition> entryPointParameters}) { |
| 92 tag("block", () { | 91 tag("block", () { |
| 93 printProperty("name", block.name); | 92 printProperty("name", block.name); |
| 94 printProperty("from_bci", -1); | 93 printProperty("from_bci", -1); |
| 95 printProperty("to_bci", -1); | 94 printProperty("to_bci", -1); |
| 96 printProperty("predecessors", block.pred.map((n) => n.name)); | 95 printProperty("predecessors", block.pred.map((n) => n.name)); |
| 97 printProperty("successors", block.succ.map((n) => n.name)); | 96 printProperty("successors", block.succ.map((n) => n.name)); |
| 98 printEmptyProperty("xhandlers"); | 97 printEmptyProperty("xhandlers"); |
| 99 printEmptyProperty("flags"); | 98 printEmptyProperty("flags"); |
| 100 tag("states", () { | 99 tag("states", () { |
| 101 tag("locals", () { | 100 tag("locals", () { |
| 102 printProperty("size", 0); | 101 printProperty("size", 0); |
| 103 printProperty("method", "None"); | 102 printProperty("method", "None"); |
| 104 }); | 103 }); |
| 105 }); | 104 }); |
| 106 tag("HIR", () { | 105 tag("HIR", () { |
| 106 if (entryPointParameters != null) { |
| 107 String params = entryPointParameters.map(names.name).join(', '); |
| 108 printStmt('x0', 'Entry ($params)'); |
| 109 } |
| 107 for (cps_ir.Parameter param in block.parameters) { | 110 for (cps_ir.Parameter param in block.parameters) { |
| 108 String name = names.name(param); | 111 String name = names.name(param); |
| 109 printStmt(name, "Parameter $name [useCount=${countUses(param)}]"); | 112 printStmt(name, "Parameter $name [useCount=${countUses(param)}]"); |
| 110 } | 113 } |
| 111 visit(block.body); | 114 visit(block.body); |
| 112 }); | 115 }); |
| 113 }); | 116 }); |
| 114 } | 117 } |
| 115 | 118 |
| 116 void printStmt(String resultVar, String contents) { | 119 void printStmt(String resultVar, String contents) { |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 void addEdgeTo(Block successor) { | 408 void addEdgeTo(Block successor) { |
| 406 succ.add(successor); | 409 succ.add(successor); |
| 407 successor.pred.add(this); | 410 successor.pred.add(this); |
| 408 } | 411 } |
| 409 } | 412 } |
| 410 | 413 |
| 411 class BlockCollector implements cps_ir.Visitor { | 414 class BlockCollector implements cps_ir.Visitor { |
| 412 final Map<cps_ir.Continuation, Block> cont2block = | 415 final Map<cps_ir.Continuation, Block> cont2block = |
| 413 <cps_ir.Continuation, Block>{}; | 416 <cps_ir.Continuation, Block>{}; |
| 414 final Set<Block> entries = new Set<Block>(); | 417 final Set<Block> entries = new Set<Block>(); |
| 415 Block current_block; | 418 Block currentBlock; |
| 416 | 419 |
| 417 Names names; | 420 Names names; |
| 418 BlockCollector(this.names); | 421 BlockCollector(this.names); |
| 419 | 422 |
| 420 Block getBlock(cps_ir.Continuation c) { | 423 Block getBlock(cps_ir.Continuation c) { |
| 421 Block block = cont2block[c]; | 424 Block block = cont2block[c]; |
| 422 if (block == null) { | 425 if (block == null) { |
| 423 block = new Block(names.name(c), c.parameters, c.body); | 426 block = new Block(names.name(c), c.parameters, c.body); |
| 424 cont2block[c] = block; | 427 cont2block[c] = block; |
| 425 } | 428 } |
| 426 return block; | 429 return block; |
| 427 } | 430 } |
| 428 | 431 |
| 429 visit(cps_ir.Node node) => node.accept(this); | 432 visit(cps_ir.Node node) => node.accept(this); |
| 430 | 433 |
| 431 visitFieldDefinition(cps_ir.FieldDefinition node) { | 434 visitFieldDefinition(cps_ir.FieldDefinition node) { |
| 432 if (node.hasInitializer) { | 435 visit(node.body); |
| 433 visit(node.body); | |
| 434 } | |
| 435 } | 436 } |
| 436 | 437 |
| 437 visitFunctionDefinition(cps_ir.FunctionDefinition node) { | 438 visitFunctionDefinition(cps_ir.FunctionDefinition node) { |
| 438 visit(node.body); | 439 visit(node.body); |
| 439 } | 440 } |
| 440 | 441 |
| 441 visitConstructorDefinition(cps_ir.ConstructorDefinition node) { | 442 visitConstructorDefinition(cps_ir.ConstructorDefinition node) { |
| 443 node.initializers.forEach(visit); |
| 442 visit(node.body); | 444 visit(node.body); |
| 443 } | 445 } |
| 444 | 446 |
| 445 visitRunnableBody(cps_ir.RunnableBody node) { | 447 visitBody(cps_ir.Body node) { |
| 446 current_block = new Block(names.name(node), [], node.body); | 448 currentBlock = new Block(names.name(node), [], node.body); |
| 447 entries.add(current_block); | 449 entries.add(currentBlock); |
| 448 visit(node.body); | 450 visit(node.body); |
| 449 } | 451 } |
| 450 | 452 |
| 451 visitFieldInitializer(cps_ir.FieldInitializer node) { | 453 visitFieldInitializer(cps_ir.FieldInitializer node) { |
| 452 visit(node.body); | 454 visit(node.body); |
| 453 } | 455 } |
| 454 | 456 |
| 455 visitSuperInitializer(cps_ir.SuperInitializer node) { | 457 visitSuperInitializer(cps_ir.SuperInitializer node) { |
| 456 node.arguments.forEach(visit); | 458 node.arguments.forEach(visit); |
| 457 } | 459 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 470 visit(exp.body); | 472 visit(exp.body); |
| 471 } | 473 } |
| 472 | 474 |
| 473 visitLetMutable(cps_ir.LetMutable exp) { | 475 visitLetMutable(cps_ir.LetMutable exp) { |
| 474 visit(exp.body); | 476 visit(exp.body); |
| 475 } | 477 } |
| 476 | 478 |
| 477 void addEdgeToContinuation(cps_ir.Reference continuation) { | 479 void addEdgeToContinuation(cps_ir.Reference continuation) { |
| 478 cps_ir.Definition target = continuation.definition; | 480 cps_ir.Definition target = continuation.definition; |
| 479 if (target is cps_ir.Continuation && !target.isReturnContinuation) { | 481 if (target is cps_ir.Continuation && !target.isReturnContinuation) { |
| 480 current_block.addEdgeTo(getBlock(target)); | 482 currentBlock.addEdgeTo(getBlock(target)); |
| 481 } | 483 } |
| 482 } | 484 } |
| 483 | 485 |
| 484 visitInvokeContinuation(cps_ir.InvokeContinuation exp) { | 486 visitInvokeContinuation(cps_ir.InvokeContinuation exp) { |
| 485 addEdgeToContinuation(exp.continuation); | 487 addEdgeToContinuation(exp.continuation); |
| 486 } | 488 } |
| 487 | 489 |
| 488 visitInvokeStatic(cps_ir.InvokeStatic exp) { | 490 visitInvokeStatic(cps_ir.InvokeStatic exp) { |
| 489 addEdgeToContinuation(exp.continuation); | 491 addEdgeToContinuation(exp.continuation); |
| 490 } | 492 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 513 visit(exp.body); | 515 visit(exp.body); |
| 514 } | 516 } |
| 515 | 517 |
| 516 visitDeclareFunction(cps_ir.DeclareFunction exp) { | 518 visitDeclareFunction(cps_ir.DeclareFunction exp) { |
| 517 visit(exp.body); | 519 visit(exp.body); |
| 518 } | 520 } |
| 519 | 521 |
| 520 visitBranch(cps_ir.Branch exp) { | 522 visitBranch(cps_ir.Branch exp) { |
| 521 cps_ir.Continuation trueTarget = exp.trueContinuation.definition; | 523 cps_ir.Continuation trueTarget = exp.trueContinuation.definition; |
| 522 if (!trueTarget.isReturnContinuation) { | 524 if (!trueTarget.isReturnContinuation) { |
| 523 current_block.addEdgeTo(getBlock(trueTarget)); | 525 currentBlock.addEdgeTo(getBlock(trueTarget)); |
| 524 } | 526 } |
| 525 cps_ir.Continuation falseTarget = exp.falseContinuation.definition; | 527 cps_ir.Continuation falseTarget = exp.falseContinuation.definition; |
| 526 if (!falseTarget.isReturnContinuation) { | 528 if (!falseTarget.isReturnContinuation) { |
| 527 current_block.addEdgeTo(getBlock(falseTarget)); | 529 currentBlock.addEdgeTo(getBlock(falseTarget)); |
| 528 } | 530 } |
| 529 } | 531 } |
| 530 | 532 |
| 531 visitTypeOperator(cps_ir.TypeOperator exp) { | 533 visitTypeOperator(cps_ir.TypeOperator exp) { |
| 532 addEdgeToContinuation(exp.continuation); | 534 addEdgeToContinuation(exp.continuation); |
| 533 } | 535 } |
| 534 | 536 |
| 535 visitContinuation(cps_ir.Continuation c) { | 537 visitContinuation(cps_ir.Continuation c) { |
| 536 var old_node = current_block; | 538 var old_node = currentBlock; |
| 537 current_block = getBlock(c); | 539 currentBlock = getBlock(c); |
| 538 visit(c.body); | 540 visit(c.body); |
| 539 current_block = old_node; | 541 currentBlock = old_node; |
| 540 } | 542 } |
| 541 | 543 |
| 542 // Primitives and conditions are not visited when searching for blocks. | 544 // Primitives and conditions are not visited when searching for blocks. |
| 543 unexpectedNode(cps_ir.Node node) { | 545 unexpectedNode(cps_ir.Node node) { |
| 544 throw "The IR tracer's block collector reached an unexpected IR " | 546 throw "The IR tracer's block collector reached an unexpected IR " |
| 545 "instruction: $node"; | 547 "instruction: $node"; |
| 546 } | 548 } |
| 547 | 549 |
| 548 visitLiteralList(cps_ir.LiteralList node) { | 550 visitLiteralList(cps_ir.LiteralList node) { |
| 549 unexpectedNode(node); | 551 unexpectedNode(node); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 @override | 598 @override |
| 597 visitReifyRuntimeType(cps_ir.ReifyRuntimeType node) { | 599 visitReifyRuntimeType(cps_ir.ReifyRuntimeType node) { |
| 598 unexpectedNode(node); | 600 unexpectedNode(node); |
| 599 } | 601 } |
| 600 | 602 |
| 601 @override | 603 @override |
| 602 visitTypeExpression(cps_ir.TypeExpression node) { | 604 visitTypeExpression(cps_ir.TypeExpression node) { |
| 603 unexpectedNode(node); | 605 unexpectedNode(node); |
| 604 } | 606 } |
| 605 } | 607 } |
| OLD | NEW |