Mercurial > hg > graal-jvmci-8
comparison graal/Compiler/src/com/sun/c1x/debug/CFGPrinter.java @ 2507:9ec15d6914ca
Pull over of compiler from maxine repository.
author | Thomas Wuerthinger <thomas@wuerthinger.net> |
---|---|
date | Wed, 27 Apr 2011 11:43:22 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2506:4a3bf8a5bf41 | 2507:9ec15d6914ca |
---|---|
1 /* | |
2 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 package com.sun.c1x.debug; | |
24 | |
25 import java.io.*; | |
26 import java.util.*; | |
27 | |
28 import com.sun.c1x.*; | |
29 import com.sun.c1x.alloc.*; | |
30 import com.sun.c1x.alloc.Interval.*; | |
31 import com.sun.c1x.graph.*; | |
32 import com.sun.c1x.ir.*; | |
33 import com.sun.c1x.lir.*; | |
34 import com.sun.c1x.lir.LIRInstruction.*; | |
35 import com.sun.c1x.util.*; | |
36 import com.sun.c1x.value.*; | |
37 import com.sun.cri.ci.*; | |
38 import com.sun.cri.ci.CiAddress.*; | |
39 import com.sun.cri.ri.*; | |
40 | |
41 /** | |
42 * Utility for printing the control flow graph of a method being compiled by C1X at various compilation phases. | |
43 * The output format matches that produced by HotSpot so that it can then be fed to the | |
44 * <a href="https://c1visualizer.dev.java.net/">C1 Visualizer</a>. | |
45 * | |
46 * @author Doug Simon | |
47 */ | |
48 public class CFGPrinter { | |
49 private static final String COLUMN_END = " <|@"; | |
50 private static final String HOVER_START = "<@"; | |
51 private static final String HOVER_SEP = "|@"; | |
52 private static final String HOVER_END = ">@"; | |
53 | |
54 private static OutputStream cfgFileStream; | |
55 | |
56 /** | |
57 * Gets the output stream on the file "output.cfg" in the current working directory. | |
58 * This stream is first opened if necessary. | |
59 * | |
60 * @return the output stream to "output.cfg" or {@code null} if there was an error opening this file for writing | |
61 */ | |
62 public static synchronized OutputStream cfgFileStream() { | |
63 if (cfgFileStream == null) { | |
64 File cfgFile = new File("output.cfg"); | |
65 try { | |
66 cfgFileStream = new FileOutputStream(cfgFile); | |
67 } catch (FileNotFoundException e) { | |
68 TTY.println("WARNING: Could not open " + cfgFile.getAbsolutePath()); | |
69 } | |
70 } | |
71 return cfgFileStream; | |
72 } | |
73 | |
74 private final LogStream out; | |
75 private final CiTarget target; | |
76 | |
77 /** | |
78 * Creates a control flow graph printer. | |
79 * | |
80 * @param os where the output generated via this printer shown be written | |
81 * @param target the target architecture description | |
82 */ | |
83 public CFGPrinter(OutputStream os, CiTarget target) { | |
84 out = new LogStream(os); | |
85 this.target = target; | |
86 } | |
87 | |
88 /** | |
89 * Flushes all buffered output to the stream passed to {@link #CFGPrinter(OutputStream, CiTarget)}. | |
90 */ | |
91 public void flush() { | |
92 out.flush(); | |
93 } | |
94 | |
95 private void begin(String string) { | |
96 out.println("begin_" + string); | |
97 out.adjustIndentation(2); | |
98 } | |
99 | |
100 private void end(String string) { | |
101 out.adjustIndentation(-2); | |
102 out.println("end_" + string); | |
103 } | |
104 | |
105 /** | |
106 * Prints a compilation timestamp for a given method. | |
107 * | |
108 * @param method the method for which a timestamp will be printed | |
109 */ | |
110 public void printCompilation(RiMethod method) { | |
111 begin("compilation"); | |
112 out.print("name \" ").print(CiUtil.format("%H::%n", method, true)).println('"'); | |
113 out.print("method \"").print(CiUtil.format("%f %r %H.%n(%p)", method, true)).println('"'); | |
114 out.print("date ").println(System.currentTimeMillis()); | |
115 end("compilation"); | |
116 } | |
117 | |
118 /** | |
119 * Print the details of a given control flow graph block. | |
120 * | |
121 * @param block the block to print | |
122 * @param successors the successor blocks of {@code block} | |
123 * @param handlers the exception handler blocks of {@code block} | |
124 * @param printHIR if {@code true} the HIR for each instruction in the block will be printed | |
125 * @param printLIR if {@code true} the LIR for each instruction in the block will be printed | |
126 */ | |
127 void printBlock(BlockBegin block, List<BlockBegin> successors, Iterable<BlockBegin> handlers, boolean printHIR, boolean printLIR) { | |
128 begin("block"); | |
129 | |
130 out.print("name \"B").print(block.blockID).println('"'); | |
131 out.print("from_bci ").println(block.bci()); | |
132 out.print("to_bci ").println(block.end() == null ? -1 : block.end().bci()); | |
133 | |
134 out.print("predecessors "); | |
135 for (BlockBegin pred : block.predecessors()) { | |
136 out.print("\"B").print(pred.blockID).print("\" "); | |
137 } | |
138 out.println(); | |
139 | |
140 out.print("successors "); | |
141 for (BlockBegin succ : successors) { | |
142 out.print("\"B").print(succ.blockID).print("\" "); | |
143 } | |
144 out.println(); | |
145 | |
146 out.print("xhandlers"); | |
147 for (BlockBegin handler : handlers) { | |
148 out.print("\"B").print(handler.blockID).print("\" "); | |
149 } | |
150 out.println(); | |
151 | |
152 out.print("flags "); | |
153 if (block.isStandardEntry()) { | |
154 out.print("\"std\" "); | |
155 } | |
156 if (block.isOsrEntry()) { | |
157 out.print("\"osr\" "); | |
158 } | |
159 if (block.isExceptionEntry()) { | |
160 out.print("\"ex\" "); | |
161 } | |
162 if (block.isSubroutineEntry()) { | |
163 out.print("\"sr\" "); | |
164 } | |
165 if (block.isBackwardBranchTarget()) { | |
166 out.print("\"bb\" "); | |
167 } | |
168 if (block.isParserLoopHeader()) { | |
169 out.print("\"plh\" "); | |
170 } | |
171 if (block.isCriticalEdgeSplit()) { | |
172 out.print("\"ces\" "); | |
173 } | |
174 if (block.isLinearScanLoopHeader()) { | |
175 out.print("\"llh\" "); | |
176 } | |
177 if (block.isLinearScanLoopEnd()) { | |
178 out.print("\"lle\" "); | |
179 } | |
180 out.println(); | |
181 | |
182 if (block.dominator() != null) { | |
183 out.print("dominator \"B").print(block.dominator().blockID).println('"'); | |
184 } | |
185 if (block.loopIndex() != -1) { | |
186 out.print("loop_index ").println(block.loopIndex()); | |
187 out.print("loop_depth ").println(block.loopDepth()); | |
188 } | |
189 | |
190 if (printHIR) { | |
191 printState(block); | |
192 printHIR(block); | |
193 } | |
194 | |
195 if (printLIR) { | |
196 printLIR(block); | |
197 } | |
198 | |
199 end("block"); | |
200 } | |
201 | |
202 /** | |
203 * Prints the JVM frame state upon entry to a given block. | |
204 * | |
205 * @param block the block for which the frame state is to be printed | |
206 */ | |
207 private void printState(BlockBegin block) { | |
208 begin("states"); | |
209 | |
210 FrameState state = block.stateBefore(); | |
211 | |
212 do { | |
213 int stackSize = state.stackSize(); | |
214 if (stackSize > 0) { | |
215 begin("stack"); | |
216 out.print("size ").println(stackSize); | |
217 out.print("method \"").print(CiUtil.toLocation(state.scope().method, state.bci)).println('"'); | |
218 | |
219 int i = 0; | |
220 while (i < stackSize) { | |
221 Value value = state.stackAt(i); | |
222 out.disableIndentation(); | |
223 out.print(block.stateString(i, value)); | |
224 printOperand(value); | |
225 out.println(); | |
226 out.enableIndentation(); | |
227 if (value == null) { | |
228 i++; | |
229 } else { | |
230 i += value.kind.sizeInSlots(); | |
231 } | |
232 } | |
233 end("stack"); | |
234 } | |
235 | |
236 if (state.locksSize() > 0) { | |
237 begin("locks"); | |
238 out.print("size ").println(state.locksSize()); | |
239 out.print("method \"").print(CiUtil.toLocation(state.scope().method, state.bci)).println('"'); | |
240 | |
241 for (int i = 0; i < state.locksSize(); ++i) { | |
242 Value value = state.lockAt(i); | |
243 out.disableIndentation(); | |
244 out.print(block.stateString(i, value)); | |
245 printOperand(value); | |
246 out.println(); | |
247 out.enableIndentation(); | |
248 } | |
249 end("locks"); | |
250 } | |
251 | |
252 begin("locals"); | |
253 out.print("size ").println(state.localsSize()); | |
254 out.print("method \"").print(CiUtil.toLocation(state.scope().method, state.bci)).println('"'); | |
255 int i = 0; | |
256 while (i < state.localsSize()) { | |
257 Value value = state.localAt(i); | |
258 if (value != null) { | |
259 out.disableIndentation(); | |
260 out.print(block.stateString(i, value)); | |
261 printOperand(value); | |
262 out.println(); | |
263 out.enableIndentation(); | |
264 // also ignore illegal HiWords | |
265 i += value.isIllegal() ? 1 : value.kind.sizeInSlots(); | |
266 } else { | |
267 i++; | |
268 } | |
269 } | |
270 state = state.callerState(); | |
271 end("locals"); | |
272 } while (state != null); | |
273 | |
274 end("states"); | |
275 } | |
276 | |
277 /** | |
278 * Formats a given {@linkplain FrameState JVM frame state} as a multi line string. | |
279 */ | |
280 private String stateToString(FrameState state, CFGOperandFormatter operandFmt) { | |
281 if (state == null) { | |
282 return null; | |
283 } | |
284 | |
285 StringBuilder buf = new StringBuilder(); | |
286 | |
287 do { | |
288 buf.append(CiUtil.toLocation(state.scope().method, state.bci)); | |
289 buf.append('\n'); | |
290 if (state.stackSize() > 0) { | |
291 int i = 0; | |
292 buf.append("stack: "); | |
293 while (i < state.stackSize()) { | |
294 if (i == 0) { | |
295 buf.append(' '); | |
296 } | |
297 Value value = state.stackAt(i); | |
298 buf.append(stateValueToString(value, operandFmt)).append(' '); | |
299 i++; | |
300 } | |
301 buf.append("\n"); | |
302 } | |
303 | |
304 if (state.locksSize() > 0) { | |
305 buf.append("locks: "); | |
306 for (int i = 0; i < state.locksSize(); ++i) { | |
307 if (i == 0) { | |
308 buf.append(' '); | |
309 } | |
310 Value value = state.lockAt(i); | |
311 buf.append(stateValueToString(value, operandFmt)).append(' '); | |
312 } | |
313 buf.append("\n"); | |
314 } | |
315 | |
316 buf.append("locals: "); | |
317 int i = 0; | |
318 while (i < state.localsSize()) { | |
319 if (i == 0) { | |
320 buf.append(' '); | |
321 } | |
322 Value value = state.localAt(i); | |
323 buf.append(stateValueToString(value, operandFmt)).append(' '); | |
324 i++; | |
325 } | |
326 buf.append("\n"); | |
327 state = state.callerState(); | |
328 } while (state != null); | |
329 return buf.toString(); | |
330 } | |
331 | |
332 private String stateValueToString(Value value, OperandFormatter operandFmt) { | |
333 if (operandFmt == null) { | |
334 return Util.valueString(value); | |
335 } | |
336 if (value == null) { | |
337 return "-"; | |
338 } | |
339 return operandFmt.format(value.operand()); | |
340 } | |
341 | |
342 private String stateValueToString(CiValue value, OperandFormatter operandFmt) { | |
343 if (value == null) { | |
344 return "-"; | |
345 } | |
346 return operandFmt.format(value); | |
347 } | |
348 | |
349 /** | |
350 * Formats a given {@linkplain FrameState JVM frame state} as a multi line string. | |
351 */ | |
352 private String debugInfoToString(CiDebugInfo info, CFGOperandFormatter operandFmt) { | |
353 if (info == null) { | |
354 return null; | |
355 } | |
356 StringBuilder sb = new StringBuilder(); | |
357 | |
358 | |
359 if (info.hasRegisterRefMap()) { | |
360 sb.append("reg-ref-map:"); | |
361 C1XCompilation compilation = C1XCompilation.compilation(); | |
362 CiArchitecture arch = compilation == null ? null : compilation.target.arch; | |
363 for (int reg = info.registerRefMap.nextSetBit(0); reg >= 0; reg = info.registerRefMap.nextSetBit(reg + 1)) { | |
364 sb.append(' ').append(arch == null ? "reg" + reg : arch.registers[reg]); | |
365 } | |
366 sb.append("\n"); | |
367 } | |
368 if (info.hasStackRefMap()) { | |
369 sb.append("frame-ref-map:"); | |
370 CiBitMap bm = info.frameRefMap; | |
371 for (int i = bm.nextSetBit(0); i >= 0; i = bm.nextSetBit(i + 1)) { | |
372 sb.append(' ').append(CiStackSlot.get(CiKind.Object, i)); | |
373 } | |
374 sb.append("\n"); | |
375 } | |
376 if (info.codePos != null) { | |
377 sb.append(stateToString(info.codePos, operandFmt)); | |
378 } | |
379 return sb.toString(); | |
380 } | |
381 | |
382 /** | |
383 * Formats a given {@linkplain FrameState JVM frame state} as a multi line string. | |
384 */ | |
385 private String stateToString(CiCodePos codePos, CFGOperandFormatter operandFmt) { | |
386 if (codePos == null) { | |
387 return null; | |
388 } | |
389 | |
390 StringBuilder buf = new StringBuilder(); | |
391 | |
392 do { | |
393 buf.append(CiUtil.toLocation(codePos.method, codePos.bci)); | |
394 buf.append('\n'); | |
395 if (codePos instanceof CiFrame) { | |
396 CiFrame frame = (CiFrame) codePos; | |
397 if (frame.numStack > 0) { | |
398 int i = 0; | |
399 buf.append("stack: "); | |
400 while (i < frame.numStack) { | |
401 if (i == 0) { | |
402 buf.append(' '); | |
403 } | |
404 CiValue value = frame.getStackValue(i); | |
405 buf.append(stateValueToString(value, operandFmt)).append(' '); | |
406 i++; | |
407 } | |
408 buf.append("\n"); | |
409 } | |
410 | |
411 if (frame.numLocks > 0) { | |
412 buf.append("locks: "); | |
413 for (int i = 0; i < frame.numLocks; ++i) { | |
414 if (i == 0) { | |
415 buf.append(' '); | |
416 } | |
417 CiValue value = frame.getLockValue(i); | |
418 buf.append(stateValueToString(value, operandFmt)).append(' '); | |
419 } | |
420 buf.append("\n"); | |
421 } | |
422 | |
423 buf.append("locals: "); | |
424 int i = 0; | |
425 while (i < frame.numLocals) { | |
426 if (i == 0) { | |
427 buf.append(' '); | |
428 } | |
429 CiValue value = frame.getLocalValue(i); | |
430 buf.append(stateValueToString(value, operandFmt)).append(' '); | |
431 i++; | |
432 } | |
433 buf.append("\n"); | |
434 } | |
435 codePos = codePos.caller; | |
436 } while (codePos != null); | |
437 return buf.toString(); | |
438 } | |
439 | |
440 /** | |
441 * Prints the HIR for each instruction in a given block. | |
442 * | |
443 * @param block | |
444 */ | |
445 private void printHIR(BlockBegin block) { | |
446 begin("IR"); | |
447 out.println("HIR"); | |
448 out.disableIndentation(); | |
449 for (Instruction i = block.next(); i != null; i = i.next()) { | |
450 printInstructionHIR(i); | |
451 } | |
452 out.enableIndentation(); | |
453 end("IR"); | |
454 } | |
455 | |
456 /** | |
457 * Formats LIR operands as expected by the C1 Visualizer. | |
458 */ | |
459 public static class CFGOperandFormatter extends OperandFormatter { | |
460 /** | |
461 * The textual delimiters used for an operand depend on the context in which it is being | |
462 * printed. When printed as part of a frame state or as the result operand in a HIR node listing, | |
463 * it is enclosed in double-quotes (i.e. {@code "}'s). | |
464 */ | |
465 public final boolean asStateOrHIROperandResult; | |
466 | |
467 public CFGOperandFormatter(boolean asStateOrHIROperandResult) { | |
468 this.asStateOrHIROperandResult = asStateOrHIROperandResult; | |
469 } | |
470 | |
471 @Override | |
472 public String format(CiValue operand) { | |
473 if (operand.isLegal()) { | |
474 String op; | |
475 if (operand.isVariableOrRegister() || operand.isStackSlot()) { | |
476 op = operand.name(); | |
477 } else if (operand.isConstant()) { | |
478 CiConstant constant = (CiConstant) operand; | |
479 op = operand.kind.javaName + ":" + operand.kind.format(constant.boxedValue()); | |
480 } else if (operand.isAddress()) { | |
481 CiAddress address = (CiAddress) operand; | |
482 op = "Base:" + format(address.base); | |
483 if (!address.index.isIllegal()) { | |
484 op += " Index:" + format(address.index); | |
485 } | |
486 if (address.scale != Scale.Times1) { | |
487 op += " * " + address.scale.value; | |
488 } | |
489 op += " Disp:" + address.displacement; | |
490 } else { | |
491 assert operand.isIllegal(); | |
492 op = "-"; | |
493 } | |
494 if (operand.kind != CiKind.Illegal) { | |
495 op += "|" + operand.kind.typeChar; | |
496 } | |
497 if (asStateOrHIROperandResult) { | |
498 op = " \"" + op.replace('"', '\'') + "\" "; | |
499 } | |
500 return op; | |
501 } | |
502 return ""; | |
503 } | |
504 } | |
505 | |
506 /** | |
507 * Prints the LIR for each instruction in a given block. | |
508 * | |
509 * @param block the block to print | |
510 */ | |
511 private void printLIR(BlockBegin block) { | |
512 LIRList lir = block.lir(); | |
513 if (lir != null) { | |
514 begin("IR"); | |
515 out.println("LIR"); | |
516 for (int i = 0; i < lir.length(); i++) { | |
517 LIRInstruction inst = lir.at(i); | |
518 out.printf("nr %4d ", inst.id).print(COLUMN_END); | |
519 | |
520 if (inst.info != null) { | |
521 int level = out.indentationLevel(); | |
522 out.adjustIndentation(-level); | |
523 String state; | |
524 if (inst.info.debugInfo != null) { | |
525 // Use register-allocator output if available | |
526 state = debugInfoToString(inst.info.debugInfo, new CFGOperandFormatter(false)); | |
527 } else { | |
528 state = stateToString(inst.info.state, new CFGOperandFormatter(false)); | |
529 } | |
530 if (state != null) { | |
531 out.print(" st ").print(HOVER_START).print("st").print(HOVER_SEP).print(state).print(HOVER_END).print(COLUMN_END); | |
532 } | |
533 out.adjustIndentation(level); | |
534 } | |
535 | |
536 out.print(" instruction ").print(inst.toString(new CFGOperandFormatter(false))).print(COLUMN_END); | |
537 out.println(COLUMN_END); | |
538 } | |
539 end("IR"); | |
540 } | |
541 } | |
542 | |
543 private void printOperand(Value i) { | |
544 if (i != null && i.operand().isLegal()) { | |
545 out.print(new CFGOperandFormatter(true).format(i.operand())); | |
546 } | |
547 } | |
548 | |
549 /** | |
550 * Prints the HIR for a given instruction. | |
551 * | |
552 * @param i the instruction for which HIR will be printed | |
553 */ | |
554 private void printInstructionHIR(Instruction i) { | |
555 out.print("bci ").print(i.bci()).println(COLUMN_END); | |
556 if (i.operand().isLegal()) { | |
557 out.print("result ").print(new CFGOperandFormatter(false).format(i.operand())).println(COLUMN_END); | |
558 } | |
559 out.print("tid ").print(i).println(COLUMN_END); | |
560 | |
561 String state = stateToString(i.stateBefore(), null); | |
562 if (state != null) { | |
563 out.print("st ").print(HOVER_START).print("st").print(HOVER_SEP).print(state).print(HOVER_END).println(COLUMN_END); | |
564 } | |
565 | |
566 out.print("instruction "); | |
567 i.print(out); | |
568 out.print(COLUMN_END).print(' ').println(COLUMN_END); | |
569 } | |
570 | |
571 /** | |
572 * Prints the control flow graph denoted by a given block map. | |
573 * | |
574 * @param blockMap a data structure describing the blocks in a method and how they are connected | |
575 * @param codeSize the bytecode size of the method from which {@code blockMap} was produced | |
576 * @param label a label describing the compilation phase that produced the control flow graph | |
577 * @param printHIR if {@code true} the HIR for each instruction in the block will be printed | |
578 * @param printLIR if {@code true} the LIR for each instruction in the block will be printed | |
579 */ | |
580 public void printCFG(RiMethod method, BlockMap blockMap, int codeSize, String label, boolean printHIR, boolean printLIR) { | |
581 begin("cfg"); | |
582 out.print("name \"").print(label).println('"'); | |
583 for (int bci = 0; bci < codeSize; ++bci) { | |
584 BlockBegin block = blockMap.get(bci); | |
585 if (block != null) { | |
586 printBlock(block, Arrays.asList(blockMap.getSuccessors(block)), blockMap.getHandlers(block), printHIR, printLIR); | |
587 } | |
588 } | |
589 end("cfg"); | |
590 } | |
591 | |
592 /** | |
593 * Prints the control flow graph rooted at a given block. | |
594 * | |
595 * @param startBlock the entry block of the control flow graph to be printed | |
596 * @param label a label describing the compilation phase that produced the control flow graph | |
597 * @param printHIR if {@code true} the HIR for each instruction in the block will be printed | |
598 * @param printLIR if {@code true} the LIR for each instruction in the block will be printed | |
599 */ | |
600 public void printCFG(BlockBegin startBlock, String label, final boolean printHIR, final boolean printLIR) { | |
601 begin("cfg"); | |
602 out.print("name \"").print(label).println('"'); | |
603 startBlock.iteratePreOrder(new BlockClosure() { | |
604 public void apply(BlockBegin block) { | |
605 List<BlockBegin> successors = block.end() != null ? block.end().successors() : new ArrayList<BlockBegin>(0); | |
606 printBlock(block, successors, block.exceptionHandlerBlocks(), printHIR, printLIR); | |
607 } | |
608 }); | |
609 end("cfg"); | |
610 } | |
611 | |
612 public void printIntervals(LinearScan allocator, Interval[] intervals, String name) { | |
613 begin("intervals"); | |
614 out.println(String.format("name \"%s\"", name)); | |
615 | |
616 for (Interval interval : intervals) { | |
617 if (interval != null) { | |
618 printInterval(allocator, interval); | |
619 } | |
620 } | |
621 | |
622 end("intervals"); | |
623 } | |
624 | |
625 private void printInterval(LinearScan allocator, Interval interval) { | |
626 out.printf("%d %s ", interval.operandNumber, (interval.operand.isRegister() ? "fixed" : interval.kind().name())); | |
627 if (interval.operand.isRegister()) { | |
628 out.printf("\"[%s|%c]\"", interval.operand.name(), interval.operand.kind.typeChar); | |
629 } else { | |
630 if (interval.location() != null) { | |
631 out.printf("\"[%s|%c]\"", interval.location().name(), interval.location().kind.typeChar); | |
632 } | |
633 } | |
634 | |
635 Interval hint = interval.locationHint(false, allocator); | |
636 out.printf("%d %d ", interval.splitParent().operandNumber, hint != null ? hint.operandNumber : -1); | |
637 | |
638 // print ranges | |
639 Range cur = interval.first(); | |
640 while (cur != Range.EndMarker) { | |
641 out.printf("[%d, %d[", cur.from, cur.to); | |
642 cur = cur.next; | |
643 assert cur != null : "range list not closed with range sentinel"; | |
644 } | |
645 | |
646 // print use positions | |
647 int prev = 0; | |
648 UsePosList usePosList = interval.usePosList(); | |
649 for (int i = usePosList.size() - 1; i >= 0; --i) { | |
650 assert prev < usePosList.usePos(i) : "use positions not sorted"; | |
651 out.printf("%d %s ", usePosList.usePos(i), usePosList.registerPriority(i)); | |
652 prev = usePosList.usePos(i); | |
653 } | |
654 | |
655 out.printf(" \"%s\"", interval.spillState()); | |
656 out.println(); | |
657 } | |
658 | |
659 public void printMachineCode(String code, String label) { | |
660 if (code.length() == 0) { | |
661 return; | |
662 } | |
663 if (label != null) { | |
664 begin("cfg"); | |
665 out.print("name \"").print(label).println('"'); | |
666 end("cfg"); | |
667 } | |
668 begin("nmethod"); | |
669 out.print(code); | |
670 out.println(" <|@"); | |
671 end("nmethod"); | |
672 } | |
673 } |