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 |