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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/ssa_tracer.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013, 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 ssa.tracer;
6
7 import 'dart:async' show EventSink;
8
9 import 'ssa.dart';
10 import '../js_backend/js_backend.dart';
11 import '../dart2jslib.dart';
12 import '../tracer.dart';
13
14 /**
15 * Outputs SSA code in a format readable by Hydra IR.
16 * Tracing is disabled by default, see ../tracer.dart for how
17 * to enable it.
18 */
19 class HTracer extends HGraphVisitor with TracerUtil {
20 Compiler compiler;
21 JavaScriptItemCompilationContext context;
22 final EventSink<String> output;
23
24 HTracer(this.output, this.compiler, this.context);
25
26 void traceGraph(String name, HGraph graph) {
27 DEBUG_MODE = true;
28 tag("cfg", () {
29 printProperty("name", name);
30 visitDominatorTree(graph);
31 });
32 }
33
34 void addPredecessors(HBasicBlock block) {
35 if (block.predecessors.isEmpty) {
36 printEmptyProperty("predecessors");
37 } else {
38 addIndent();
39 add("predecessors");
40 for (HBasicBlock predecessor in block.predecessors) {
41 add(' "B${predecessor.id}"');
42 }
43 add("\n");
44 }
45 }
46
47 void addSuccessors(HBasicBlock block) {
48 if (block.successors.isEmpty) {
49 printEmptyProperty("successors");
50 } else {
51 addIndent();
52 add("successors");
53 for (HBasicBlock successor in block.successors) {
54 add(' "B${successor.id}"');
55 }
56 add("\n");
57 }
58 }
59
60 void addInstructions(HInstructionStringifier stringifier,
61 HInstructionList list) {
62 for (HInstruction instruction = list.first;
63 instruction != null;
64 instruction = instruction.next) {
65 int bci = 0;
66 int uses = instruction.usedBy.length;
67 String changes = instruction.sideEffects.hasSideEffects() ? '!' : ' ';
68 String depends = instruction.sideEffects.dependsOnSomething() ? '?' : '';
69 addIndent();
70 String temporaryId = stringifier.temporaryId(instruction);
71 String instructionString = stringifier.visit(instruction);
72 add("$bci $uses $temporaryId $instructionString $changes $depends <|@\n");
73 }
74 }
75
76 void visitBasicBlock(HBasicBlock block) {
77 HInstructionStringifier stringifier =
78 new HInstructionStringifier(context, block, compiler);
79 assert(block.id != null);
80 tag("block", () {
81 printProperty("name", "B${block.id}");
82 printProperty("from_bci", -1);
83 printProperty("to_bci", -1);
84 addPredecessors(block);
85 addSuccessors(block);
86 printEmptyProperty("xhandlers");
87 printEmptyProperty("flags");
88 if (block.dominator != null) {
89 printProperty("dominator", "B${block.dominator.id}");
90 }
91 tag("states", () {
92 tag("locals", () {
93 printProperty("size", 0);
94 printProperty("method", "None");
95 block.forEachPhi((phi) {
96 String phiId = stringifier.temporaryId(phi);
97 StringBuffer inputIds = new StringBuffer();
98 for (int i = 0; i < phi.inputs.length; i++) {
99 inputIds.write(stringifier.temporaryId(phi.inputs[i]));
100 inputIds.write(" ");
101 }
102 println("${phi.id} $phiId [ $inputIds]");
103 });
104 });
105 });
106 tag("HIR", () {
107 addInstructions(stringifier, block.phis);
108 addInstructions(stringifier, block);
109 });
110 });
111 }
112 }
113
114 class HInstructionStringifier implements HVisitor<String> {
115 final Compiler compiler;
116 final JavaScriptItemCompilationContext context;
117 final HBasicBlock currentBlock;
118
119 HInstructionStringifier(this.context, this.currentBlock, this.compiler);
120
121 visit(HInstruction node) => '${node.accept(this)} ${node.instructionType}';
122
123 String temporaryId(HInstruction instruction) {
124 String prefix;
125 if (instruction.isNull()) {
126 prefix = 'u';
127 } else if (instruction.isConflicting()) {
128 prefix = 'c';
129 } else if (instruction.isExtendableArray(compiler)) {
130 prefix = 'e';
131 } else if (instruction.isFixedArray(compiler)) {
132 prefix = 'f';
133 } else if (instruction.isMutableArray(compiler)) {
134 prefix = 'm';
135 } else if (instruction.isReadableArray(compiler)) {
136 prefix = 'a';
137 } else if (instruction.isString(compiler)) {
138 prefix = 's';
139 } else if (instruction.isIndexablePrimitive(compiler)) {
140 prefix = 'r';
141 } else if (instruction.isBoolean(compiler)) {
142 prefix = 'b';
143 } else if (instruction.isInteger(compiler)) {
144 prefix = 'i';
145 } else if (instruction.isDouble(compiler)) {
146 prefix = 'd';
147 } else if (instruction.isNumber(compiler)) {
148 prefix = 'n';
149 } else if (instruction.instructionType.containsAll(compiler.world)) {
150 prefix = 'v';
151 } else {
152 prefix = 'U';
153 }
154 return "$prefix${instruction.id}";
155 }
156
157 String visitBoolify(HBoolify node) {
158 return "Boolify: ${temporaryId(node.inputs[0])}";
159 }
160
161 String handleInvokeBinary(HInvokeBinary node, String op) {
162 String left = temporaryId(node.left);
163 String right= temporaryId(node.right);
164 return '$left $op $right';
165 }
166
167 String visitAdd(HAdd node) => handleInvokeBinary(node, '+');
168
169 String visitBitAnd(HBitAnd node) => handleInvokeBinary(node, '&');
170
171 String visitBitNot(HBitNot node) {
172 String operand = temporaryId(node.operand);
173 return "~$operand";
174 }
175
176 String visitBitOr(HBitOr node) => handleInvokeBinary(node, '|');
177
178 String visitBitXor(HBitXor node) => handleInvokeBinary(node, '^');
179
180 String visitBoundsCheck(HBoundsCheck node) {
181 String lengthId = temporaryId(node.length);
182 String indexId = temporaryId(node.index);
183 return "Bounds check: length = $lengthId, index = $indexId";
184 }
185
186 String visitBreak(HBreak node) {
187 HBasicBlock target = currentBlock.successors[0];
188 if (node.label != null) {
189 return "Break ${node.label.labelName}: (B${target.id})";
190 }
191 return "Break: (B${target.id})";
192 }
193
194 String visitConstant(HConstant constant) => "Constant ${constant.constant}";
195
196 String visitContinue(HContinue node) {
197 HBasicBlock target = currentBlock.successors[0];
198 if (node.label != null) {
199 return "Continue ${node.label.labelName}: (B${target.id})";
200 }
201 return "Continue: (B${target.id})";
202 }
203
204 String visitDivide(HDivide node) => handleInvokeBinary(node, '/');
205
206 String visitExit(HExit node) => "exit";
207
208 String visitFieldGet(HFieldGet node) {
209 if (node.isNullCheck) {
210 return 'null check on ${temporaryId(node.receiver)}';
211 }
212 String fieldName = node.element.name;
213 return 'field get ${temporaryId(node.receiver)}.$fieldName';
214 }
215
216 String visitFieldSet(HFieldSet node) {
217 String valueId = temporaryId(node.value);
218 String fieldName = node.element.name;
219 return 'field set ${temporaryId(node.receiver)}.$fieldName to $valueId';
220 }
221
222 String visitReadModifyWrite(HReadModifyWrite node) {
223 String fieldName = node.element.name;
224 String receiverId = temporaryId(node.receiver);
225 String op = node.jsOp;
226 if (node.isAssignOp) {
227 String valueId = temporaryId(node.value);
228 return 'field-update $receiverId.$fieldName $op= $valueId';
229 } else if (node.isPreOp) {
230 return 'field-update $op$receiverId.$fieldName';
231 } else {
232 return 'field-update $receiverId.$fieldName$op';
233 }
234 }
235
236 String visitLocalGet(HLocalGet node) {
237 String localName = node.variable.name;
238 return 'local get ${temporaryId(node.local)}.$localName';
239 }
240
241 String visitLocalSet(HLocalSet node) {
242 String valueId = temporaryId(node.value);
243 String localName = node.variable.name;
244 return 'local set ${temporaryId(node.local)}.$localName to $valueId';
245 }
246
247 String visitGoto(HGoto node) {
248 HBasicBlock target = currentBlock.successors[0];
249 return "Goto: (B${target.id})";
250 }
251
252 String visitGreater(HGreater node) => handleInvokeBinary(node, '>');
253 String visitGreaterEqual(HGreaterEqual node) {
254 return handleInvokeBinary(node, '>=');
255 }
256 String visitIdentity(HIdentity node) => handleInvokeBinary(node, '===');
257
258 String visitIf(HIf node) {
259 HBasicBlock thenBlock = currentBlock.successors[0];
260 HBasicBlock elseBlock = currentBlock.successors[1];
261 String conditionId = temporaryId(node.inputs[0]);
262 return "If ($conditionId): (B${thenBlock.id}) else (B${elseBlock.id})";
263 }
264
265 String visitGenericInvoke(String invokeType, String functionName,
266 List<HInstruction> arguments) {
267 StringBuffer argumentsString = new StringBuffer();
268 for (int i = 0; i < arguments.length; i++) {
269 if (i != 0) argumentsString.write(", ");
270 argumentsString.write(temporaryId(arguments[i]));
271 }
272 return "$invokeType: $functionName($argumentsString)";
273 }
274
275 String visitIndex(HIndex node) {
276 String receiver = temporaryId(node.receiver);
277 String index = temporaryId(node.index);
278 return "Index: $receiver[$index]";
279 }
280
281 String visitIndexAssign(HIndexAssign node) {
282 String receiver = temporaryId(node.receiver);
283 String index = temporaryId(node.index);
284 String value = temporaryId(node.value);
285 return "IndexAssign: $receiver[$index] = $value";
286 }
287
288 String visitInterceptor(HInterceptor node) {
289 String value = temporaryId(node.inputs[0]);
290 if (node.interceptedClasses != null) {
291 JavaScriptBackend backend = compiler.backend;
292 String cls = backend.namer.getInterceptorSuffix(node.interceptedClasses);
293 return "Intercept ($cls): $value";
294 }
295 return "Intercept: $value";
296 }
297
298 String visitInvokeClosure(HInvokeClosure node)
299 => visitInvokeDynamic(node, "closure");
300
301 String visitInvokeDynamic(HInvokeDynamic invoke, String kind) {
302 String receiver = temporaryId(invoke.receiver);
303 String name = invoke.selector.name;
304 String target = "($kind) $receiver.$name";
305 int offset = HInvoke.ARGUMENTS_OFFSET;
306 List arguments = invoke.inputs.sublist(offset);
307 return visitGenericInvoke("Invoke", target, arguments) +
308 "(${invoke.selector.mask})";
309 }
310
311 String visitInvokeDynamicMethod(HInvokeDynamicMethod node)
312 => visitInvokeDynamic(node, "method");
313 String visitInvokeDynamicGetter(HInvokeDynamicGetter node)
314 => visitInvokeDynamic(node, "get");
315 String visitInvokeDynamicSetter(HInvokeDynamicSetter node)
316 => visitInvokeDynamic(node, "set");
317
318 String visitInvokeStatic(HInvokeStatic invoke) {
319 String target = invoke.element.name;
320 return visitGenericInvoke("Invoke", target, invoke.inputs);
321 }
322
323 String visitInvokeSuper(HInvokeSuper invoke) {
324 String target = invoke.element.name;
325 return visitGenericInvoke("Invoke super", target, invoke.inputs);
326 }
327
328 String visitInvokeConstructorBody(HInvokeConstructorBody invoke) {
329 String target = invoke.element.name;
330 return visitGenericInvoke("Invoke constructor body", target, invoke.inputs);
331 }
332
333 String visitForeign(HForeign foreign) {
334 return visitGenericInvoke("Foreign", "${foreign.codeTemplate.ast}", foreign. inputs);
335 }
336
337 String visitForeignNew(HForeignNew node) {
338 return visitGenericInvoke("New",
339 "${node.element.name}",
340 node.inputs);
341 }
342
343 String visitLess(HLess node) => handleInvokeBinary(node, '<');
344 String visitLessEqual(HLessEqual node) => handleInvokeBinary(node, '<=');
345
346 String visitLiteralList(HLiteralList node) {
347 StringBuffer elementsString = new StringBuffer();
348 for (int i = 0; i < node.inputs.length; i++) {
349 if (i != 0) elementsString.write(", ");
350 elementsString.write(temporaryId(node.inputs[i]));
351 }
352 return "Literal list: [$elementsString]";
353 }
354
355 String visitLoopBranch(HLoopBranch branch) {
356 HBasicBlock bodyBlock = currentBlock.successors[0];
357 HBasicBlock exitBlock = currentBlock.successors[1];
358 String conditionId = temporaryId(branch.inputs[0]);
359 return "While ($conditionId): (B${bodyBlock.id}) then (B${exitBlock.id})";
360 }
361
362 String visitMultiply(HMultiply node) => handleInvokeBinary(node, '*');
363
364 String visitNegate(HNegate node) {
365 String operand = temporaryId(node.operand);
366 return "-$operand";
367 }
368
369 String visitNot(HNot node) => "Not: ${temporaryId(node.inputs[0])}";
370
371 String visitParameterValue(HParameterValue node) {
372 return "p${node.sourceElement.name}";
373 }
374
375 String visitLocalValue(HLocalValue node) {
376 return "l${node.sourceElement.name}";
377 }
378
379 String visitPhi(HPhi phi) {
380 StringBuffer buffer = new StringBuffer();
381 buffer.write("Phi(");
382 for (int i = 0; i < phi.inputs.length; i++) {
383 if (i > 0) buffer.write(", ");
384 buffer.write(temporaryId(phi.inputs[i]));
385 }
386 buffer.write(")");
387 return buffer.toString();
388 }
389
390 String visitReturn(HReturn node) => "Return ${temporaryId(node.inputs[0])}";
391
392 String visitShiftLeft(HShiftLeft node) => handleInvokeBinary(node, '<<');
393 String visitShiftRight(HShiftRight node) => handleInvokeBinary(node, '>>');
394
395 String visitStatic(HStatic node)
396 => "Static ${node.element.name}";
397
398 String visitLazyStatic(HLazyStatic node)
399 => "LazyStatic ${node.element.name}";
400
401 String visitOneShotInterceptor(HOneShotInterceptor node)
402 => visitInvokeDynamic(node, "one shot interceptor");
403
404 String visitStaticStore(HStaticStore node) {
405 String lhs = node.element.name;
406 return "Static $lhs = ${temporaryId(node.inputs[0])}";
407 }
408
409 String visitStringConcat(HStringConcat node) {
410 var leftId = temporaryId(node.left);
411 var rightId = temporaryId(node.right);
412 return "StringConcat: $leftId + $rightId";
413 }
414
415 String visitStringify(HStringify node) {
416 return "Stringify ${temporaryId(node.inputs[0])}";
417 }
418
419 String visitSubtract(HSubtract node) => handleInvokeBinary(node, '-');
420
421 String visitSwitch(HSwitch node) {
422 StringBuffer buf = new StringBuffer();
423 buf.write("Switch: (");
424 buf.write(temporaryId(node.inputs[0]));
425 buf.write(") ");
426 for (int i = 1; i < node.inputs.length; i++) {
427 buf.write(temporaryId(node.inputs[i]));
428 buf.write(": B");
429 buf.write(node.block.successors[i - 1].id);
430 buf.write(", ");
431 }
432 buf.write("default: B");
433 buf.write(node.defaultTarget.id);
434 return buf.toString();
435 }
436
437 String visitThis(HThis node) => "this";
438
439 String visitThrow(HThrow node) => "Throw ${temporaryId(node.inputs[0])}";
440
441 String visitThrowExpression(HThrowExpression node) {
442 return "ThrowExpression ${temporaryId(node.inputs[0])}";
443 }
444
445 String visitTruncatingDivide(HTruncatingDivide node) {
446 return handleInvokeBinary(node, '~/');
447 }
448
449 String visitExitTry(HExitTry node) {
450 return "Exit try";
451 }
452
453 String visitTry(HTry node) {
454 List<HBasicBlock> successors = currentBlock.successors;
455 String tryBlock = 'B${successors[0].id}';
456 String catchBlock = 'none';
457 if (node.catchBlock != null) {
458 catchBlock = 'B${successors[1].id}';
459 }
460
461 String finallyBlock = 'none';
462 if (node.finallyBlock != null) {
463 finallyBlock = 'B${node.finallyBlock.id}';
464 }
465
466 return "Try: $tryBlock, Catch: $catchBlock, Finally: $finallyBlock, "
467 "Join: B${successors.last.id}";
468 }
469
470 String visitIs(HIs node) {
471 String type = node.typeExpression.toString();
472 return "TypeTest: ${temporaryId(node.expression)} is $type";
473 }
474
475 String visitIsViaInterceptor(HIsViaInterceptor node) {
476 String type = node.typeExpression.toString();
477 return "TypeTest: ${temporaryId(node.inputs[0])} is $type";
478 }
479
480 String visitTypeConversion(HTypeConversion node) {
481 assert(node.inputs.length <= 2);
482 String otherInput = (node.inputs.length == 2)
483 ? temporaryId(node.inputs[1])
484 : '';
485 return "TypeConversion: ${temporaryId(node.checkedInput)} to "
486 "${node.instructionType} $otherInput";
487 }
488
489 String visitTypeKnown(HTypeKnown node) {
490 assert(node.inputs.length <= 2);
491 String result =
492 "TypeKnown: ${temporaryId(node.checkedInput)} is ${node.knownType}";
493 if (node.witness != null) {
494 result += " witnessed by ${temporaryId(node.witness)}";
495 }
496 return result;
497 }
498
499 String visitRangeConversion(HRangeConversion node) {
500 return "RangeConversion: ${node.checkedInput}";
501 }
502
503 String visitReadTypeVariable(HReadTypeVariable node) {
504 return "ReadTypeVariable: ${node.dartType} ${node.hasReceiver}";
505 }
506
507 String visitFunctionType(HFunctionType node) {
508 return "FunctionType: ${node.dartType}";
509 }
510
511 String visitVoidType(HVoidType node) {
512 return "VoidType";
513 }
514
515 String visitInterfaceType(HInterfaceType node) {
516 return "InterfaceType: ${node.dartType}";
517 }
518
519 String visitDynamicType(HDynamicType node) {
520 return "DynamicType";
521 }
522 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/ssa/ssa.dart ('k') | sdk/lib/_internal/compiler/implementation/ssa/types.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698