Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: pkg/compiler/lib/src/tree_ir/tree_ir_tracer.dart

Issue 2246623002: Delete CPS IR (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library tree_ir_tracer;
6
7 import 'dart:async' show EventSink;
8
9 import '../tracer.dart';
10 import 'tree_ir_nodes.dart';
11
12 class Block {
13 Label label;
14 int index;
15
16 /// Mixed list of [Statement] and [Block].
17 /// A [Block] represents a synthetic goto statement.
18 final List statements = [];
19 final List<Block> predecessors = <Block>[];
20 final List<Block> successors = <Block>[];
21
22 /// The catch block associated with the immediately enclosing try block or
23 /// `null` if not inside a try block.
24 Block catcher;
25
26 /// True if this block is the entry point to one of the bodies
27 /// (constructors can have multiple bodies).
28 bool isEntryPoint = false;
29
30 String get name => 'B$index';
31
32 Block([this.label]);
33
34 void addEdgeTo(Block successor) {
35 successors.add(successor);
36 successor.predecessors.add(this);
37 }
38 }
39
40 class BlockCollector extends StatementVisitor {
41 // Accumulate a list of blocks. The current block is the last block in
42 // the list.
43 final List<Block> blocks = [];
44
45 // Map tree [Label]s (break or continue targets) and [Statement]s
46 // (if targets) to blocks.
47 final Map<Label, Block> breakTargets = <Label, Block>{};
48 final Map<Label, Block> continueTargets = <Label, Block>{};
49 final Map<Statement, Block> substatements = <Statement, Block>{};
50
51 Block catcher;
52
53 void _addStatement(Statement statement) {
54 blocks.last.statements.add(statement);
55 }
56
57 void _addGotoStatement(Block target) {
58 blocks.last.statements.add(target);
59 }
60
61 void _addBlock(Block block) {
62 block.index = blocks.length;
63 block.catcher = catcher;
64 blocks.add(block);
65 }
66
67 void collect(FunctionDefinition node) {
68 _addBlock(new Block()..isEntryPoint = true);
69 visitStatement(node.body);
70 }
71
72 visitLabeledStatement(LabeledStatement node) {
73 Block target = new Block(node.label);
74 breakTargets[node.label] = target;
75 visitStatement(node.body);
76 _addBlock(target);
77 visitStatement(node.next);
78 }
79
80 visitReturn(Return node) {
81 _addStatement(node);
82 }
83
84 visitThrow(Throw node) {
85 _addStatement(node);
86 }
87
88 visitUnreachable(Unreachable node) {
89 _addStatement(node);
90 }
91
92 visitBreak(Break node) {
93 _addStatement(node);
94 if (breakTargets.containsKey(node.target)) {
95 blocks.last.addEdgeTo(breakTargets[node.target]);
96 }
97 }
98
99 visitContinue(Continue node) {
100 _addStatement(node);
101 blocks.last.addEdgeTo(continueTargets[node.target]);
102 }
103
104 visitIf(If node) {
105 _addStatement(node);
106 Block thenTarget = new Block();
107 Block elseTarget = new Block();
108 substatements[node.thenStatement] = thenTarget;
109 substatements[node.elseStatement] = elseTarget;
110 blocks.last.addEdgeTo(thenTarget);
111 blocks.last.addEdgeTo(elseTarget);
112 _addBlock(thenTarget);
113 visitStatement(node.thenStatement);
114 _addBlock(elseTarget);
115 visitStatement(node.elseStatement);
116 }
117
118 visitWhileTrue(WhileTrue node) {
119 Block continueTarget = new Block();
120 _addGotoStatement(continueTarget);
121
122 continueTargets[node.label] = continueTarget;
123 blocks.last.addEdgeTo(continueTarget);
124 _addBlock(continueTarget);
125 _addStatement(node);
126 visitStatement(node.body);
127 }
128
129 visitFor(For node) {
130 Block whileBlock = new Block();
131 _addGotoStatement(whileBlock);
132
133 _addBlock(whileBlock);
134 _addStatement(node);
135 blocks.last.addEdgeTo(whileBlock);
136
137 Block bodyBlock = new Block();
138 Block nextBlock = new Block();
139 whileBlock.addEdgeTo(bodyBlock);
140 whileBlock.addEdgeTo(nextBlock);
141
142 continueTargets[node.label] = bodyBlock;
143 _addBlock(bodyBlock);
144 visitStatement(node.body);
145
146 _addBlock(nextBlock);
147 visitStatement(node.next);
148
149 substatements[node.body] = bodyBlock;
150 substatements[node.next] = nextBlock;
151 }
152
153 visitTry(Try node) {
154 _addStatement(node);
155 Block tryBlock = new Block();
156 Block catchBlock = new Block();
157
158 Block oldCatcher = catcher;
159 catcher = catchBlock;
160 _addBlock(tryBlock);
161 visitStatement(node.tryBody);
162 catcher = oldCatcher;
163
164 _addBlock(catchBlock);
165 visitStatement(node.catchBody);
166
167 substatements[node.tryBody] = tryBlock;
168 substatements[node.catchBody] = catchBlock;
169 }
170
171 visitExpressionStatement(ExpressionStatement node) {
172 _addStatement(node);
173 visitStatement(node.next);
174 }
175
176 visitForeignStatement(ForeignStatement node) {
177 _addStatement(node);
178 }
179
180 visitYield(Yield node) {
181 _addStatement(node);
182 visitStatement(node.next);
183 }
184
185 visitReceiverCheck(ReceiverCheck node) {
186 _addStatement(node);
187 visitStatement(node.next);
188 }
189 }
190
191 class TreeTracer extends TracerUtil with StatementVisitor {
192 String get passName => null;
193
194 final EventSink<String> output;
195
196 TreeTracer(this.output);
197
198 List<Variable> parameters;
199 Names names;
200 BlockCollector collector;
201 int statementCounter;
202
203 void traceGraph(String name, FunctionDefinition node) {
204 parameters = node.parameters;
205 tag("cfg", () {
206 printProperty("name", name);
207 names = new Names();
208 statementCounter = 0;
209 collector = new BlockCollector();
210 collector.collect(node);
211 collector.blocks.forEach(printBlock);
212 });
213 }
214
215 void printBlock(Block block) {
216 tag("block", () {
217 printProperty("name", block.name);
218 printProperty("from_bci", -1);
219 printProperty("to_bci", -1);
220 printProperty("predecessors", block.predecessors.map((b) => b.name));
221 printProperty("successors", block.successors.map((b) => b.name));
222 printEmptyProperty("xhandlers");
223 printEmptyProperty("flags");
224 tag("states", () {
225 tag("locals", () {
226 printProperty("size", 0);
227 printProperty("method", "None");
228 });
229 });
230 tag("HIR", () {
231 if (block.isEntryPoint) {
232 String params = parameters.map(names.varName).join(', ');
233 printStatement(null, 'Entry ($params)');
234 }
235 if (block.label != null) {
236 printStatement(
237 null, "Label ${block.name}, useCount=${block.label.useCount}");
238 }
239 if (block.catcher != null) {
240 printStatement(null, 'Catch exceptions at ${block.catcher.name}');
241 }
242 block.statements.forEach(visitBlockMember);
243 });
244 });
245 }
246
247 void visitBlockMember(member) {
248 if (member is Block) {
249 printStatement(null, "goto block B${member.name}");
250 } else {
251 assert(member is Statement);
252 visitStatement(member);
253 }
254 }
255
256 void printStatement(String name, String contents) {
257 int bci = 0;
258 int uses = 0;
259 if (name == null) {
260 name = 'x${statementCounter++}';
261 }
262 addIndent();
263 add("$bci $uses $name $contents <|@\n");
264 }
265
266 visitLabeledStatement(LabeledStatement node) {
267 // These do not get added to a block's list of statements.
268 }
269
270 visitReturn(Return node) {
271 printStatement(null, "return ${expr(node.value)}");
272 }
273
274 visitThrow(Throw node) {
275 printStatement(null, "throw ${expr(node.value)}");
276 }
277
278 visitUnreachable(Unreachable node) {
279 printStatement(null, "unreachable");
280 }
281
282 visitBreak(Break node) {
283 Block block = collector.breakTargets[node.target];
284 String name = block != null ? block.name : '<missing label>';
285 printStatement(null, "break $name");
286 }
287
288 visitContinue(Continue node) {
289 printStatement(
290 null, "continue ${collector.continueTargets[node.target].name}");
291 }
292
293 visitIf(If node) {
294 String condition = expr(node.condition);
295 String thenTarget = collector.substatements[node.thenStatement].name;
296 String elseTarget = collector.substatements[node.elseStatement].name;
297 printStatement(null, "if $condition then $thenTarget else $elseTarget");
298 }
299
300 visitWhileTrue(WhileTrue node) {
301 printStatement(null, "while true do");
302 }
303
304 visitFor(For node) {
305 String bodyTarget = collector.substatements[node.body].name;
306 String nextTarget = collector.substatements[node.next].name;
307 String updates = node.updates.map(expr).join(', ');
308 printStatement(null, "while ${expr(node.condition)}");
309 printStatement(null, "do $bodyTarget");
310 printStatement(null, "updates ($updates)");
311 printStatement(null, "then $nextTarget");
312 }
313
314 visitTry(Try node) {
315 String tryTarget = collector.substatements[node.tryBody].name;
316 String catchParams = node.catchParameters.map(names.varName).join(',');
317 String catchTarget = collector.substatements[node.catchBody].name;
318 printStatement(null, 'try $tryTarget catch($catchParams) $catchTarget');
319 }
320
321 visitExpressionStatement(ExpressionStatement node) {
322 printStatement(null, expr(node.expression));
323 }
324
325 visitSetField(SetField node) {
326 String object = expr(node.object);
327 String field = node.field.name;
328 String value = expr(node.value);
329 if (SubexpressionVisitor.usesInfixNotation(node.object)) {
330 object = '($object)';
331 }
332 printStatement(null, '$object.$field = $value');
333 }
334
335 String expr(Expression e) {
336 return e.accept(new SubexpressionVisitor(names));
337 }
338
339 @override
340 visitForeignStatement(ForeignStatement node) {
341 printStatement(null, 'foreign ${node.codeTemplate.source}');
342 }
343
344 @override
345 visitYield(Yield node) {
346 String name = node.hasStar ? 'yield*' : 'yield';
347 printStatement(null, '$name ${expr(node.input)}');
348 }
349
350 @override
351 visitReceiverCheck(ReceiverCheck node) {
352 printStatement(null, 'NullCheck ${expr(node.value)}');
353 }
354 }
355
356 class SubexpressionVisitor extends ExpressionVisitor<String> {
357 Names names;
358
359 SubexpressionVisitor(this.names);
360
361 String visitVariableUse(VariableUse node) {
362 return names.varName(node.variable);
363 }
364
365 String visitAssign(Assign node) {
366 String variable = names.varName(node.variable);
367 String value = visitExpression(node.value);
368 return '$variable = $value';
369 }
370
371 String formatArguments(Invoke node) {
372 return node.arguments.map(visitExpression).join(', ');
373 }
374
375 String visitInvokeStatic(InvokeStatic node) {
376 String head = node.target.name;
377 String args = formatArguments(node);
378 return "$head($args)";
379 }
380
381 String visitInvokeMethod(InvokeMethod node) {
382 String receiver = node.receiver.accept(this);
383 String name = node.selector.name;
384 String args = formatArguments(node);
385 return "$receiver.$name($args)";
386 }
387
388 String visitInvokeMethodDirectly(InvokeMethodDirectly node) {
389 String receiver = visitExpression(node.receiver);
390 String host = node.target.enclosingClass.name;
391 String name = node.selector.name;
392 String args = formatArguments(node);
393 return "$receiver.$host::$name($args)";
394 }
395
396 String visitInvokeConstructor(InvokeConstructor node) {
397 String className = node.target.enclosingClass.name;
398 String callName;
399 if (node.target.name.isEmpty) {
400 callName = '${className}';
401 } else {
402 callName = '${className}.${node.target.name}';
403 }
404 String args = formatArguments(node);
405 String keyword = node.constant != null ? 'const' : 'new';
406 return "$keyword $callName($args)";
407 }
408
409 String visitOneShotInterceptor(OneShotInterceptor node) {
410 String name = node.selector.name;
411 String args = formatArguments(node);
412 return "oneshot $name($args)";
413 }
414
415 String visitLiteralList(LiteralList node) {
416 String values = node.values.map(visitExpression).join(', ');
417 return "list [$values]";
418 }
419
420 String visitConstant(Constant node) {
421 return "${node.value.toStructuredText()}";
422 }
423
424 String visitThis(This node) {
425 return "this";
426 }
427
428 static bool usesInfixNotation(Expression node) {
429 return node is Conditional ||
430 node is LogicalOperator ||
431 node is Assign ||
432 node is SetField;
433 }
434
435 String visitConditional(Conditional node) {
436 String condition = visitExpression(node.condition);
437 String thenExpr = visitExpression(node.thenExpression);
438 String elseExpr = visitExpression(node.elseExpression);
439 return "$condition ? $thenExpr : $elseExpr";
440 }
441
442 String visitLogicalOperator(LogicalOperator node) {
443 String left = visitExpression(node.left);
444 String right = visitExpression(node.right);
445 if (usesInfixNotation(node.left)) {
446 left = "($left)";
447 }
448 if (usesInfixNotation(node.right)) {
449 right = "($right)";
450 }
451 return "$left ${node.operator} $right";
452 }
453
454 String visitTypeOperator(TypeOperator node) {
455 String value = visitExpression(node.value);
456 String type = "${node.type}";
457 return "TypeOperator $value ${node.operator} $type";
458 }
459
460 String visitNot(Not node) {
461 String operand = visitExpression(node.operand);
462 if (usesInfixNotation(node.operand)) {
463 operand = '($operand)';
464 }
465 return '!$operand';
466 }
467
468 String visitGetField(GetField node) {
469 String object = visitExpression(node.object);
470 String field = node.field.name;
471 if (usesInfixNotation(node.object)) {
472 object = '($object)';
473 }
474 return '$object.$field';
475 }
476
477 String visitSetField(SetField node) {
478 String object = visitExpression(node.object);
479 String field = node.field.name;
480 if (usesInfixNotation(node.object)) {
481 object = '($object)';
482 }
483 String value = visitExpression(node.value);
484 return '$object.$field = $value';
485 }
486
487 String visitGetStatic(GetStatic node) {
488 String element = node.element.name;
489 return element;
490 }
491
492 String visitSetStatic(SetStatic node) {
493 String element = node.element.name;
494 String value = visitExpression(node.value);
495 return '$element = $value';
496 }
497
498 String visitGetTypeTestProperty(GetTypeTestProperty node) {
499 String object = visitExpression(node.object);
500 if (usesInfixNotation(node.object)) {
501 object = '($object)';
502 }
503 // TODO(sra): Fix up this.
504 return '$object."is-${node.dartType}"';
505 }
506
507 String visitCreateBox(CreateBox node) {
508 return 'CreateBox';
509 }
510
511 String visitCreateInstance(CreateInstance node) {
512 String className = node.classElement.name;
513 String arguments = node.arguments.map(visitExpression).join(', ');
514 return 'CreateInstance $className($arguments)';
515 }
516
517 @override
518 String visitReadTypeVariable(ReadTypeVariable node) {
519 return 'Read ${node.variable.element} ${visitExpression(node.target)}';
520 }
521
522 @override
523 String visitReifyRuntimeType(ReifyRuntimeType node) {
524 return 'Reify ${node.value}';
525 }
526
527 @override
528 String visitTypeExpression(TypeExpression node) {
529 String kind = '${node.kind}'.split('.').last;
530 String args = node.arguments.map(visitExpression).join(', ');
531 return 'TypeExpression($kind, ${node.dartType}, $args)';
532 }
533
534 @override
535 String visitCreateInvocationMirror(CreateInvocationMirror node) {
536 String args = node.arguments.map(visitExpression).join(', ');
537 return 'CreateInvocationMirror(${node.selector.name}, $args)';
538 }
539
540 @override
541 String visitInterceptor(Interceptor node) {
542 return 'Interceptor(${visitExpression(node.input)})';
543 }
544
545 @override
546 String visitForeignExpression(ForeignExpression node) {
547 String arguments = node.arguments.map(visitExpression).join(', ');
548 return 'Foreign "${node.codeTemplate.source}"($arguments)';
549 }
550
551 @override
552 String visitApplyBuiltinOperator(ApplyBuiltinOperator node) {
553 String args = node.arguments.map(visitExpression).join(', ');
554 return 'ApplyBuiltinOperator ${node.operator} ($args)';
555 }
556
557 @override
558 String visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
559 String receiver = visitExpression(node.receiver);
560 String args = node.arguments.map(visitExpression).join(', ');
561 return 'ApplyBuiltinMethod ${node.method} $receiver ($args)';
562 }
563
564 @override
565 String visitGetLength(GetLength node) {
566 String object = visitExpression(node.object);
567 return 'GetLength($object)';
568 }
569
570 @override
571 String visitGetIndex(GetIndex node) {
572 String object = visitExpression(node.object);
573 String index = visitExpression(node.index);
574 return 'GetIndex($object, $index)';
575 }
576
577 @override
578 String visitSetIndex(SetIndex node) {
579 String object = visitExpression(node.object);
580 String index = visitExpression(node.index);
581 String value = visitExpression(node.value);
582 return 'SetIndex($object, $index, $value)';
583 }
584
585 @override
586 String visitAwait(Await node) {
587 String value = visitExpression(node.input);
588 return 'Await($value)';
589 }
590
591 String visitYield(Yield node) {
592 String value = visitExpression(node.input);
593 return 'Yield($value)';
594 }
595 }
596
597 /**
598 * Invents (and remembers) names for Variables that do not have an associated
599 * identifier.
600 *
601 * In case a variable is named v0, v1, etc, it may be assigned a different
602 * name to avoid clashing with a previously synthesized variable name.
603 */
604 class Names {
605 final Map<Variable, String> _names = {};
606 final Set<String> _usedNames = new Set();
607 int _counter = 0;
608
609 String varName(Variable v) {
610 String name = _names[v];
611 if (name == null) {
612 String prefix = v.element == null ? 'v' : '${v.element.name}_';
613 while (name == null || _usedNames.contains(name)) {
614 name = "$prefix${_counter++}";
615 }
616 _names[v] = name;
617 _usedNames.add(name);
618 }
619 return name;
620 }
621 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart ('k') | pkg/compiler/lib/src/use_unused_api.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698