|
1 /* |
|
2 * Copyright 2005-2006 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
21 * have any questions. |
|
22 * |
|
23 */ |
|
24 |
|
25 #include "incls/_precompiled.incl" |
|
26 #include "incls/_c1_CFGPrinter.cpp.incl" |
|
27 |
|
28 #ifndef PRODUCT |
|
29 |
|
30 |
|
31 class CFGPrinterOutput : public CHeapObj { |
|
32 private: |
|
33 outputStream* _output; |
|
34 |
|
35 Compilation* _compilation; |
|
36 bool _do_print_HIR; |
|
37 bool _do_print_LIR; |
|
38 |
|
39 class PrintBlockClosure: public BlockClosure { |
|
40 void block_do(BlockBegin* block) { if (block != NULL) CFGPrinter::output()->print_block(block); } |
|
41 }; |
|
42 |
|
43 |
|
44 outputStream* output() { assert(_output != NULL, ""); return _output; } |
|
45 |
|
46 void inc_indent(); |
|
47 void dec_indent(); |
|
48 void print(const char* format, ...); |
|
49 void print_begin(const char* tag); |
|
50 void print_end(const char* tag); |
|
51 |
|
52 char* method_name(ciMethod* method, bool short_name = false); |
|
53 |
|
54 public: |
|
55 CFGPrinterOutput(); |
|
56 |
|
57 void set_compilation(Compilation* compilation) { _compilation = compilation; } |
|
58 void set_print_flags(bool do_print_HIR, bool do_print_LIR) { _do_print_HIR = do_print_HIR; _do_print_LIR = do_print_LIR; } |
|
59 |
|
60 void print_compilation(); |
|
61 void print_intervals(IntervalList* intervals, const char* name); |
|
62 |
|
63 void print_state(BlockBegin* block); |
|
64 void print_operand(Value instr); |
|
65 void print_HIR(Value instr); |
|
66 void print_HIR(BlockBegin* block); |
|
67 void print_LIR(BlockBegin* block); |
|
68 void print_block(BlockBegin* block); |
|
69 void print_cfg(BlockList* blocks, const char* name); |
|
70 void print_cfg(IR* blocks, const char* name); |
|
71 }; |
|
72 |
|
73 CFGPrinterOutput* CFGPrinter::_output = NULL; |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 void CFGPrinter::print_compilation(Compilation* compilation) { |
|
79 if (_output == NULL) { |
|
80 _output = new CFGPrinterOutput(); |
|
81 } |
|
82 output()->set_compilation(compilation); |
|
83 output()->print_compilation(); |
|
84 } |
|
85 |
|
86 void CFGPrinter::print_cfg(BlockList* blocks, const char* name, bool do_print_HIR, bool do_print_LIR) { |
|
87 output()->set_print_flags(do_print_HIR, do_print_LIR); |
|
88 output()->print_cfg(blocks, name); |
|
89 } |
|
90 |
|
91 void CFGPrinter::print_cfg(IR* blocks, const char* name, bool do_print_HIR, bool do_print_LIR) { |
|
92 output()->set_print_flags(do_print_HIR, do_print_LIR); |
|
93 output()->print_cfg(blocks, name); |
|
94 } |
|
95 |
|
96 |
|
97 void CFGPrinter::print_intervals(IntervalList* intervals, const char* name) { |
|
98 output()->print_intervals(intervals, name); |
|
99 } |
|
100 |
|
101 |
|
102 |
|
103 CFGPrinterOutput::CFGPrinterOutput() |
|
104 : _output(new(ResourceObj::C_HEAP) fileStream("output.cfg")) |
|
105 { |
|
106 } |
|
107 |
|
108 |
|
109 |
|
110 void CFGPrinterOutput::inc_indent() { |
|
111 output()->inc(); |
|
112 output()->inc(); |
|
113 } |
|
114 |
|
115 void CFGPrinterOutput::dec_indent() { |
|
116 output()->dec(); |
|
117 output()->dec(); |
|
118 } |
|
119 |
|
120 void CFGPrinterOutput::print(const char* format, ...) { |
|
121 output()->indent(); |
|
122 |
|
123 va_list ap; |
|
124 va_start(ap, format); |
|
125 output()->vprint_cr(format, ap); |
|
126 va_end(ap); |
|
127 } |
|
128 |
|
129 void CFGPrinterOutput::print_begin(const char* tag) { |
|
130 output()->indent(); |
|
131 output()->print_cr("begin_%s", tag); |
|
132 inc_indent(); |
|
133 } |
|
134 |
|
135 void CFGPrinterOutput::print_end(const char* tag) { |
|
136 dec_indent(); |
|
137 output()->indent(); |
|
138 output()->print_cr("end_%s", tag); |
|
139 } |
|
140 |
|
141 |
|
142 char* CFGPrinterOutput::method_name(ciMethod* method, bool short_name) { |
|
143 stringStream name; |
|
144 if (short_name) { |
|
145 method->print_short_name(&name); |
|
146 } else { |
|
147 method->print_name(&name); |
|
148 } |
|
149 return name.as_string(); |
|
150 |
|
151 } |
|
152 |
|
153 |
|
154 void CFGPrinterOutput::print_compilation() { |
|
155 print_begin("compilation"); |
|
156 |
|
157 print("name \"%s\"", method_name(_compilation->method(), true)); |
|
158 print("method \"%s\"", method_name(_compilation->method())); |
|
159 print("date "INT64_FORMAT, os::javaTimeMillis()); |
|
160 |
|
161 print_end("compilation"); |
|
162 } |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 void CFGPrinterOutput::print_state(BlockBegin* block) { |
|
169 print_begin("states"); |
|
170 |
|
171 InstructionPrinter ip(true, output()); |
|
172 |
|
173 ValueStack* state = block->state(); |
|
174 int index; |
|
175 Value value; |
|
176 |
|
177 if (state->stack_size() > 0) { |
|
178 print_begin("stack"); |
|
179 print("size %d", state->stack_size()); |
|
180 |
|
181 for_each_stack_value(state, index, value) { |
|
182 ip.print_phi(index, value, block); |
|
183 print_operand(value); |
|
184 output()->cr(); |
|
185 } |
|
186 |
|
187 print_end("stack"); |
|
188 } |
|
189 |
|
190 if (state->locks_size() > 0) { |
|
191 print_begin("locks"); |
|
192 print("size %d", state->locks_size()); |
|
193 |
|
194 for_each_lock_value(state, index, value) { |
|
195 ip.print_phi(index, value, block); |
|
196 print_operand(value); |
|
197 output()->cr(); |
|
198 } |
|
199 print_end("locks"); |
|
200 } |
|
201 |
|
202 for_each_state(state) { |
|
203 print_begin("locals"); |
|
204 print("size %d", state->locals_size()); |
|
205 print("method \"%s\"", method_name(state->scope()->method())); |
|
206 |
|
207 for_each_local_value(state, index, value) { |
|
208 ip.print_phi(index, value, block); |
|
209 print_operand(value); |
|
210 output()->cr(); |
|
211 } |
|
212 print_end("locals"); |
|
213 } |
|
214 |
|
215 print_end("states"); |
|
216 } |
|
217 |
|
218 |
|
219 void CFGPrinterOutput::print_operand(Value instr) { |
|
220 if (instr->operand()->is_virtual()) { |
|
221 output()->print(" \""); |
|
222 instr->operand()->print(output()); |
|
223 output()->print("\" "); |
|
224 } |
|
225 } |
|
226 |
|
227 void CFGPrinterOutput::print_HIR(Value instr) { |
|
228 InstructionPrinter ip(true, output()); |
|
229 |
|
230 if (instr->is_pinned()) { |
|
231 output()->put('.'); |
|
232 } |
|
233 output()->print("%d %d ", instr->bci(), instr->use_count()); |
|
234 |
|
235 print_operand(instr); |
|
236 |
|
237 ip.print_temp(instr); |
|
238 output()->print(" "); |
|
239 ip.print_instr(instr); |
|
240 |
|
241 output()->print_cr(" <|@"); |
|
242 } |
|
243 |
|
244 void CFGPrinterOutput::print_HIR(BlockBegin* block) { |
|
245 print_begin("HIR"); |
|
246 |
|
247 Value cur = block->next(); |
|
248 while (cur != NULL) { |
|
249 print_HIR(cur); |
|
250 cur = cur->next(); |
|
251 } |
|
252 |
|
253 print_end("HIR"); |
|
254 } |
|
255 |
|
256 void CFGPrinterOutput::print_LIR(BlockBegin* block) { |
|
257 print_begin("LIR"); |
|
258 |
|
259 for (int i = 0; i < block->lir()->length(); i++) { |
|
260 block->lir()->at(i)->print_on(output()); |
|
261 output()->print_cr(" <|@ "); |
|
262 } |
|
263 |
|
264 print_end("LIR"); |
|
265 } |
|
266 |
|
267 |
|
268 void CFGPrinterOutput::print_block(BlockBegin* block) { |
|
269 print_begin("block"); |
|
270 |
|
271 print("name \"B%d\"", block->block_id()); |
|
272 |
|
273 print("from_bci %d", block->bci()); |
|
274 print("to_bci %d", (block->end() == NULL ? -1 : block->end()->bci())); |
|
275 |
|
276 output()->indent(); |
|
277 output()->print("predecessors "); |
|
278 int i; |
|
279 for (i = 0; i < block->number_of_preds(); i++) { |
|
280 output()->print("\"B%d\" ", block->pred_at(i)->block_id()); |
|
281 } |
|
282 output()->cr(); |
|
283 |
|
284 output()->indent(); |
|
285 output()->print("successors "); |
|
286 for (i = 0; i < block->number_of_sux(); i++) { |
|
287 output()->print("\"B%d\" ", block->sux_at(i)->block_id()); |
|
288 } |
|
289 output()->cr(); |
|
290 |
|
291 output()->indent(); |
|
292 output()->print("xhandlers"); |
|
293 for (i = 0; i < block->number_of_exception_handlers(); i++) { |
|
294 output()->print("\"B%d\" ", block->exception_handler_at(i)->block_id()); |
|
295 } |
|
296 output()->cr(); |
|
297 |
|
298 output()->indent(); |
|
299 output()->print("flags "); |
|
300 if (block->is_set(BlockBegin::std_entry_flag)) output()->print("\"std\" "); |
|
301 if (block->is_set(BlockBegin::osr_entry_flag)) output()->print("\"osr\" "); |
|
302 if (block->is_set(BlockBegin::exception_entry_flag)) output()->print("\"ex\" "); |
|
303 if (block->is_set(BlockBegin::subroutine_entry_flag)) output()->print("\"sr\" "); |
|
304 if (block->is_set(BlockBegin::backward_branch_target_flag)) output()->print("\"bb\" "); |
|
305 if (block->is_set(BlockBegin::parser_loop_header_flag)) output()->print("\"plh\" "); |
|
306 if (block->is_set(BlockBegin::critical_edge_split_flag)) output()->print("\"ces\" "); |
|
307 if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) output()->print("\"llh\" "); |
|
308 if (block->is_set(BlockBegin::linear_scan_loop_end_flag)) output()->print("\"lle\" "); |
|
309 output()->cr(); |
|
310 |
|
311 if (block->dominator() != NULL) { |
|
312 print("dominator \"B%d\"", block->dominator()->block_id()); |
|
313 } |
|
314 if (block->loop_index() != -1) { |
|
315 print("loop_index %d", block->loop_index()); |
|
316 print("loop_depth %d", block->loop_depth()); |
|
317 } |
|
318 |
|
319 if (block->first_lir_instruction_id() != -1) { |
|
320 print("first_lir_id %d", block->first_lir_instruction_id()); |
|
321 print("last_lir_id %d", block->last_lir_instruction_id()); |
|
322 } |
|
323 |
|
324 if (_do_print_HIR) { |
|
325 print_state(block); |
|
326 print_HIR(block); |
|
327 } |
|
328 |
|
329 if (_do_print_LIR) { |
|
330 print_LIR(block); |
|
331 } |
|
332 |
|
333 print_end("block"); |
|
334 } |
|
335 |
|
336 |
|
337 |
|
338 void CFGPrinterOutput::print_cfg(BlockList* blocks, const char* name) { |
|
339 print_begin("cfg"); |
|
340 print("name \"%s\"", name); |
|
341 |
|
342 PrintBlockClosure print_block; |
|
343 blocks->iterate_forward(&print_block); |
|
344 |
|
345 print_end("cfg"); |
|
346 output()->flush(); |
|
347 } |
|
348 |
|
349 void CFGPrinterOutput::print_cfg(IR* blocks, const char* name) { |
|
350 print_begin("cfg"); |
|
351 print("name \"%s\"", name); |
|
352 |
|
353 PrintBlockClosure print_block; |
|
354 blocks->iterate_preorder(&print_block); |
|
355 |
|
356 print_end("cfg"); |
|
357 output()->flush(); |
|
358 } |
|
359 |
|
360 |
|
361 |
|
362 |
|
363 void CFGPrinterOutput::print_intervals(IntervalList* intervals, const char* name) { |
|
364 print_begin("intervals"); |
|
365 print("name \"%s\"", name); |
|
366 |
|
367 for (int i = 0; i < intervals->length(); i++) { |
|
368 if (intervals->at(i) != NULL) { |
|
369 intervals->at(i)->print(output()); |
|
370 } |
|
371 } |
|
372 |
|
373 print_end("intervals"); |
|
374 output()->flush(); |
|
375 } |
|
376 |
|
377 |
|
378 #endif |