| 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 | |
| 9 import 'cps_ir_nodes.dart' as cps_ir hide Function; | 8 import 'cps_ir_nodes.dart' as cps_ir hide Function; |
| 10 import '../tracer.dart'; | 9 import '../tracer.dart'; |
| 11 | 10 |
| 12 /** | 11 /** |
| 13 * If true, show LetCont expressions in output. | 12 * If true, show LetCont expressions in output. |
| 14 */ | 13 */ |
| 15 const bool IR_TRACE_LET_CONT = false; | 14 const bool IR_TRACE_LET_CONT = false; |
| 16 | 15 |
| 17 class IRTracer extends TracerUtil implements cps_ir.Visitor { | 16 class IRTracer extends TracerUtil implements cps_ir.Visitor { |
| 18 EventSink<String> output; | 17 EventSink<String> output; |
| 19 | 18 |
| 20 IRTracer(this.output); | 19 IRTracer(this.output); |
| 21 | 20 |
| 22 visit(cps_ir.Node node) => node.accept(this); | 21 visit(cps_ir.Node node) => node.accept(this); |
| 23 | 22 |
| 24 void traceGraph(String name, cps_ir.RootNode node) { | 23 void traceGraph(String name, cps_ir.FunctionDefinition node) { |
| 25 if (node.isEmpty) return; // Don't bother printing an empty trace. | |
| 26 tag("cfg", () { | 24 tag("cfg", () { |
| 27 printProperty("name", name); | 25 printProperty("name", name); |
| 28 | 26 |
| 29 names = new Names(); | 27 names = new Names(); |
| 30 BlockCollector builder = new BlockCollector(names); | 28 BlockCollector builder = new BlockCollector(names); |
| 31 builder.visit(node); | 29 builder.visit(node); |
| 32 | 30 |
| 33 for (Block block in builder.entries) { | 31 for (Block block in builder.entries) { |
| 34 printBlock(block, entryPointParameters: node.parameters); | 32 printBlock(block, entryPointParameters: node.parameters); |
| 35 } | 33 } |
| 36 for (Block block in builder.cont2block.values) { | 34 for (Block block in builder.cont2block.values) { |
| 37 printBlock(block); | 35 printBlock(block); |
| 38 } | 36 } |
| 39 names = null; | 37 names = null; |
| 40 }); | 38 }); |
| 41 } | 39 } |
| 42 | 40 |
| 43 // Temporary field used during tree walk | 41 // Temporary field used during tree walk |
| 44 Names names; | 42 Names names; |
| 45 | 43 |
| 46 visitFieldDefinition(cps_ir.FieldDefinition node) { | |
| 47 unexpectedNode(node); | |
| 48 } | |
| 49 | |
| 50 visitFunctionDefinition(cps_ir.FunctionDefinition node) { | 44 visitFunctionDefinition(cps_ir.FunctionDefinition node) { |
| 51 unexpectedNode(node); | 45 unexpectedNode(node); |
| 52 } | 46 } |
| 53 | 47 |
| 54 visitConstructorDefinition(cps_ir.ConstructorDefinition node) { | |
| 55 unexpectedNode(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); | |
| 68 } | |
| 69 | |
| 70 // Bodies and initializers are not visited. They contain continuations which | 48 // Bodies and initializers are not visited. They contain continuations which |
| 71 // are found by a BlockCollector, then those continuations are processed by | 49 // are found by a BlockCollector, then those continuations are processed by |
| 72 // this visitor. | 50 // this visitor. |
| 73 unexpectedNode(cps_ir.Node node) { | 51 unexpectedNode(cps_ir.Node node) { |
| 74 throw 'The IR tracer reached an unexpected IR instruction: $node'; | 52 throw 'The IR tracer reached an unexpected IR instruction: $node'; |
| 75 } | 53 } |
| 76 | 54 |
| 77 | 55 |
| 78 int countUses(cps_ir.Definition definition) { | 56 int countUses(cps_ir.Definition definition) { |
| 79 int count = 0; | 57 int count = 0; |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 } | 235 } |
| 258 | 236 |
| 259 visitSetMutableVariable(cps_ir.SetMutableVariable node) { | 237 visitSetMutableVariable(cps_ir.SetMutableVariable node) { |
| 260 String dummy = names.name(node); | 238 String dummy = names.name(node); |
| 261 String variable = names.name(node.variable.definition); | 239 String variable = names.name(node.variable.definition); |
| 262 String value = formatReference(node.value); | 240 String value = formatReference(node.value); |
| 263 printStmt(dummy, 'SetMutableVariable $variable := $value'); | 241 printStmt(dummy, 'SetMutableVariable $variable := $value'); |
| 264 visit(node.body); | 242 visit(node.body); |
| 265 } | 243 } |
| 266 | 244 |
| 267 visitDeclareFunction(cps_ir.DeclareFunction node) { | |
| 268 String dummy = names.name(node); | |
| 269 String variable = names.name(node.variable); | |
| 270 printStmt(dummy, 'DeclareFunction $variable'); | |
| 271 visit(node.body); | |
| 272 } | |
| 273 | |
| 274 String formatReference(cps_ir.Reference ref) { | 245 String formatReference(cps_ir.Reference ref) { |
| 275 cps_ir.Definition target = ref.definition; | 246 cps_ir.Definition target = ref.definition; |
| 276 if (target is cps_ir.Continuation && target.isReturnContinuation) { | 247 if (target is cps_ir.Continuation && target.isReturnContinuation) { |
| 277 return "return"; // Do not generate a name for the return continuation | 248 return "return"; // Do not generate a name for the return continuation |
| 278 } else { | 249 } else { |
| 279 return names.name(ref.definition); | 250 return names.name(ref.definition); |
| 280 } | 251 } |
| 281 } | 252 } |
| 282 | 253 |
| 283 String formatPrimitive(cps_ir.Primitive p) => visit(p); | 254 String formatPrimitive(cps_ir.Primitive p) => visit(p); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 visitIdentical(cps_ir.Identical node) { | 322 visitIdentical(cps_ir.Identical node) { |
| 352 String left = formatReference(node.left); | 323 String left = formatReference(node.left); |
| 353 String right = formatReference(node.right); | 324 String right = formatReference(node.right); |
| 354 return "Identical($left, $right)"; | 325 return "Identical($left, $right)"; |
| 355 } | 326 } |
| 356 | 327 |
| 357 visitInterceptor(cps_ir.Interceptor node) { | 328 visitInterceptor(cps_ir.Interceptor node) { |
| 358 return "Interceptor(${formatReference(node.input)})"; | 329 return "Interceptor(${formatReference(node.input)})"; |
| 359 } | 330 } |
| 360 | 331 |
| 361 visitReifyTypeVar(cps_ir.ReifyTypeVar node) { | |
| 362 return "ReifyTypeVar ${node.typeVariable.name}"; | |
| 363 } | |
| 364 | |
| 365 visitCreateFunction(cps_ir.CreateFunction node) { | 332 visitCreateFunction(cps_ir.CreateFunction node) { |
| 366 return "CreateFunction ${node.definition.element.name}"; | 333 return "CreateFunction ${node.definition.element.name}"; |
| 367 } | 334 } |
| 368 | 335 |
| 369 visitGetMutableVariable(cps_ir.GetMutableVariable node) { | 336 visitGetMutableVariable(cps_ir.GetMutableVariable node) { |
| 370 String variable = names.name(node.variable.definition); | 337 String variable = names.name(node.variable.definition); |
| 371 return 'GetMutableVariable $variable'; | 338 return 'GetMutableVariable $variable'; |
| 372 } | 339 } |
| 373 | 340 |
| 374 visitReadTypeVariable(cps_ir.ReadTypeVariable node) { | 341 visitReadTypeVariable(cps_ir.ReadTypeVariable node) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 Block block = cont2block[c]; | 429 Block block = cont2block[c]; |
| 463 if (block == null) { | 430 if (block == null) { |
| 464 block = new Block(names.name(c), c.parameters, c.body); | 431 block = new Block(names.name(c), c.parameters, c.body); |
| 465 cont2block[c] = block; | 432 cont2block[c] = block; |
| 466 } | 433 } |
| 467 return block; | 434 return block; |
| 468 } | 435 } |
| 469 | 436 |
| 470 visit(cps_ir.Node node) => node.accept(this); | 437 visit(cps_ir.Node node) => node.accept(this); |
| 471 | 438 |
| 472 visitFieldDefinition(cps_ir.FieldDefinition node) { | |
| 473 visit(node.body); | |
| 474 } | |
| 475 | |
| 476 visitFunctionDefinition(cps_ir.FunctionDefinition node) { | 439 visitFunctionDefinition(cps_ir.FunctionDefinition node) { |
| 477 visit(node.body); | |
| 478 } | |
| 479 | |
| 480 visitConstructorDefinition(cps_ir.ConstructorDefinition node) { | |
| 481 node.initializers.forEach(visit); | |
| 482 visit(node.body); | |
| 483 } | |
| 484 | |
| 485 visitBody(cps_ir.Body node) { | |
| 486 currentBlock = new Block(names.name(node), [], node.body); | 440 currentBlock = new Block(names.name(node), [], node.body); |
| 487 entries.add(currentBlock); | 441 entries.add(currentBlock); |
| 488 visit(node.body); | 442 visit(node.body); |
| 489 } | 443 } |
| 490 | 444 |
| 491 visitFieldInitializer(cps_ir.FieldInitializer node) { | |
| 492 visit(node.body); | |
| 493 } | |
| 494 | |
| 495 visitSuperInitializer(cps_ir.SuperInitializer node) { | |
| 496 node.arguments.forEach(visit); | |
| 497 } | |
| 498 | |
| 499 visitLetPrim(cps_ir.LetPrim exp) { | 445 visitLetPrim(cps_ir.LetPrim exp) { |
| 500 visit(exp.body); | 446 visit(exp.body); |
| 501 } | 447 } |
| 502 | 448 |
| 503 visitLetCont(cps_ir.LetCont exp) { | 449 visitLetCont(cps_ir.LetCont exp) { |
| 504 exp.continuations.forEach(visit); | 450 exp.continuations.forEach(visit); |
| 505 visit(exp.body); | 451 visit(exp.body); |
| 506 } | 452 } |
| 507 | 453 |
| 508 visitLetHandler(cps_ir.LetHandler exp) { | 454 visitLetHandler(cps_ir.LetHandler exp) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 } | 506 } |
| 561 | 507 |
| 562 visitSetStatic(cps_ir.SetStatic exp) { | 508 visitSetStatic(cps_ir.SetStatic exp) { |
| 563 visit(exp.body); | 509 visit(exp.body); |
| 564 } | 510 } |
| 565 | 511 |
| 566 visitGetLazyStatic(cps_ir.GetLazyStatic exp) { | 512 visitGetLazyStatic(cps_ir.GetLazyStatic exp) { |
| 567 addEdgeToContinuation(exp.continuation); | 513 addEdgeToContinuation(exp.continuation); |
| 568 } | 514 } |
| 569 | 515 |
| 570 visitDeclareFunction(cps_ir.DeclareFunction exp) { | |
| 571 visit(exp.body); | |
| 572 } | |
| 573 | |
| 574 visitBranch(cps_ir.Branch exp) { | 516 visitBranch(cps_ir.Branch exp) { |
| 575 cps_ir.Continuation trueTarget = exp.trueContinuation.definition; | 517 cps_ir.Continuation trueTarget = exp.trueContinuation.definition; |
| 576 if (!trueTarget.isReturnContinuation) { | 518 if (!trueTarget.isReturnContinuation) { |
| 577 currentBlock.addEdgeTo(getBlock(trueTarget)); | 519 currentBlock.addEdgeTo(getBlock(trueTarget)); |
| 578 } | 520 } |
| 579 cps_ir.Continuation falseTarget = exp.falseContinuation.definition; | 521 cps_ir.Continuation falseTarget = exp.falseContinuation.definition; |
| 580 if (!falseTarget.isReturnContinuation) { | 522 if (!falseTarget.isReturnContinuation) { |
| 581 currentBlock.addEdgeTo(getBlock(falseTarget)); | 523 currentBlock.addEdgeTo(getBlock(falseTarget)); |
| 582 } | 524 } |
| 583 } | 525 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 601 | 543 |
| 602 visitLiteralList(cps_ir.LiteralList node) { | 544 visitLiteralList(cps_ir.LiteralList node) { |
| 603 unexpectedNode(node); | 545 unexpectedNode(node); |
| 604 } | 546 } |
| 605 visitLiteralMap(cps_ir.LiteralMap node) { | 547 visitLiteralMap(cps_ir.LiteralMap node) { |
| 606 unexpectedNode(node); | 548 unexpectedNode(node); |
| 607 } | 549 } |
| 608 visitConstant(cps_ir.Constant node) { | 550 visitConstant(cps_ir.Constant node) { |
| 609 unexpectedNode(node); | 551 unexpectedNode(node); |
| 610 } | 552 } |
| 611 visitReifyTypeVar(cps_ir.ReifyTypeVar node) { | |
| 612 unexpectedNode(node); | |
| 613 } | |
| 614 visitCreateFunction(cps_ir.CreateFunction node) { | 553 visitCreateFunction(cps_ir.CreateFunction node) { |
| 615 unexpectedNode(node); | 554 unexpectedNode(node); |
| 616 } | 555 } |
| 617 visitGetMutableVariable(cps_ir.GetMutableVariable node) { | 556 visitGetMutableVariable(cps_ir.GetMutableVariable node) { |
| 618 unexpectedNode(node); | 557 unexpectedNode(node); |
| 619 } | 558 } |
| 620 visitParameter(cps_ir.Parameter node) { | 559 visitParameter(cps_ir.Parameter node) { |
| 621 unexpectedNode(node); | 560 unexpectedNode(node); |
| 622 } | 561 } |
| 623 visitMutableVariable(cps_ir.MutableVariable node) { | 562 visitMutableVariable(cps_ir.MutableVariable node) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 } | 597 } |
| 659 | 598 |
| 660 visitNonTailThrow(cps_ir.NonTailThrow node) { | 599 visitNonTailThrow(cps_ir.NonTailThrow node) { |
| 661 unexpectedNode(node); | 600 unexpectedNode(node); |
| 662 } | 601 } |
| 663 | 602 |
| 664 visitCreateInvocationMirror(cps_ir.CreateInvocationMirror node) { | 603 visitCreateInvocationMirror(cps_ir.CreateInvocationMirror node) { |
| 665 unexpectedNode(node); | 604 unexpectedNode(node); |
| 666 } | 605 } |
| 667 } | 606 } |
| OLD | NEW |