c1_CFGPrinter.cpp revision 1472:c18cbe5936b8
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 31class 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 73CFGPrinterOutput* CFGPrinter::_output = NULL; 74 75 76 77 78void 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 86void 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 91void 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 97void CFGPrinter::print_intervals(IntervalList* intervals, const char* name) { 98 output()->print_intervals(intervals, name); 99} 100 101 102 103CFGPrinterOutput::CFGPrinterOutput() 104 : _output(new(ResourceObj::C_HEAP) fileStream("output.cfg")) 105{ 106} 107 108 109 110void CFGPrinterOutput::inc_indent() { 111 output()->inc(); 112 output()->inc(); 113} 114 115void CFGPrinterOutput::dec_indent() { 116 output()->dec(); 117 output()->dec(); 118} 119 120void 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 129void CFGPrinterOutput::print_begin(const char* tag) { 130 output()->indent(); 131 output()->print_cr("begin_%s", tag); 132 inc_indent(); 133} 134 135void CFGPrinterOutput::print_end(const char* tag) { 136 dec_indent(); 137 output()->indent(); 138 output()->print_cr("end_%s", tag); 139} 140 141 142char* 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 154void 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 168void 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 219void 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 227void 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 244void 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 256void 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 268void 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 338void 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 349void 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 363void 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 379