| 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'; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 void traceGraph(String name, cps_ir.ExecutableDefinition graph) { | 24 void traceGraph(String name, cps_ir.ExecutableDefinition graph) { |
| 25 tag("cfg", () { | 25 tag("cfg", () { |
| 26 printProperty("name", name); | 26 printProperty("name", name); |
| 27 visit(graph); | 27 visit(graph); |
| 28 }); | 28 }); |
| 29 } | 29 } |
| 30 | 30 |
| 31 // Temporary field used during tree walk | 31 // Temporary field used during tree walk |
| 32 Names names; | 32 Names names; |
| 33 | 33 |
| 34 visitExecutableDefinition(cps_ir.ExecutableDefinition node) { | 34 printDefinition(cps_ir.ExecutableDefinition node) { |
| 35 names = new Names(); | 35 names = new Names(); |
| 36 BlockCollector builder = new BlockCollector(names); | 36 BlockCollector builder = new BlockCollector(names); |
| 37 builder.visit(node); | 37 builder.visit(node); |
| 38 | 38 |
| 39 for (Block block in builder.entries) { | 39 for (Block block in builder.entries) { |
| 40 printNode(block); | 40 printBlock(block); |
| 41 } | 41 } |
| 42 for (Block block in builder.cont2block.values) { | 42 for (Block block in builder.cont2block.values) { |
| 43 printNode(block); | 43 printBlock(block); |
| 44 } | 44 } |
| 45 names = null; | 45 names = null; |
| 46 } | 46 } |
| 47 | 47 |
| 48 visitFieldDefinition(cps_ir.FieldDefinition node) { | 48 visitFieldDefinition(cps_ir.FieldDefinition node) { |
| 49 if (node.hasInitializer) { | 49 if (node.hasInitializer) { |
| 50 visitExecutableDefinition(node); | 50 printDefinition(node); |
| 51 } | 51 } |
| 52 } | 52 } |
| 53 | 53 |
| 54 visitFunctionDefinition(cps_ir.FunctionDefinition node) { | 54 visitFunctionDefinition(cps_ir.FunctionDefinition node) { |
| 55 if (node.isAbstract) return; | 55 if (node.isAbstract) return; |
| 56 visitExecutableDefinition(node); | 56 printDefinition(node); |
| 57 } | 57 } |
| 58 | 58 |
| 59 visitConstructorDefinition(cps_ir.ConstructorDefinition node) { | 59 visitConstructorDefinition(cps_ir.ConstructorDefinition node) { |
| 60 if (node.isAbstract) return; | 60 if (node.isAbstract) return; |
| 61 visitExecutableDefinition(node); | 61 printDefinition(node); |
| 62 } |
| 63 |
| 64 // Bodies and initializers are not visited. They contain continuations which |
| 65 // are found by a BlockCollector, then those continuations are processed by |
| 66 // this visitor. |
| 67 unexpectedNode(cps_ir.Node node) { |
| 68 throw 'The IR tracer reached an unexpected IR instruction: $node'; |
| 69 } |
| 70 |
| 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); |
| 62 } | 79 } |
| 63 | 80 |
| 64 int countUses(cps_ir.Definition definition) { | 81 int countUses(cps_ir.Definition definition) { |
| 65 int count = 0; | 82 int count = 0; |
| 66 cps_ir.Reference ref = definition.firstRef; | 83 cps_ir.Reference ref = definition.firstRef; |
| 67 while (ref != null) { | 84 while (ref != null) { |
| 68 ++count; | 85 ++count; |
| 69 ref = ref.next; | 86 ref = ref.next; |
| 70 } | 87 } |
| 71 return count; | 88 return count; |
| 72 } | 89 } |
| 73 | 90 |
| 74 printNode(Block block) { | 91 printBlock(Block block) { |
| 75 tag("block", () { | 92 tag("block", () { |
| 76 printProperty("name", block.name); | 93 printProperty("name", block.name); |
| 77 printProperty("from_bci", -1); | 94 printProperty("from_bci", -1); |
| 78 printProperty("to_bci", -1); | 95 printProperty("to_bci", -1); |
| 79 printProperty("predecessors", block.pred.map((n) => n.name)); | 96 printProperty("predecessors", block.pred.map((n) => n.name)); |
| 80 printProperty("successors", block.succ.map((n) => n.name)); | 97 printProperty("successors", block.succ.map((n) => n.name)); |
| 81 printEmptyProperty("xhandlers"); | 98 printEmptyProperty("xhandlers"); |
| 82 printEmptyProperty("flags"); | 99 printEmptyProperty("flags"); |
| 83 tag("states", () { | 100 tag("states", () { |
| 84 tag("locals", () { | 101 tag("locals", () { |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 } | 330 } |
| 314 | 331 |
| 315 visitCreateFunction(cps_ir.CreateFunction node) { | 332 visitCreateFunction(cps_ir.CreateFunction node) { |
| 316 return "CreateFunction ${node.definition.element.name}"; | 333 return "CreateFunction ${node.definition.element.name}"; |
| 317 } | 334 } |
| 318 | 335 |
| 319 visitGetMutableVariable(cps_ir.GetMutableVariable node) { | 336 visitGetMutableVariable(cps_ir.GetMutableVariable node) { |
| 320 String variable = names.name(node.variable.definition); | 337 String variable = names.name(node.variable.definition); |
| 321 return '${node.runtimeType} $variable'; | 338 return '${node.runtimeType} $variable'; |
| 322 } | 339 } |
| 323 | |
| 324 visitRunnableBody(cps_ir.RunnableBody node) {} | |
| 325 visitFieldInitializer(cps_ir.FieldInitializer node) {} | |
| 326 visitSuperInitializer(cps_ir.SuperInitializer node) {} | |
| 327 visitCondition(cps_ir.Condition c) {} | |
| 328 visitExpression(cps_ir.Expression e) {} | |
| 329 visitPrimitive(cps_ir.Primitive p) {} | |
| 330 visitDefinition(cps_ir.Definition d) {} | |
| 331 visitInitializer(cps_ir.Initializer i) {} | |
| 332 visitNode(cps_ir.Node n) {} | |
| 333 } | 340 } |
| 334 | 341 |
| 335 /** | 342 /** |
| 336 * Invents (and remembers) names for Continuations, Parameters, etc. | 343 * Invents (and remembers) names for Continuations, Parameters, etc. |
| 337 * The names must match the conventions used by IR Hydra, e.g. | 344 * The names must match the conventions used by IR Hydra, e.g. |
| 338 * Continuations and Functions must have names of form B### since they | 345 * Continuations and Functions must have names of form B### since they |
| 339 * are visualized as basic blocks. | 346 * are visualized as basic blocks. |
| 340 */ | 347 */ |
| 341 class Names { | 348 class Names { |
| 342 final Map<Object, String> names = {}; | 349 final Map<Object, String> names = {}; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 final List<Block> pred = <Block>[]; | 385 final List<Block> pred = <Block>[]; |
| 379 | 386 |
| 380 Block(this.name, this.parameters, this.body); | 387 Block(this.name, this.parameters, this.body); |
| 381 | 388 |
| 382 void addEdgeTo(Block successor) { | 389 void addEdgeTo(Block successor) { |
| 383 succ.add(successor); | 390 succ.add(successor); |
| 384 successor.pred.add(this); | 391 successor.pred.add(this); |
| 385 } | 392 } |
| 386 } | 393 } |
| 387 | 394 |
| 388 class BlockCollector extends cps_ir.Visitor { | 395 class BlockCollector implements cps_ir.Visitor { |
| 389 final Map<cps_ir.Continuation, Block> cont2block = | 396 final Map<cps_ir.Continuation, Block> cont2block = |
| 390 <cps_ir.Continuation, Block>{}; | 397 <cps_ir.Continuation, Block>{}; |
| 391 final Set<Block> entries = new Set<Block>(); | 398 final Set<Block> entries = new Set<Block>(); |
| 392 Block current_block; | 399 Block current_block; |
| 393 | 400 |
| 394 Names names; | 401 Names names; |
| 395 BlockCollector(this.names); | 402 BlockCollector(this.names); |
| 396 | 403 |
| 397 Block getBlock(cps_ir.Continuation c) { | 404 Block getBlock(cps_ir.Continuation c) { |
| 398 Block block = cont2block[c]; | 405 Block block = cont2block[c]; |
| 399 if (block == null) { | 406 if (block == null) { |
| 400 block = new Block(names.name(c), c.parameters, c.body); | 407 block = new Block(names.name(c), c.parameters, c.body); |
| 401 cont2block[c] = block; | 408 cont2block[c] = block; |
| 402 } | 409 } |
| 403 return block; | 410 return block; |
| 404 } | 411 } |
| 405 | 412 |
| 413 visit(cps_ir.Node node) => node.accept(this); |
| 414 |
| 415 visitFieldDefinition(cps_ir.FieldDefinition node) { |
| 416 if (node.hasInitializer) { |
| 417 visit(node.body); |
| 418 } |
| 419 } |
| 420 |
| 421 visitFunctionDefinition(cps_ir.FunctionDefinition node) { |
| 422 visit(node.body); |
| 423 } |
| 424 |
| 425 visitConstructorDefinition(cps_ir.ConstructorDefinition node) { |
| 426 visit(node.body); |
| 427 } |
| 428 |
| 406 visitRunnableBody(cps_ir.RunnableBody node) { | 429 visitRunnableBody(cps_ir.RunnableBody node) { |
| 407 current_block = new Block(names.name(node), [], node.body); | 430 current_block = new Block(names.name(node), [], node.body); |
| 408 entries.add(current_block); | 431 entries.add(current_block); |
| 409 visit(node.body); | 432 visit(node.body); |
| 410 } | 433 } |
| 411 | 434 |
| 412 visitFieldInitializer(cps_ir.FieldInitializer node) { | 435 visitFieldInitializer(cps_ir.FieldInitializer node) { |
| 413 visit(node.body); | 436 visit(node.body); |
| 414 } | 437 } |
| 415 | 438 |
| 416 visitSuperInitializer(cps_ir.SuperInitializer node) { | 439 visitSuperInitializer(cps_ir.SuperInitializer node) { |
| 417 node.arguments.forEach(visit); | 440 node.arguments.forEach(visit); |
| 418 } | 441 } |
| 419 | 442 |
| 420 visitExecutableDefinition(cps_ir.ExecutableDefinition node) { | |
| 421 visit(node.body); | |
| 422 } | |
| 423 | |
| 424 visitFieldDefinition(cps_ir.FieldDefinition node) { | |
| 425 if (node.hasInitializer) { | |
| 426 visitExecutableDefinition(node); | |
| 427 } | |
| 428 } | |
| 429 | |
| 430 visitFunctionDefinition(cps_ir.FunctionDefinition node) { | |
| 431 visitExecutableDefinition(node); | |
| 432 } | |
| 433 | |
| 434 visitConstructorDefinition(cps_ir.ConstructorDefinition node) { | |
| 435 visitExecutableDefinition(node); | |
| 436 } | |
| 437 | |
| 438 visitLetPrim(cps_ir.LetPrim exp) { | 443 visitLetPrim(cps_ir.LetPrim exp) { |
| 439 visit(exp.body); | 444 visit(exp.body); |
| 440 } | 445 } |
| 441 | 446 |
| 442 visitLetCont(cps_ir.LetCont exp) { | 447 visitLetCont(cps_ir.LetCont exp) { |
| 443 exp.continuations.forEach(visit); | 448 exp.continuations.forEach(visit); |
| 444 visit(exp.body); | 449 visit(exp.body); |
| 445 } | 450 } |
| 446 | 451 |
| 447 visitLetHandler(cps_ir.LetHandler exp) { | 452 visitLetHandler(cps_ir.LetHandler exp) { |
| 448 visit(exp.handler); | 453 visit(exp.handler); |
| 449 visit(exp.body); | 454 visit(exp.body); |
| 450 } | 455 } |
| 451 | 456 |
| 452 visitLetMutable(cps_ir.LetMutable exp) { | 457 visitLetMutable(cps_ir.LetMutable exp) { |
| 453 visit(exp.body); | 458 visit(exp.body); |
| 454 } | 459 } |
| 455 | 460 |
| 456 void addEdgeToContinuation(cps_ir.Reference continuation) { | 461 void addEdgeToContinuation(cps_ir.Reference continuation) { |
| 457 cps_ir.Definition target = continuation.definition; | 462 cps_ir.Definition target = continuation.definition; |
| 458 if (target is cps_ir.Continuation && !target.isReturnContinuation) { | 463 if (target is cps_ir.Continuation && !target.isReturnContinuation) { |
| 459 current_block.addEdgeTo(getBlock(target)); | 464 current_block.addEdgeTo(getBlock(target)); |
| 460 } | 465 } |
| 461 } | 466 } |
| 462 | 467 |
| 468 visitInvokeContinuation(cps_ir.InvokeContinuation exp) { |
| 469 addEdgeToContinuation(exp.continuation); |
| 470 } |
| 471 |
| 463 visitInvokeStatic(cps_ir.InvokeStatic exp) { | 472 visitInvokeStatic(cps_ir.InvokeStatic exp) { |
| 464 addEdgeToContinuation(exp.continuation); | 473 addEdgeToContinuation(exp.continuation); |
| 465 } | 474 } |
| 466 | 475 |
| 467 visitInvokeMethod(cps_ir.InvokeMethod exp) { | 476 visitInvokeMethod(cps_ir.InvokeMethod exp) { |
| 468 addEdgeToContinuation(exp.continuation); | 477 addEdgeToContinuation(exp.continuation); |
| 469 } | 478 } |
| 470 | 479 |
| 480 visitInvokeMethodDirectly(cps_ir.InvokeMethodDirectly exp) { |
| 481 addEdgeToContinuation(exp.continuation); |
| 482 } |
| 483 |
| 471 visitInvokeConstructor(cps_ir.InvokeConstructor exp) { | 484 visitInvokeConstructor(cps_ir.InvokeConstructor exp) { |
| 472 addEdgeToContinuation(exp.continuation); | 485 addEdgeToContinuation(exp.continuation); |
| 473 } | 486 } |
| 474 | 487 |
| 475 visitConcatenateStrings(cps_ir.ConcatenateStrings exp) { | 488 visitConcatenateStrings(cps_ir.ConcatenateStrings exp) { |
| 476 addEdgeToContinuation(exp.continuation); | 489 addEdgeToContinuation(exp.continuation); |
| 477 } | 490 } |
| 478 | 491 |
| 479 visitInvokeContinuation(cps_ir.InvokeContinuation exp) { | |
| 480 addEdgeToContinuation(exp.continuation); | |
| 481 } | |
| 482 | |
| 483 visitSetMutableVariable(cps_ir.SetMutableVariable exp) { | 492 visitSetMutableVariable(cps_ir.SetMutableVariable exp) { |
| 484 visit(exp.body); | 493 visit(exp.body); |
| 485 } | 494 } |
| 486 | 495 |
| 487 visitSetField(cps_ir.SetField exp) { | 496 visitSetField(cps_ir.SetField exp) { |
| 488 visit(exp.body); | 497 visit(exp.body); |
| 489 } | 498 } |
| 490 | 499 |
| 491 visitDeclareFunction(cps_ir.DeclareFunction exp) { | 500 visitDeclareFunction(cps_ir.DeclareFunction exp) { |
| 492 visit(exp.body); | 501 visit(exp.body); |
| 493 } | 502 } |
| 494 | 503 |
| 495 visitBranch(cps_ir.Branch exp) { | 504 visitBranch(cps_ir.Branch exp) { |
| 496 cps_ir.Continuation trueTarget = exp.trueContinuation.definition; | 505 cps_ir.Continuation trueTarget = exp.trueContinuation.definition; |
| 497 if (!trueTarget.isReturnContinuation) { | 506 if (!trueTarget.isReturnContinuation) { |
| 498 current_block.addEdgeTo(getBlock(trueTarget)); | 507 current_block.addEdgeTo(getBlock(trueTarget)); |
| 499 } | 508 } |
| 500 cps_ir.Continuation falseTarget = exp.falseContinuation.definition; | 509 cps_ir.Continuation falseTarget = exp.falseContinuation.definition; |
| 501 if (!falseTarget.isReturnContinuation) { | 510 if (!falseTarget.isReturnContinuation) { |
| 502 current_block.addEdgeTo(getBlock(falseTarget)); | 511 current_block.addEdgeTo(getBlock(falseTarget)); |
| 503 } | 512 } |
| 504 } | 513 } |
| 505 | 514 |
| 515 visitTypeOperator(cps_ir.TypeOperator exp) { |
| 516 addEdgeToContinuation(exp.continuation); |
| 517 } |
| 518 |
| 506 visitContinuation(cps_ir.Continuation c) { | 519 visitContinuation(cps_ir.Continuation c) { |
| 507 var old_node = current_block; | 520 var old_node = current_block; |
| 508 current_block = getBlock(c); | 521 current_block = getBlock(c); |
| 509 visit(c.body); | 522 visit(c.body); |
| 510 current_block = old_node; | 523 current_block = old_node; |
| 511 } | 524 } |
| 525 |
| 526 // Primitives and conditions are not visited when searching for blocks. |
| 527 unexpectedNode(cps_ir.Node node) { |
| 528 throw "The IR tracer's block collector reached an unexpected IR " |
| 529 "instruction: $node"; |
| 530 } |
| 531 |
| 532 visitLiteralList(cps_ir.LiteralList node) { |
| 533 unexpectedNode(node); |
| 534 } |
| 535 visitLiteralMap(cps_ir.LiteralMap node) { |
| 536 unexpectedNode(node); |
| 537 } |
| 538 visitConstant(cps_ir.Constant node) { |
| 539 unexpectedNode(node); |
| 540 } |
| 541 visitThis(cps_ir.This node) { |
| 542 unexpectedNode(node); |
| 543 } |
| 544 visitReifyTypeVar(cps_ir.ReifyTypeVar node) { |
| 545 unexpectedNode(node); |
| 546 } |
| 547 visitCreateFunction(cps_ir.CreateFunction node) { |
| 548 unexpectedNode(node); |
| 549 } |
| 550 visitGetMutableVariable(cps_ir.GetMutableVariable node) { |
| 551 unexpectedNode(node); |
| 552 } |
| 553 visitParameter(cps_ir.Parameter node) { |
| 554 unexpectedNode(node); |
| 555 } |
| 556 visitMutableVariable(cps_ir.MutableVariable node) { |
| 557 unexpectedNode(node); |
| 558 } |
| 559 visitGetField(cps_ir.GetField node) { |
| 560 unexpectedNode(node); |
| 561 } |
| 562 visitCreateBox(cps_ir.CreateBox node) { |
| 563 unexpectedNode(node); |
| 564 } |
| 565 visitCreateInstance(cps_ir.CreateInstance node) { |
| 566 unexpectedNode(node); |
| 567 } |
| 568 visitIsTrue(cps_ir.IsTrue node) { |
| 569 unexpectedNode(node); |
| 570 } |
| 571 visitIdentical(cps_ir.Identical node) { |
| 572 unexpectedNode(node); |
| 573 } |
| 574 visitInterceptor(cps_ir.Interceptor node) { |
| 575 unexpectedNode(node); |
| 576 } |
| 512 } | 577 } |
| OLD | NEW |