0
|
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
|