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   print("name \"B%d\"", block->block_id());
235   print("from_bci %d", block->bci());
236   print("to_bci %d", (block->end() == NULL ? -1 : block->end()->printable_bci()));
237 
238   output()->indent();
239   output()->print("predecessors ");
240   int i;
241   for (i = 0; i < block->number_of_preds(); i++) {
242     output()->print("\"B%d\" ", block->pred_at(i)->block_id());
243   }
244   output()->cr();
245 
246   output()->indent();
247   if (block->end() != NULL) {
248     output()->print("successors ");
249     for (i = 0; i < block->number_of_sux(); i++) {
250       output()->print("\"B%d\" ", block->sux_at(i)->block_id());
251     }
252   } else {
253     output()->print("(block has no end, cannot print successors)");
254   }
255   output()->cr();
256 
257   output()->indent();
258   output()->print("xhandlers");
259   for (i = 0; i < block->number_of_exception_handlers(); i++) {
260     output()->print("\"B%d\" ", block->exception_handler_at(i)->block_id());
261   }
262   output()->cr();
263 
264   output()->indent();
265   output()->print("flags ");
266   if (block->is_set(BlockBegin::std_entry_flag))                output()->print("\"std\" ");
267   if (block->is_set(BlockBegin::osr_entry_flag))                output()->print("\"osr\" ");
268   if (block->is_set(BlockBegin::exception_entry_flag))          output()->print("\"ex\" ");
269   if (block->is_set(BlockBegin::subroutine_entry_flag))         output()->print("\"sr\" ");
270   if (block->is_set(BlockBegin::backward_branch_target_flag))   output()->print("\"bb\" ");
271   if (block->is_set(BlockBegin::parser_loop_header_flag))       output()->print("\"plh\" ");
272   if (block->is_set(BlockBegin::critical_edge_split_flag))      output()->print("\"ces\" ");
273   if (block->is_set(BlockBegin::linear_scan_loop_header_flag))  output()->print("\"llh\" ");
274   if (block->is_set(BlockBegin::linear_scan_loop_end_flag))     output()->print("\"lle\" ");
275   output()->cr();
276 
277   if (block->dominator() != NULL) {
278     print("dominator \"B%d\"", block->dominator()->block_id());
279   }
280   if (block->loop_index() != -1) {
281     print("loop_index %d", block->loop_index());
282     print("loop_depth %d", block->loop_depth());
283   }
284 
285   if (block->first_lir_instruction_id() != -1) {
286     print("first_lir_id %d", block->first_lir_instruction_id());
287     print("last_lir_id %d", block->last_lir_instruction_id());
288   }
289 
290   if (_do_print_HIR) {
291     print_state(block);
292     print_HIR(block);
293   }
294 
295   if (_do_print_LIR) {
296     print_LIR(block);
297   }
298 
299   print_end("block");
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 void CFGPrinterOutput::print_intervals(IntervalList* intervals, const char* name) {
325   print_begin("intervals");
326   print("name \"%s\"", name);
327 
328   for (int i = 0; i < intervals->length(); i++) {
329     if (intervals->at(i) != NULL) {
330       intervals->at(i)->print_on(output(), true);
331     }
332   }
333 
334   print_end("intervals");
335   output()->flush();
336 }
337 
338 #endif // NOT PRODUCT