1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/c1/c1_CFGPrinter.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,386 @@ 1.4 +/* 1.5 + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "c1/c1_CFGPrinter.hpp" 1.30 +#include "c1/c1_IR.hpp" 1.31 +#include "c1/c1_InstructionPrinter.hpp" 1.32 +#include "c1/c1_LIR.hpp" 1.33 +#include "c1/c1_LinearScan.hpp" 1.34 +#include "c1/c1_ValueStack.hpp" 1.35 + 1.36 +#ifndef PRODUCT 1.37 + 1.38 + 1.39 +class CFGPrinterOutput : public CHeapObj<mtCompiler> { 1.40 + private: 1.41 + outputStream* _output; 1.42 + 1.43 + Compilation* _compilation; 1.44 + bool _do_print_HIR; 1.45 + bool _do_print_LIR; 1.46 + 1.47 + class PrintBlockClosure: public BlockClosure { 1.48 + void block_do(BlockBegin* block) { if (block != NULL) CFGPrinter::output()->print_block(block); } 1.49 + }; 1.50 + 1.51 + 1.52 + outputStream* output() { assert(_output != NULL, ""); return _output; } 1.53 + 1.54 + void inc_indent(); 1.55 + void dec_indent(); 1.56 + void print(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); 1.57 + void print_begin(const char* tag); 1.58 + void print_end(const char* tag); 1.59 + 1.60 + char* method_name(ciMethod* method, bool short_name = false); 1.61 + 1.62 + public: 1.63 + CFGPrinterOutput(); 1.64 + 1.65 + void set_compilation(Compilation* compilation) { _compilation = compilation; } 1.66 + void set_print_flags(bool do_print_HIR, bool do_print_LIR) { _do_print_HIR = do_print_HIR; _do_print_LIR = do_print_LIR; } 1.67 + 1.68 + void print_compilation(); 1.69 + void print_intervals(IntervalList* intervals, const char* name); 1.70 + 1.71 + void print_state(BlockBegin* block); 1.72 + void print_operand(Value instr); 1.73 + void print_HIR(Value instr); 1.74 + void print_HIR(BlockBegin* block); 1.75 + void print_LIR(BlockBegin* block); 1.76 + void print_block(BlockBegin* block); 1.77 + void print_cfg(BlockList* blocks, const char* name); 1.78 + void print_cfg(IR* blocks, const char* name); 1.79 +}; 1.80 + 1.81 +CFGPrinterOutput* CFGPrinter::_output = NULL; 1.82 + 1.83 + 1.84 + 1.85 + 1.86 +void CFGPrinter::print_compilation(Compilation* compilation) { 1.87 + if (_output == NULL) { 1.88 + _output = new CFGPrinterOutput(); 1.89 + } 1.90 + output()->set_compilation(compilation); 1.91 + output()->print_compilation(); 1.92 +} 1.93 + 1.94 +void CFGPrinter::print_cfg(BlockList* blocks, const char* name, bool do_print_HIR, bool do_print_LIR) { 1.95 + output()->set_print_flags(do_print_HIR, do_print_LIR); 1.96 + output()->print_cfg(blocks, name); 1.97 +} 1.98 + 1.99 +void CFGPrinter::print_cfg(IR* blocks, const char* name, bool do_print_HIR, bool do_print_LIR) { 1.100 + output()->set_print_flags(do_print_HIR, do_print_LIR); 1.101 + output()->print_cfg(blocks, name); 1.102 +} 1.103 + 1.104 + 1.105 +void CFGPrinter::print_intervals(IntervalList* intervals, const char* name) { 1.106 + output()->print_intervals(intervals, name); 1.107 +} 1.108 + 1.109 + 1.110 + 1.111 +CFGPrinterOutput::CFGPrinterOutput() 1.112 + : _output(new(ResourceObj::C_HEAP, mtCompiler) fileStream("output.cfg")) 1.113 +{ 1.114 +} 1.115 + 1.116 + 1.117 + 1.118 +void CFGPrinterOutput::inc_indent() { 1.119 + output()->inc(); 1.120 + output()->inc(); 1.121 +} 1.122 + 1.123 +void CFGPrinterOutput::dec_indent() { 1.124 + output()->dec(); 1.125 + output()->dec(); 1.126 +} 1.127 + 1.128 +void CFGPrinterOutput::print(const char* format, ...) { 1.129 + output()->indent(); 1.130 + 1.131 + va_list ap; 1.132 + va_start(ap, format); 1.133 + output()->vprint_cr(format, ap); 1.134 + va_end(ap); 1.135 +} 1.136 + 1.137 +void CFGPrinterOutput::print_begin(const char* tag) { 1.138 + output()->indent(); 1.139 + output()->print_cr("begin_%s", tag); 1.140 + inc_indent(); 1.141 +} 1.142 + 1.143 +void CFGPrinterOutput::print_end(const char* tag) { 1.144 + dec_indent(); 1.145 + output()->indent(); 1.146 + output()->print_cr("end_%s", tag); 1.147 +} 1.148 + 1.149 + 1.150 +char* CFGPrinterOutput::method_name(ciMethod* method, bool short_name) { 1.151 + stringStream name; 1.152 + if (short_name) { 1.153 + method->print_short_name(&name); 1.154 + } else { 1.155 + method->print_name(&name); 1.156 + } 1.157 + return name.as_string(); 1.158 + 1.159 +} 1.160 + 1.161 + 1.162 +void CFGPrinterOutput::print_compilation() { 1.163 + print_begin("compilation"); 1.164 + 1.165 + print("name \"%s\"", method_name(_compilation->method(), true)); 1.166 + print("method \"%s\"", method_name(_compilation->method())); 1.167 + print("date "INT64_FORMAT, (int64_t) os::javaTimeMillis()); 1.168 + 1.169 + print_end("compilation"); 1.170 +} 1.171 + 1.172 + 1.173 + 1.174 + 1.175 + 1.176 +void CFGPrinterOutput::print_state(BlockBegin* block) { 1.177 + print_begin("states"); 1.178 + 1.179 + InstructionPrinter ip(true, output()); 1.180 + 1.181 + ValueStack* state = block->state(); 1.182 + int index; 1.183 + Value value; 1.184 + 1.185 + for_each_state(state) { 1.186 + print_begin("locals"); 1.187 + print("size %d", state->locals_size()); 1.188 + print("method \"%s\"", method_name(state->scope()->method())); 1.189 + 1.190 + for_each_local_value(state, index, value) { 1.191 + ip.print_phi(index, value, block); 1.192 + print_operand(value); 1.193 + output()->cr(); 1.194 + } 1.195 + print_end("locals"); 1.196 + 1.197 + if (state->stack_size() > 0) { 1.198 + print_begin("stack"); 1.199 + print("size %d", state->stack_size()); 1.200 + print("method \"%s\"", method_name(state->scope()->method())); 1.201 + 1.202 + for_each_stack_value(state, index, value) { 1.203 + ip.print_phi(index, value, block); 1.204 + print_operand(value); 1.205 + output()->cr(); 1.206 + } 1.207 + 1.208 + print_end("stack"); 1.209 + } 1.210 + 1.211 + if (state->locks_size() > 0) { 1.212 + print_begin("locks"); 1.213 + print("size %d", state->locks_size()); 1.214 + print("method \"%s\"", method_name(state->scope()->method())); 1.215 + 1.216 + for_each_lock_value(state, index, value) { 1.217 + ip.print_phi(index, value, block); 1.218 + print_operand(value); 1.219 + output()->cr(); 1.220 + } 1.221 + print_end("locks"); 1.222 + } 1.223 + } 1.224 + 1.225 + print_end("states"); 1.226 +} 1.227 + 1.228 + 1.229 +void CFGPrinterOutput::print_operand(Value instr) { 1.230 + if (instr->operand()->is_virtual()) { 1.231 + output()->print(" \""); 1.232 + instr->operand()->print(output()); 1.233 + output()->print("\" "); 1.234 + } 1.235 +} 1.236 + 1.237 +void CFGPrinterOutput::print_HIR(Value instr) { 1.238 + InstructionPrinter ip(true, output()); 1.239 + 1.240 + if (instr->is_pinned()) { 1.241 + output()->put('.'); 1.242 + } 1.243 + 1.244 + output()->print("%d %d ", instr->printable_bci(), instr->use_count()); 1.245 + 1.246 + print_operand(instr); 1.247 + 1.248 + ip.print_temp(instr); 1.249 + output()->print(" "); 1.250 + ip.print_instr(instr); 1.251 + 1.252 + output()->print_cr(" <|@"); 1.253 +} 1.254 + 1.255 +void CFGPrinterOutput::print_HIR(BlockBegin* block) { 1.256 + print_begin("HIR"); 1.257 + 1.258 + Value cur = block->next(); 1.259 + while (cur != NULL) { 1.260 + print_HIR(cur); 1.261 + cur = cur->next(); 1.262 + } 1.263 + 1.264 + print_end("HIR"); 1.265 +} 1.266 + 1.267 +void CFGPrinterOutput::print_LIR(BlockBegin* block) { 1.268 + print_begin("LIR"); 1.269 + 1.270 + for (int i = 0; i < block->lir()->length(); i++) { 1.271 + block->lir()->at(i)->print_on(output()); 1.272 + output()->print_cr(" <|@ "); 1.273 + } 1.274 + 1.275 + print_end("LIR"); 1.276 +} 1.277 + 1.278 + 1.279 +void CFGPrinterOutput::print_block(BlockBegin* block) { 1.280 + print_begin("block"); 1.281 + 1.282 + print("name \"B%d\"", block->block_id()); 1.283 + 1.284 + print("from_bci %d", block->bci()); 1.285 + print("to_bci %d", (block->end() == NULL ? -1 : block->end()->printable_bci())); 1.286 + 1.287 + output()->indent(); 1.288 + output()->print("predecessors "); 1.289 + int i; 1.290 + for (i = 0; i < block->number_of_preds(); i++) { 1.291 + output()->print("\"B%d\" ", block->pred_at(i)->block_id()); 1.292 + } 1.293 + output()->cr(); 1.294 + 1.295 + output()->indent(); 1.296 + output()->print("successors "); 1.297 + for (i = 0; i < block->number_of_sux(); i++) { 1.298 + output()->print("\"B%d\" ", block->sux_at(i)->block_id()); 1.299 + } 1.300 + output()->cr(); 1.301 + 1.302 + output()->indent(); 1.303 + output()->print("xhandlers"); 1.304 + for (i = 0; i < block->number_of_exception_handlers(); i++) { 1.305 + output()->print("\"B%d\" ", block->exception_handler_at(i)->block_id()); 1.306 + } 1.307 + output()->cr(); 1.308 + 1.309 + output()->indent(); 1.310 + output()->print("flags "); 1.311 + if (block->is_set(BlockBegin::std_entry_flag)) output()->print("\"std\" "); 1.312 + if (block->is_set(BlockBegin::osr_entry_flag)) output()->print("\"osr\" "); 1.313 + if (block->is_set(BlockBegin::exception_entry_flag)) output()->print("\"ex\" "); 1.314 + if (block->is_set(BlockBegin::subroutine_entry_flag)) output()->print("\"sr\" "); 1.315 + if (block->is_set(BlockBegin::backward_branch_target_flag)) output()->print("\"bb\" "); 1.316 + if (block->is_set(BlockBegin::parser_loop_header_flag)) output()->print("\"plh\" "); 1.317 + if (block->is_set(BlockBegin::critical_edge_split_flag)) output()->print("\"ces\" "); 1.318 + if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) output()->print("\"llh\" "); 1.319 + if (block->is_set(BlockBegin::linear_scan_loop_end_flag)) output()->print("\"lle\" "); 1.320 + output()->cr(); 1.321 + 1.322 + if (block->dominator() != NULL) { 1.323 + print("dominator \"B%d\"", block->dominator()->block_id()); 1.324 + } 1.325 + if (block->loop_index() != -1) { 1.326 + print("loop_index %d", block->loop_index()); 1.327 + print("loop_depth %d", block->loop_depth()); 1.328 + } 1.329 + 1.330 + if (block->first_lir_instruction_id() != -1) { 1.331 + print("first_lir_id %d", block->first_lir_instruction_id()); 1.332 + print("last_lir_id %d", block->last_lir_instruction_id()); 1.333 + } 1.334 + 1.335 + if (_do_print_HIR) { 1.336 + print_state(block); 1.337 + print_HIR(block); 1.338 + } 1.339 + 1.340 + if (_do_print_LIR) { 1.341 + print_LIR(block); 1.342 + } 1.343 + 1.344 + print_end("block"); 1.345 +} 1.346 + 1.347 + 1.348 + 1.349 +void CFGPrinterOutput::print_cfg(BlockList* blocks, const char* name) { 1.350 + print_begin("cfg"); 1.351 + print("name \"%s\"", name); 1.352 + 1.353 + PrintBlockClosure print_block; 1.354 + blocks->iterate_forward(&print_block); 1.355 + 1.356 + print_end("cfg"); 1.357 + output()->flush(); 1.358 +} 1.359 + 1.360 +void CFGPrinterOutput::print_cfg(IR* blocks, const char* name) { 1.361 + print_begin("cfg"); 1.362 + print("name \"%s\"", name); 1.363 + 1.364 + PrintBlockClosure print_block; 1.365 + blocks->iterate_preorder(&print_block); 1.366 + 1.367 + print_end("cfg"); 1.368 + output()->flush(); 1.369 +} 1.370 + 1.371 + 1.372 + 1.373 + 1.374 +void CFGPrinterOutput::print_intervals(IntervalList* intervals, const char* name) { 1.375 + print_begin("intervals"); 1.376 + print("name \"%s\"", name); 1.377 + 1.378 + for (int i = 0; i < intervals->length(); i++) { 1.379 + if (intervals->at(i) != NULL) { 1.380 + intervals->at(i)->print(output()); 1.381 + } 1.382 + } 1.383 + 1.384 + print_end("intervals"); 1.385 + output()->flush(); 1.386 +} 1.387 + 1.388 + 1.389 +#endif