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

Side by Side Diff: frog/leg/ssa/tracer.dart

Issue 9873021: Move frog/leg to lib/compiler/implementation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « frog/leg/ssa/ssa.dart ('k') | frog/leg/ssa/types.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011, 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('tracer');
6
7 #import('dart:io');
8 #import('ssa.dart');
9 #import('../leg.dart');
10
11 final bool GENERATE_SSA_TRACE = false;
12
13 class HTracer extends HGraphVisitor implements Tracer {
14 int indent = 0;
15 final RandomAccessFile output;
16 final bool enabled = GENERATE_SSA_TRACE;
17
18 HTracer([String path = "dart.cfg"])
19 : output = GENERATE_SSA_TRACE ? new File(path).openSync(FileMode.WRITE)
20 : null;
21
22 void close() {
23 if (enabled) output.closeSync();
24 }
25
26 void traceCompilation(String methodName) {
27 tag("compilation", () {
28 printProperty("name", methodName);
29 printProperty("method", methodName);
30 printProperty("date", new Date.now().value);
31 });
32 }
33
34 void traceGraph(String name, HGraph graph) {
35 if (!enabled) return;
36 tag("cfg", () {
37 printProperty("name", name);
38 visitDominatorTree(graph);
39 });
40 }
41
42 void addPredecessors(HBasicBlock block) {
43 if (block.predecessors.isEmpty()) {
44 printEmptyProperty("predecessors");
45 } else {
46 addIndent();
47 add("predecessors");
48 for (HBasicBlock predecessor in block.predecessors) {
49 add(' "B${predecessor.id}"');
50 }
51 add("\n");
52 }
53 }
54
55 void addSuccessors(HBasicBlock block) {
56 if (block.successors.isEmpty()) {
57 printEmptyProperty("successors");
58 } else {
59 addIndent();
60 add("successors");
61 for (HBasicBlock successor in block.successors) {
62 add(' "B${successor.id}"');
63 }
64 add("\n");
65 }
66 }
67
68 void addInstructions(HInstructionStringifier stringifier,
69 HInstructionList list) {
70 for (HInstruction instruction = list.first;
71 instruction !== null;
72 instruction = instruction.next) {
73 int bci = 0;
74 int uses = instruction.usedBy.length;
75 addIndent();
76 String temporaryId = stringifier.temporaryId(instruction);
77 String instructionString = stringifier.visit(instruction);
78 add("$bci $uses $temporaryId $instructionString <|@\n");
79 }
80 }
81
82 void visitBasicBlock(HBasicBlock block) {
83 HInstructionStringifier stringifier = new HInstructionStringifier(block);
84 assert(block.id !== null);
85 tag("block", () {
86 printProperty("name", "B${block.id}");
87 printProperty("from_bci", -1);
88 printProperty("to_bci", -1);
89 addPredecessors(block);
90 addSuccessors(block);
91 printEmptyProperty("xhandlers");
92 printEmptyProperty("flags");
93 if (block.dominator !== null) {
94 printProperty("dominator", "B${block.dominator.id}");
95 }
96 tag("states", () {
97 tag("locals", () {
98 printProperty("size", 0);
99 printProperty("method", "None");
100 block.forEachPhi((phi) {
101 String phiId = stringifier.temporaryId(phi);
102 StringBuffer inputIds = new StringBuffer();
103 for (int i = 0; i < phi.inputs.length; i++) {
104 inputIds.add(stringifier.temporaryId(phi.inputs[i]));
105 inputIds.add(" ");
106 }
107 println("${phi.id} $phiId [ $inputIds]");
108 });
109 });
110 });
111 tag("HIR", () {
112 addInstructions(stringifier, block.phis);
113 addInstructions(stringifier, block);
114 });
115 });
116 }
117
118 void tag(String tagName, Function f) {
119 println("begin_$tagName");
120 indent++;
121 f();
122 indent--;
123 println("end_$tagName");
124 }
125
126 void println(String string) {
127 addIndent();
128 add(string);
129 add("\n");
130 }
131
132 void printEmptyProperty(String propertyName) {
133 println(propertyName);
134 }
135
136 void printProperty(String propertyName, var value) {
137 if (value is num) {
138 println("$propertyName $value");
139 } else {
140 println('$propertyName "$value"');
141 }
142 }
143
144 void add(String string) {
145 output.writeStringSync(string);
146 }
147
148 void addIndent() {
149 for (int i = 0; i < indent; i++) {
150 add(" ");
151 }
152 }
153 }
154
155 class HInstructionStringifier implements HVisitor<String> {
156 HBasicBlock currentBlock;
157
158 HInstructionStringifier(this.currentBlock);
159
160 visit(HInstruction node) => node.accept(this);
161
162 visitBasicBlock(HBasicBlock node) {
163 unreachable();
164 }
165
166 String temporaryId(HInstruction instruction) {
167 String prefix;
168 switch (instruction.type) {
169 case HType.ARRAY: prefix = 'a'; break;
170 case HType.BOOLEAN: prefix = 'b'; break;
171 case HType.INTEGER: prefix = 'i'; break;
172 case HType.DOUBLE: prefix = 'd'; break;
173 case HType.NUMBER: prefix = 'n'; break;
174 case HType.STRING: prefix = 's'; break;
175 case HType.UNKNOWN: prefix = 'v'; break;
176 case HType.CONFLICTING: prefix = 'c'; break;
177 case HType.STRING_OR_ARRAY: prefix = 'sa'; break;
178 default: unreachable();
179 }
180 return "$prefix${instruction.id}";
181 }
182
183 String visitBoolify(HBoolify node) {
184 return "Boolify: ${temporaryId(node.inputs[0])}";
185 }
186
187 String visitAdd(HAdd node) => visitInvokeStatic(node);
188
189 String visitBitAnd(HBitAnd node) => visitInvokeStatic(node);
190
191 String visitBitNot(HBitNot node) => visitInvokeStatic(node);
192
193 String visitBitOr(HBitOr node) => visitInvokeStatic(node);
194
195 String visitBitXor(HBitXor node) => visitInvokeStatic(node);
196
197 String visitBoundsCheck(HBoundsCheck node) {
198 String lengthId = temporaryId(node.length);
199 String indexId = temporaryId(node.index);
200 return "Bounds check: length = $lengthId, index = $indexId";
201 }
202
203 String visitBreak(HBreak node) {
204 HBasicBlock target = currentBlock.successors[0];
205 if (node.label !== null) {
206 return "Break ${node.label.labelName}: (B${target.id})";
207 }
208 return "Break: (B${target.id})";
209 }
210
211 String visitConstant(HConstant constant) => "Constant ${constant.constant}";
212
213 String visitContinue(HContinue node) {
214 HBasicBlock target = currentBlock.successors[0];
215 if (node.label !== null) {
216 return "Continue ${node.label.labelName}: (B${target.id})";
217 }
218 return "Continue: (B${target.id})";
219 }
220
221 String visitDivide(HDivide node) => visitInvokeStatic(node);
222
223 String visitEquals(HEquals node) => visitInvokeStatic(node);
224
225 String visitExit(HExit node) => "exit";
226
227 String visitFieldGet(HFieldGet node) {
228 return 'get ${node.element.name.slowToString()}';
229 }
230
231 String visitFieldSet(HFieldSet node) {
232 String valueId = temporaryId(node.value);
233 return 'set ${node.element.name.slowToString()} to $valueId';
234 }
235
236 String visitGoto(HGoto node) {
237 HBasicBlock target = currentBlock.successors[0];
238 return "Goto: (B${target.id})";
239 }
240
241 String visitGreater(HGreater node) => visitInvokeStatic(node);
242 String visitGreaterEqual(HGreaterEqual node) => visitInvokeStatic(node);
243
244 String visitIdentity(HIdentity node) => visitInvokeStatic(node);
245
246 String visitIf(HIf node) {
247 HBasicBlock thenBlock = currentBlock.successors[0];
248 HBasicBlock elseBlock = currentBlock.successors[1];
249 String conditionId = temporaryId(node.inputs[0]);
250 return "If ($conditionId): (B${thenBlock.id}) else (B${elseBlock.id})";
251 }
252
253 String visitGenericInvoke(String invokeType, String functionName,
254 List<HInstruction> arguments) {
255 StringBuffer argumentsString = new StringBuffer();
256 for (int i = 0; i < arguments.length; i++) {
257 if (i != 0) argumentsString.add(", ");
258 argumentsString.add(temporaryId(arguments[i]));
259 }
260 return "$invokeType: $functionName($argumentsString)";
261 }
262
263 String visitIndex(HIndex node) => visitInvokeStatic(node);
264 String visitIndexAssign(HIndexAssign node) => visitInvokeStatic(node);
265
266 String visitIntegerCheck(HIntegerCheck node) {
267 String value = temporaryId(node.value);
268 return "Integer check: $value";
269 }
270
271 String visitInvokeClosure(HInvokeClosure node)
272 => visitInvokeDynamic(node, "closure");
273
274 String visitInvokeDynamic(HInvokeDynamic invoke, String kind) {
275 String receiver = temporaryId(invoke.receiver);
276 String target = "($kind) $receiver.${invoke.name.slowToString()}";
277 int offset = HInvoke.ARGUMENTS_OFFSET;
278 List arguments =
279 invoke.inputs.getRange(offset, invoke.inputs.length - offset);
280 return visitGenericInvoke("Invoke", target, arguments);
281 }
282
283 String visitInvokeDynamicMethod(HInvokeDynamicMethod node)
284 => visitInvokeDynamic(node, "method");
285 String visitInvokeDynamicGetter(HInvokeDynamicGetter node)
286 => visitInvokeDynamic(node, "get");
287 String visitInvokeDynamicSetter(HInvokeDynamicSetter node)
288 => visitInvokeDynamic(node, "set");
289
290 String visitInvokeInterceptor(HInvokeInterceptor invoke)
291 => visitInvokeStatic(invoke);
292
293 String visitInvokeStatic(HInvokeStatic invoke) {
294 String target = temporaryId(invoke.target);
295 int offset = HInvoke.ARGUMENTS_OFFSET;
296 List arguments =
297 invoke.inputs.getRange(offset, invoke.inputs.length - offset);
298 return visitGenericInvoke("Invoke", target, arguments);
299 }
300
301 String visitInvokeSuper(HInvokeSuper invoke) {
302 String target = temporaryId(invoke.target);
303 int offset = HInvoke.ARGUMENTS_OFFSET + 1;
304 List arguments =
305 invoke.inputs.getRange(offset, invoke.inputs.length - offset);
306 return visitGenericInvoke("Invoke super", target, arguments);
307 }
308
309 String visitForeign(HForeign foreign) {
310 return visitGenericInvoke("Foreign", "${foreign.code}", foreign.inputs);
311 }
312
313 String visitForeignNew(HForeignNew node) {
314 return visitGenericInvoke("New",
315 "${node.element.name.slowToString()}",
316 node.inputs);
317 }
318
319 String visitLess(HLess node) => visitInvokeStatic(node);
320 String visitLessEqual(HLessEqual node) => visitInvokeStatic(node);
321
322 String visitLiteralList(HLiteralList node) {
323 StringBuffer elementsString = new StringBuffer();
324 for (int i = 0; i < node.inputs.length; i++) {
325 if (i != 0) elementsString.add(", ");
326 elementsString.add(temporaryId(node.inputs[i]));
327 }
328 return "Literal list: [$elementsString]";
329 }
330
331 String visitLoopBranch(HLoopBranch branch) {
332 HBasicBlock bodyBlock = currentBlock.successors[0];
333 HBasicBlock exitBlock = currentBlock.successors[1];
334 String conditionId = temporaryId(branch.inputs[0]);
335 return "While ($conditionId): (B${bodyBlock.id}) then (B${exitBlock.id})";
336 }
337
338 String visitModulo(HModulo node) => visitInvokeStatic(node);
339
340 String visitMultiply(HMultiply node) => visitInvokeStatic(node);
341
342 String visitNegate(HNegate node) => visitInvokeStatic(node);
343
344 String visitNot(HNot node) => "Not: ${temporaryId(node.inputs[0])}";
345
346 String visitParameterValue(HParameterValue node) {
347 return "p${node.element.name.slowToString()}";
348 }
349
350 String visitPhi(HPhi phi) {
351 StringBuffer buffer = new StringBuffer();
352 buffer.add("Phi(");
353 for (int i = 0; i < phi.inputs.length; i++) {
354 if (i > 0) buffer.add(", ");
355 buffer.add(temporaryId(phi.inputs[i]));
356 }
357 buffer.add(")");
358 return buffer.toString();
359 }
360
361 String visitReturn(HReturn node) => "Return ${temporaryId(node.inputs[0])}";
362
363 String visitShiftLeft(HShiftLeft node) => visitInvokeStatic(node);
364
365 String visitShiftRight(HShiftRight node) => visitInvokeStatic(node);
366
367 String visitStatic(HStatic node)
368 => "Static ${node.element.name.slowToString()}";
369 String visitStaticStore(HStaticStore node) {
370 String lhs = node.element.name.slowToString();
371 return "Static $lhs = ${temporaryId(node.inputs[0])}";
372 }
373
374 String visitSubtract(HSubtract node) => visitInvokeStatic(node);
375
376 String visitThis(HThis node) => "this";
377
378 String visitThrow(HThrow node) => "Throw ${temporaryId(node.inputs[0])}";
379
380 String visitTruncatingDivide(HTruncatingDivide node) {
381 return visitInvokeStatic(node);
382 }
383
384 String visitTry(HTry node) {
385 List<HBasicBlock> successors = currentBlock.successors;
386 String tryBlock = 'B${successors[0].id}';
387 StringBuffer catchBlocks = new StringBuffer();
388 for (int i = 1; i < successors.length - 1; i++) {
389 catchBlocks.add('B${successors[i].id}, ');
390 }
391
392 String finallyBlock;
393 if (node.finallyBlock != null) {
394 finallyBlock = 'B${node.finallyBlock.id}';
395 } else {
396 catchBlocks.add('B${successors[successors.length - 1].id}');
397 finallyBlock = 'none';
398 }
399 return "Try: $tryBlock, Catch: $catchBlocks, Finally: $finallyBlock";
400 }
401
402 String visitTypeGuard(HTypeGuard node) {
403 String type;
404 switch (node.type) {
405 case HType.ARRAY: type = "array"; break;
406 case HType.BOOLEAN: type = "bool"; break;
407 case HType.INTEGER: type = "integer"; break;
408 case HType.DOUBLE: type = "double"; break;
409 case HType.NUMBER: type = "number"; break;
410 case HType.STRING: type = "string"; break;
411 case HType.STRING_OR_ARRAY: type = "string_or_array"; break;
412 case HType.UNKNOWN: type = 'unknown'; break;
413 default: unreachable();
414 }
415 return "TypeGuard: ${temporaryId(node.inputs[0])} is $type";
416 }
417
418 String visitIs(HIs node) {
419 String type = node.typeExpression.toString();
420 return "TypeTest: ${temporaryId(node.expression)} is $type";
421 }
422 }
OLDNEW
« no previous file with comments | « frog/leg/ssa/ssa.dart ('k') | frog/leg/ssa/types.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698