1 /* 2 * Copyright (c) 2005, 2006, 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 "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 for_each_state(state) { 178 print_begin("locals"); 179 print("size %d", state->locals_size()); 180 print("method \"%s\"", method_name(state->scope()->method())); 181 182 for_each_local_value(state, index, value) { 183 ip.print_phi(index, value, block); 184 print_operand(value); 185 output()->cr(); 186 } 187 print_end("locals"); 188 189 if (state->stack_size() > 0) { 190 print_begin("stack"); 191 print("size %d", state->stack_size()); 192 print("method \"%s\"", method_name(state->scope()->method())); 193 194 for_each_stack_value(state, index, value) { 195 ip.print_phi(index, value, block); 196 print_operand(value); 197 output()->cr(); 198 } 199 200 print_end("stack"); 201 } 202 203 if (state->locks_size() > 0) { 204 print_begin("locks"); 205 print("size %d", state->locks_size()); 206 print("method \"%s\"", method_name(state->scope()->method())); 207 208 for_each_lock_value(state, index, value) { 209 ip.print_phi(index, value, block); 210 print_operand(value); 211 output()->cr(); 212 } 213 print_end("locks"); 214 } 215 } 216 217 print_end("states"); 218 } 219 220 221 void CFGPrinterOutput::print_operand(Value instr) { 222 if (instr->operand()->is_virtual()) { 223 output()->print(" \""); 224 instr->operand()->print(output()); 225 output()->print("\" "); 226 } 227 } 228 229 void CFGPrinterOutput::print_HIR(Value instr) { 230 InstructionPrinter ip(true, output()); 231 232 if (instr->is_pinned()) { 233 output()->put('.'); 234 } 235 236 output()->print("%d %d ", instr->printable_bci(), instr->use_count()); 237 238 print_operand(instr); 239 240 ip.print_temp(instr); 241 output()->print(" "); 242 ip.print_instr(instr); 243 244 output()->print_cr(" <|@"); 245 } 246 247 void CFGPrinterOutput::print_HIR(BlockBegin* block) { 248 print_begin("HIR"); 249 250 Value cur = block->next(); 251 while (cur != NULL) { 252 print_HIR(cur); 253 cur = cur->next(); 254 } 255 256 print_end("HIR"); 257 } 258 259 void CFGPrinterOutput::print_LIR(BlockBegin* block) { 260 print_begin("LIR"); 261 262 for (int i = 0; i < block->lir()->length(); i++) { 263 block->lir()->at(i)->print_on(output()); 264 output()->print_cr(" <|@ "); 265 } 266 267 print_end("LIR"); 268 } 269 270 271 void CFGPrinterOutput::print_block(BlockBegin* block) { 272 print_begin("block"); 273 274 print("name \"B%d\"", block->block_id()); 275 276 print("from_bci %d", block->bci()); 277 print("to_bci %d", (block->end() == NULL ? -1 : block->end()->printable_bci())); 278 279 output()->indent(); 280 output()->print("predecessors "); 281 int i; 282 for (i = 0; i < block->number_of_preds(); i++) { 283 output()->print("\"B%d\" ", block->pred_at(i)->block_id()); 284 } 285 output()->cr(); 286 287 output()->indent(); 288 output()->print("successors "); 289 for (i = 0; i < block->number_of_sux(); i++) { 290 output()->print("\"B%d\" ", block->sux_at(i)->block_id()); 291 } 292 output()->cr(); 293 294 output()->indent(); 295 output()->print("xhandlers"); 296 for (i = 0; i < block->number_of_exception_handlers(); i++) { 297 output()->print("\"B%d\" ", block->exception_handler_at(i)->block_id()); 298 } 299 output()->cr(); 300 301 output()->indent(); 302 output()->print("flags "); 303 if (block->is_set(BlockBegin::std_entry_flag)) output()->print("\"std\" "); 304 if (block->is_set(BlockBegin::osr_entry_flag)) output()->print("\"osr\" "); 305 if (block->is_set(BlockBegin::exception_entry_flag)) output()->print("\"ex\" "); 306 if (block->is_set(BlockBegin::subroutine_entry_flag)) output()->print("\"sr\" "); 307 if (block->is_set(BlockBegin::backward_branch_target_flag)) output()->print("\"bb\" "); 308 if (block->is_set(BlockBegin::parser_loop_header_flag)) output()->print("\"plh\" "); 309 if (block->is_set(BlockBegin::critical_edge_split_flag)) output()->print("\"ces\" "); 310 if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) output()->print("\"llh\" "); 311 if (block->is_set(BlockBegin::linear_scan_loop_end_flag)) output()->print("\"lle\" "); 312 output()->cr(); 313 314 if (block->dominator() != NULL) { 315 print("dominator \"B%d\"", block->dominator()->block_id()); 316 } 317 if (block->loop_index() != -1) { 318 print("loop_index %d", block->loop_index()); 319 print("loop_depth %d", block->loop_depth()); 320 } 321 322 if (block->first_lir_instruction_id() != -1) { 323 print("first_lir_id %d", block->first_lir_instruction_id()); 324 print("last_lir_id %d", block->last_lir_instruction_id()); 325 } 326 327 if (_do_print_HIR) { 328 print_state(block); 329 print_HIR(block); 330 } 331 332 if (_do_print_LIR) { 333 print_LIR(block); 334 } 335 336 print_end("block"); 337 } 338 339 340 341 void CFGPrinterOutput::print_cfg(BlockList* blocks, const char* name) { 342 print_begin("cfg"); 343 print("name \"%s\"", name); 344 345 PrintBlockClosure print_block; 346 blocks->iterate_forward(&print_block); 347 348 print_end("cfg"); 349 output()->flush(); 350 } 351 352 void CFGPrinterOutput::print_cfg(IR* blocks, const char* name) { 353 print_begin("cfg"); 354 print("name \"%s\"", name); 355 356 PrintBlockClosure print_block; 357 blocks->iterate_preorder(&print_block); 358 359 print_end("cfg"); 360 output()->flush(); 361 } 362 363 364 365 366 void CFGPrinterOutput::print_intervals(IntervalList* intervals, const char* name) { 367 print_begin("intervals"); 368 print("name \"%s\"", name); 369 370 for (int i = 0; i < intervals->length(); i++) { 371 if (intervals->at(i) != NULL) { 372 intervals->at(i)->print(output()); 373 } 374 } 375 376 print_end("intervals"); 377 output()->flush(); 378 } 379 380 381 #endif