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