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 
print_compilation(Compilation * compilation)36 void CFGPrinter::print_compilation(Compilation* compilation) {
37   CFGPrinterOutput* output = compilation->cfg_printer_output();
38   output->print_compilation();
39 }
40 
print_cfg(BlockList * blocks,const char * name,bool do_print_HIR,bool do_print_LIR)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 
print_cfg(IR * blocks,const char * name,bool do_print_HIR,bool do_print_LIR)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 
print_intervals(IntervalList * intervals,const char * name)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 
CFGPrinterOutput(Compilation * compilation)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 
inc_indent()71 void CFGPrinterOutput::inc_indent() {
72   output()->inc();
73   output()->inc();
74 }
75 
dec_indent()76 void CFGPrinterOutput::dec_indent() {
77   output()->dec();
78   output()->dec();
79 }
80 
print(const char * format,...)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 
print_begin(const char * tag)90 void CFGPrinterOutput::print_begin(const char* tag) {
91   output()->indent();
92   output()->print_cr("begin_%s", tag);
93   inc_indent();
94 }
95 
print_end(const char * tag)96 void CFGPrinterOutput::print_end(const char* tag) {
97   dec_indent();
98   output()->indent();
99   output()->print_cr("end_%s", tag);
100 }
101 
102 
method_name(ciMethod * method,bool short_name)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 
print_compilation()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 
print_state(BlockBegin * block)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 
print_operand(Value instr)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 
print_HIR(Value instr)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 
print_HIR(BlockBegin * block)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 
print_LIR(BlockBegin * block)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 
print_block(BlockBegin * block)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 
print_cfg(BlockList * blocks,const char * name)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 
print_cfg(IR * blocks,const char * name)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 
print_intervals(IntervalList * intervals,const char * name)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