1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/opto/idealGraphPrinter.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,741 @@ 1.4 +/* 1.5 + * Copyright (c) 2007, 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 "opto/chaitin.hpp" 1.30 +#include "opto/idealGraphPrinter.hpp" 1.31 +#include "opto/machnode.hpp" 1.32 +#include "opto/parse.hpp" 1.33 +#include "runtime/threadCritical.hpp" 1.34 + 1.35 +#ifndef PRODUCT 1.36 + 1.37 +// Constants 1.38 +// Keep consistent with Java constants 1.39 +const char *IdealGraphPrinter::INDENT = " "; 1.40 +const char *IdealGraphPrinter::TOP_ELEMENT = "graphDocument"; 1.41 +const char *IdealGraphPrinter::GROUP_ELEMENT = "group"; 1.42 +const char *IdealGraphPrinter::GRAPH_ELEMENT = "graph"; 1.43 +const char *IdealGraphPrinter::PROPERTIES_ELEMENT = "properties"; 1.44 +const char *IdealGraphPrinter::EDGES_ELEMENT = "edges"; 1.45 +const char *IdealGraphPrinter::PROPERTY_ELEMENT = "p"; 1.46 +const char *IdealGraphPrinter::EDGE_ELEMENT = "edge"; 1.47 +const char *IdealGraphPrinter::NODE_ELEMENT = "node"; 1.48 +const char *IdealGraphPrinter::NODES_ELEMENT = "nodes"; 1.49 +const char *IdealGraphPrinter::REMOVE_EDGE_ELEMENT = "removeEdge"; 1.50 +const char *IdealGraphPrinter::REMOVE_NODE_ELEMENT = "removeNode"; 1.51 +const char *IdealGraphPrinter::METHOD_NAME_PROPERTY = "name"; 1.52 +const char *IdealGraphPrinter::METHOD_IS_PUBLIC_PROPERTY = "public"; 1.53 +const char *IdealGraphPrinter::METHOD_IS_STATIC_PROPERTY = "static"; 1.54 +const char *IdealGraphPrinter::TRUE_VALUE = "true"; 1.55 +const char *IdealGraphPrinter::NODE_NAME_PROPERTY = "name"; 1.56 +const char *IdealGraphPrinter::EDGE_NAME_PROPERTY = "name"; 1.57 +const char *IdealGraphPrinter::NODE_ID_PROPERTY = "id"; 1.58 +const char *IdealGraphPrinter::FROM_PROPERTY = "from"; 1.59 +const char *IdealGraphPrinter::TO_PROPERTY = "to"; 1.60 +const char *IdealGraphPrinter::PROPERTY_NAME_PROPERTY = "name"; 1.61 +const char *IdealGraphPrinter::GRAPH_NAME_PROPERTY = "name"; 1.62 +const char *IdealGraphPrinter::INDEX_PROPERTY = "index"; 1.63 +const char *IdealGraphPrinter::METHOD_ELEMENT = "method"; 1.64 +const char *IdealGraphPrinter::INLINE_ELEMENT = "inline"; 1.65 +const char *IdealGraphPrinter::BYTECODES_ELEMENT = "bytecodes"; 1.66 +const char *IdealGraphPrinter::METHOD_BCI_PROPERTY = "bci"; 1.67 +const char *IdealGraphPrinter::METHOD_SHORT_NAME_PROPERTY = "shortName"; 1.68 +const char *IdealGraphPrinter::CONTROL_FLOW_ELEMENT = "controlFlow"; 1.69 +const char *IdealGraphPrinter::BLOCK_NAME_PROPERTY = "name"; 1.70 +const char *IdealGraphPrinter::BLOCK_DOMINATOR_PROPERTY = "dom"; 1.71 +const char *IdealGraphPrinter::BLOCK_ELEMENT = "block"; 1.72 +const char *IdealGraphPrinter::SUCCESSORS_ELEMENT = "successors"; 1.73 +const char *IdealGraphPrinter::SUCCESSOR_ELEMENT = "successor"; 1.74 +const char *IdealGraphPrinter::ASSEMBLY_ELEMENT = "assembly"; 1.75 + 1.76 +int IdealGraphPrinter::_file_count = 0; 1.77 + 1.78 +IdealGraphPrinter *IdealGraphPrinter::printer() { 1.79 + if (PrintIdealGraphLevel == 0) return NULL; 1.80 + 1.81 + JavaThread *thread = JavaThread::current(); 1.82 + if (!thread->is_Compiler_thread()) return NULL; 1.83 + 1.84 + CompilerThread *compiler_thread = (CompilerThread *)thread; 1.85 + if (compiler_thread->ideal_graph_printer() == NULL) { 1.86 + IdealGraphPrinter *printer = new IdealGraphPrinter(); 1.87 + compiler_thread->set_ideal_graph_printer(printer); 1.88 + } 1.89 + 1.90 + return compiler_thread->ideal_graph_printer(); 1.91 +} 1.92 + 1.93 +void IdealGraphPrinter::clean_up() { 1.94 + JavaThread *p; 1.95 + for (p = Threads::first(); p; p = p->next()) { 1.96 + if (p->is_Compiler_thread()) { 1.97 + CompilerThread *c = (CompilerThread *)p; 1.98 + IdealGraphPrinter *printer = c->ideal_graph_printer(); 1.99 + if (printer) { 1.100 + delete printer; 1.101 + } 1.102 + c->set_ideal_graph_printer(NULL); 1.103 + } 1.104 + } 1.105 +} 1.106 + 1.107 +// Constructor, either file or network output 1.108 +IdealGraphPrinter::IdealGraphPrinter() { 1.109 + 1.110 + // By default dump both ins and outs since dead or unreachable code 1.111 + // needs to appear in the graph. There are also some special cases 1.112 + // in the mach where kill projections have no users but should 1.113 + // appear in the dump. 1.114 + _traverse_outs = true; 1.115 + _should_send_method = true; 1.116 + _output = NULL; 1.117 + buffer[0] = 0; 1.118 + _depth = 0; 1.119 + _current_method = NULL; 1.120 + assert(!_current_method, "current method must be initialized to NULL"); 1.121 + _stream = NULL; 1.122 + 1.123 + if (PrintIdealGraphFile != NULL) { 1.124 + ThreadCritical tc; 1.125 + // User wants all output to go to files 1.126 + if (_file_count != 0) { 1.127 + ResourceMark rm; 1.128 + stringStream st; 1.129 + const char* dot = strrchr(PrintIdealGraphFile, '.'); 1.130 + if (dot) { 1.131 + st.write(PrintIdealGraphFile, dot - PrintIdealGraphFile); 1.132 + st.print("%d%s", _file_count, dot); 1.133 + } else { 1.134 + st.print("%s%d", PrintIdealGraphFile, _file_count); 1.135 + } 1.136 + fileStream *stream = new (ResourceObj::C_HEAP, mtCompiler) fileStream(st.as_string()); 1.137 + _output = stream; 1.138 + } else { 1.139 + fileStream *stream = new (ResourceObj::C_HEAP, mtCompiler) fileStream(PrintIdealGraphFile); 1.140 + _output = stream; 1.141 + } 1.142 + _file_count++; 1.143 + } else { 1.144 + _stream = new (ResourceObj::C_HEAP, mtCompiler) networkStream(); 1.145 + 1.146 + // Try to connect to visualizer 1.147 + if (_stream->connect(PrintIdealGraphAddress, PrintIdealGraphPort)) { 1.148 + char c = 0; 1.149 + _stream->read(&c, 1); 1.150 + if (c != 'y') { 1.151 + tty->print_cr("Client available, but does not want to receive data!"); 1.152 + _stream->close(); 1.153 + delete _stream; 1.154 + _stream = NULL; 1.155 + return; 1.156 + } 1.157 + _output = _stream; 1.158 + } else { 1.159 + // It would be nice if we could shut down cleanly but it should 1.160 + // be an error if we can't connect to the visualizer. 1.161 + fatal(err_msg_res("Couldn't connect to visualizer at %s:" INTX_FORMAT, 1.162 + PrintIdealGraphAddress, PrintIdealGraphPort)); 1.163 + } 1.164 + } 1.165 + 1.166 + _xml = new (ResourceObj::C_HEAP, mtCompiler) xmlStream(_output); 1.167 + 1.168 + head(TOP_ELEMENT); 1.169 +} 1.170 + 1.171 +// Destructor, close file or network stream 1.172 +IdealGraphPrinter::~IdealGraphPrinter() { 1.173 + 1.174 + tail(TOP_ELEMENT); 1.175 + 1.176 + // tty->print_cr("Walk time: %d", (int)_walk_time.milliseconds()); 1.177 + // tty->print_cr("Output time: %d", (int)_output_time.milliseconds()); 1.178 + // tty->print_cr("Build blocks time: %d", (int)_build_blocks_time.milliseconds()); 1.179 + 1.180 + if(_xml) { 1.181 + delete _xml; 1.182 + _xml = NULL; 1.183 + } 1.184 + 1.185 + if (_stream) { 1.186 + delete _stream; 1.187 + if (_stream == _output) { 1.188 + _output = NULL; 1.189 + } 1.190 + _stream = NULL; 1.191 + } 1.192 + 1.193 + if (_output) { 1.194 + delete _output; 1.195 + _output = NULL; 1.196 + } 1.197 +} 1.198 + 1.199 + 1.200 +void IdealGraphPrinter::begin_elem(const char *s) { 1.201 + _xml->begin_elem("%s", s); 1.202 +} 1.203 + 1.204 +void IdealGraphPrinter::end_elem() { 1.205 + _xml->end_elem(); 1.206 +} 1.207 + 1.208 +void IdealGraphPrinter::begin_head(const char *s) { 1.209 + _xml->begin_head("%s", s); 1.210 +} 1.211 + 1.212 +void IdealGraphPrinter::end_head() { 1.213 + _xml->end_head(); 1.214 +} 1.215 + 1.216 +void IdealGraphPrinter::print_attr(const char *name, intptr_t val) { 1.217 + stringStream stream; 1.218 + stream.print(INTX_FORMAT, val); 1.219 + print_attr(name, stream.as_string()); 1.220 +} 1.221 + 1.222 +void IdealGraphPrinter::print_attr(const char *name, const char *val) { 1.223 + _xml->print(" %s='", name); 1.224 + text(val); 1.225 + _xml->print("'"); 1.226 +} 1.227 + 1.228 +void IdealGraphPrinter::head(const char *name) { 1.229 + _xml->head("%s", name); 1.230 +} 1.231 + 1.232 +void IdealGraphPrinter::tail(const char *name) { 1.233 + _xml->tail(name); 1.234 +} 1.235 + 1.236 +void IdealGraphPrinter::text(const char *s) { 1.237 + _xml->text("%s", s); 1.238 +} 1.239 + 1.240 +void IdealGraphPrinter::print_prop(const char *name, int val) { 1.241 + 1.242 + stringStream stream; 1.243 + stream.print("%d", val); 1.244 + print_prop(name, stream.as_string()); 1.245 +} 1.246 + 1.247 +void IdealGraphPrinter::print_prop(const char *name, const char *val) { 1.248 + begin_head(PROPERTY_ELEMENT); 1.249 + print_attr(PROPERTY_NAME_PROPERTY, name); 1.250 + end_head(); 1.251 + text(val); 1.252 + tail(PROPERTY_ELEMENT); 1.253 +} 1.254 + 1.255 +void IdealGraphPrinter::print_method(ciMethod *method, int bci, InlineTree *tree) { 1.256 + begin_head(METHOD_ELEMENT); 1.257 + 1.258 + stringStream str; 1.259 + method->print_name(&str); 1.260 + 1.261 + stringStream shortStr; 1.262 + method->print_short_name(&shortStr); 1.263 + 1.264 + print_attr(METHOD_NAME_PROPERTY, str.as_string()); 1.265 + print_attr(METHOD_SHORT_NAME_PROPERTY, shortStr.as_string()); 1.266 + print_attr(METHOD_BCI_PROPERTY, bci); 1.267 + 1.268 + end_head(); 1.269 + 1.270 + head(BYTECODES_ELEMENT); 1.271 + output()->print_cr("<![CDATA["); 1.272 + method->print_codes_on(output()); 1.273 + output()->print_cr("]]>"); 1.274 + tail(BYTECODES_ELEMENT); 1.275 + 1.276 + head(INLINE_ELEMENT); 1.277 + if (tree != NULL) { 1.278 + GrowableArray<InlineTree *> subtrees = tree->subtrees(); 1.279 + for (int i = 0; i < subtrees.length(); i++) { 1.280 + print_inline_tree(subtrees.at(i)); 1.281 + } 1.282 + } 1.283 + tail(INLINE_ELEMENT); 1.284 + 1.285 + tail(METHOD_ELEMENT); 1.286 + output()->flush(); 1.287 +} 1.288 + 1.289 +void IdealGraphPrinter::print_inline_tree(InlineTree *tree) { 1.290 + 1.291 + if (tree == NULL) return; 1.292 + 1.293 + ciMethod *method = tree->method(); 1.294 + print_method(tree->method(), tree->caller_bci(), tree); 1.295 + 1.296 +} 1.297 + 1.298 +void IdealGraphPrinter::print_inlining(Compile* compile) { 1.299 + 1.300 + // Print inline tree 1.301 + if (_should_send_method) { 1.302 + InlineTree *inlineTree = compile->ilt(); 1.303 + if (inlineTree != NULL) { 1.304 + print_inline_tree(inlineTree); 1.305 + } else { 1.306 + // print this method only 1.307 + } 1.308 + } 1.309 +} 1.310 + 1.311 +// Has to be called whenever a method is compiled 1.312 +void IdealGraphPrinter::begin_method(Compile* compile) { 1.313 + 1.314 + ciMethod *method = compile->method(); 1.315 + assert(_output, "output stream must exist!"); 1.316 + assert(method, "null methods are not allowed!"); 1.317 + assert(!_current_method, "current method must be null!"); 1.318 + 1.319 + head(GROUP_ELEMENT); 1.320 + 1.321 + head(PROPERTIES_ELEMENT); 1.322 + 1.323 + // Print properties 1.324 + // Add method name 1.325 + stringStream strStream; 1.326 + method->print_name(&strStream); 1.327 + print_prop(METHOD_NAME_PROPERTY, strStream.as_string()); 1.328 + 1.329 + if (method->flags().is_public()) { 1.330 + print_prop(METHOD_IS_PUBLIC_PROPERTY, TRUE_VALUE); 1.331 + } 1.332 + 1.333 + if (method->flags().is_static()) { 1.334 + print_prop(METHOD_IS_STATIC_PROPERTY, TRUE_VALUE); 1.335 + } 1.336 + 1.337 + tail(PROPERTIES_ELEMENT); 1.338 + 1.339 + if (_stream) { 1.340 + char answer = 0; 1.341 + _xml->flush(); 1.342 + int result = _stream->read(&answer, 1); 1.343 + _should_send_method = (answer == 'y'); 1.344 + } 1.345 + 1.346 + this->_current_method = method; 1.347 + 1.348 + _xml->flush(); 1.349 +} 1.350 + 1.351 +// Has to be called whenever a method has finished compilation 1.352 +void IdealGraphPrinter::end_method() { 1.353 + 1.354 + nmethod* method = (nmethod*)this->_current_method->code(); 1.355 + 1.356 + tail(GROUP_ELEMENT); 1.357 + _current_method = NULL; 1.358 + _xml->flush(); 1.359 +} 1.360 + 1.361 +// Print indent 1.362 +void IdealGraphPrinter::print_indent() { 1.363 + tty->print_cr("printing ident %d", _depth); 1.364 + for (int i = 0; i < _depth; i++) { 1.365 + _xml->print("%s", INDENT); 1.366 + } 1.367 +} 1.368 + 1.369 +bool IdealGraphPrinter::traverse_outs() { 1.370 + return _traverse_outs; 1.371 +} 1.372 + 1.373 +void IdealGraphPrinter::set_traverse_outs(bool b) { 1.374 + _traverse_outs = b; 1.375 +} 1.376 + 1.377 +intptr_t IdealGraphPrinter::get_node_id(Node *n) { 1.378 + return (intptr_t)(n); 1.379 +} 1.380 + 1.381 +void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { 1.382 + 1.383 + if (edges) { 1.384 + 1.385 + // Output edge 1.386 + intptr_t dest_id = get_node_id(n); 1.387 + for ( uint i = 0; i < n->len(); i++ ) { 1.388 + if ( n->in(i) ) { 1.389 + Node *source = n->in(i); 1.390 + begin_elem(EDGE_ELEMENT); 1.391 + intptr_t source_id = get_node_id(source); 1.392 + print_attr(FROM_PROPERTY, source_id); 1.393 + print_attr(TO_PROPERTY, dest_id); 1.394 + print_attr(INDEX_PROPERTY, i); 1.395 + end_elem(); 1.396 + } 1.397 + } 1.398 + 1.399 + } else { 1.400 + 1.401 + // Output node 1.402 + begin_head(NODE_ELEMENT); 1.403 + print_attr(NODE_ID_PROPERTY, get_node_id(n)); 1.404 + end_head(); 1.405 + 1.406 + head(PROPERTIES_ELEMENT); 1.407 + 1.408 + Node *node = n; 1.409 +#ifndef PRODUCT 1.410 + Compile::current()->_in_dump_cnt++; 1.411 + print_prop(NODE_NAME_PROPERTY, (const char *)node->Name()); 1.412 + const Type *t = node->bottom_type(); 1.413 + print_prop("type", t->msg()); 1.414 + print_prop("idx", node->_idx); 1.415 +#ifdef ASSERT 1.416 + print_prop("debug_idx", node->_debug_idx); 1.417 +#endif 1.418 + 1.419 + if (C->cfg() != NULL) { 1.420 + Block* block = C->cfg()->get_block_for_node(node); 1.421 + if (block == NULL) { 1.422 + print_prop("block", C->cfg()->get_block(0)->_pre_order); 1.423 + } else { 1.424 + print_prop("block", block->_pre_order); 1.425 + } 1.426 + } 1.427 + 1.428 + const jushort flags = node->flags(); 1.429 + if (flags & Node::Flag_is_Copy) { 1.430 + print_prop("is_copy", "true"); 1.431 + } 1.432 + if (flags & Node::Flag_rematerialize) { 1.433 + print_prop("rematerialize", "true"); 1.434 + } 1.435 + if (flags & Node::Flag_needs_anti_dependence_check) { 1.436 + print_prop("needs_anti_dependence_check", "true"); 1.437 + } 1.438 + if (flags & Node::Flag_is_macro) { 1.439 + print_prop("is_macro", "true"); 1.440 + } 1.441 + if (flags & Node::Flag_is_Con) { 1.442 + print_prop("is_con", "true"); 1.443 + } 1.444 + if (flags & Node::Flag_is_cisc_alternate) { 1.445 + print_prop("is_cisc_alternate", "true"); 1.446 + } 1.447 + if (flags & Node::Flag_is_dead_loop_safe) { 1.448 + print_prop("is_dead_loop_safe", "true"); 1.449 + } 1.450 + if (flags & Node::Flag_may_be_short_branch) { 1.451 + print_prop("may_be_short_branch", "true"); 1.452 + } 1.453 + if (flags & Node::Flag_has_call) { 1.454 + print_prop("has_call", "true"); 1.455 + } 1.456 + 1.457 + if (C->matcher() != NULL) { 1.458 + if (C->matcher()->is_shared(node)) { 1.459 + print_prop("is_shared", "true"); 1.460 + } else { 1.461 + print_prop("is_shared", "false"); 1.462 + } 1.463 + if (C->matcher()->is_dontcare(node)) { 1.464 + print_prop("is_dontcare", "true"); 1.465 + } else { 1.466 + print_prop("is_dontcare", "false"); 1.467 + } 1.468 + 1.469 +#ifdef ASSERT 1.470 + Node* old = C->matcher()->find_old_node(node); 1.471 + if (old != NULL) { 1.472 + print_prop("old_node_idx", old->_idx); 1.473 + } 1.474 +#endif 1.475 + } 1.476 + 1.477 + if (node->is_Proj()) { 1.478 + print_prop("con", (int)node->as_Proj()->_con); 1.479 + } 1.480 + 1.481 + if (node->is_Mach()) { 1.482 + print_prop("idealOpcode", (const char *)NodeClassNames[node->as_Mach()->ideal_Opcode()]); 1.483 + } 1.484 + 1.485 + buffer[0] = 0; 1.486 + stringStream s2(buffer, sizeof(buffer) - 1); 1.487 + 1.488 + node->dump_spec(&s2); 1.489 + if (t != NULL && (t->isa_instptr() || t->isa_klassptr())) { 1.490 + const TypeInstPtr *toop = t->isa_instptr(); 1.491 + const TypeKlassPtr *tkls = t->isa_klassptr(); 1.492 + ciKlass* klass = toop ? toop->klass() : (tkls ? tkls->klass() : NULL ); 1.493 + if( klass && klass->is_loaded() && klass->is_interface() ) { 1.494 + s2.print(" Interface:"); 1.495 + } else if( toop ) { 1.496 + s2.print(" Oop:"); 1.497 + } else if( tkls ) { 1.498 + s2.print(" Klass:"); 1.499 + } 1.500 + t->dump_on(&s2); 1.501 + } else if( t == Type::MEMORY ) { 1.502 + s2.print(" Memory:"); 1.503 + MemNode::dump_adr_type(node, node->adr_type(), &s2); 1.504 + } 1.505 + 1.506 + assert(s2.size() < sizeof(buffer), "size in range"); 1.507 + print_prop("dump_spec", buffer); 1.508 + 1.509 + if (node->is_block_proj()) { 1.510 + print_prop("is_block_proj", "true"); 1.511 + } 1.512 + 1.513 + if (node->is_block_start()) { 1.514 + print_prop("is_block_start", "true"); 1.515 + } 1.516 + 1.517 + const char *short_name = "short_name"; 1.518 + if (strcmp(node->Name(), "Parm") == 0 && node->as_Proj()->_con >= TypeFunc::Parms) { 1.519 + int index = node->as_Proj()->_con - TypeFunc::Parms; 1.520 + if (index >= 10) { 1.521 + print_prop(short_name, "PA"); 1.522 + } else { 1.523 + sprintf(buffer, "P%d", index); 1.524 + print_prop(short_name, buffer); 1.525 + } 1.526 + } else if (strcmp(node->Name(), "IfTrue") == 0) { 1.527 + print_prop(short_name, "T"); 1.528 + } else if (strcmp(node->Name(), "IfFalse") == 0) { 1.529 + print_prop(short_name, "F"); 1.530 + } else if ((node->is_Con() && node->is_Type()) || node->is_Proj()) { 1.531 + 1.532 + if (t->base() == Type::Int && t->is_int()->is_con()) { 1.533 + const TypeInt *typeInt = t->is_int(); 1.534 + assert(typeInt->is_con(), "must be constant"); 1.535 + jint value = typeInt->get_con(); 1.536 + 1.537 + // max. 2 chars allowed 1.538 + if (value >= -9 && value <= 99) { 1.539 + sprintf(buffer, "%d", value); 1.540 + print_prop(short_name, buffer); 1.541 + } else { 1.542 + print_prop(short_name, "I"); 1.543 + } 1.544 + } else if (t == Type::TOP) { 1.545 + print_prop(short_name, "^"); 1.546 + } else if (t->base() == Type::Long && t->is_long()->is_con()) { 1.547 + const TypeLong *typeLong = t->is_long(); 1.548 + assert(typeLong->is_con(), "must be constant"); 1.549 + jlong value = typeLong->get_con(); 1.550 + 1.551 + // max. 2 chars allowed 1.552 + if (value >= -9 && value <= 99) { 1.553 + sprintf(buffer, JLONG_FORMAT, value); 1.554 + print_prop(short_name, buffer); 1.555 + } else { 1.556 + print_prop(short_name, "L"); 1.557 + } 1.558 + } else if (t->base() == Type::KlassPtr) { 1.559 + const TypeKlassPtr *typeKlass = t->is_klassptr(); 1.560 + print_prop(short_name, "CP"); 1.561 + } else if (t->base() == Type::Control) { 1.562 + print_prop(short_name, "C"); 1.563 + } else if (t->base() == Type::Memory) { 1.564 + print_prop(short_name, "M"); 1.565 + } else if (t->base() == Type::Abio) { 1.566 + print_prop(short_name, "IO"); 1.567 + } else if (t->base() == Type::Return_Address) { 1.568 + print_prop(short_name, "RA"); 1.569 + } else if (t->base() == Type::AnyPtr) { 1.570 + print_prop(short_name, "P"); 1.571 + } else if (t->base() == Type::RawPtr) { 1.572 + print_prop(short_name, "RP"); 1.573 + } else if (t->base() == Type::AryPtr) { 1.574 + print_prop(short_name, "AP"); 1.575 + } 1.576 + } 1.577 + 1.578 + JVMState* caller = NULL; 1.579 + if (node->is_SafePoint()) { 1.580 + caller = node->as_SafePoint()->jvms(); 1.581 + } else { 1.582 + Node_Notes* notes = C->node_notes_at(node->_idx); 1.583 + if (notes != NULL) { 1.584 + caller = notes->jvms(); 1.585 + } 1.586 + } 1.587 + 1.588 + if (caller != NULL) { 1.589 + stringStream bciStream; 1.590 + ciMethod* last = NULL; 1.591 + int last_bci; 1.592 + while(caller) { 1.593 + if (caller->has_method()) { 1.594 + last = caller->method(); 1.595 + last_bci = caller->bci(); 1.596 + } 1.597 + bciStream.print("%d ", caller->bci()); 1.598 + caller = caller->caller(); 1.599 + } 1.600 + print_prop("bci", bciStream.as_string()); 1.601 + if (last != NULL && last->has_linenumber_table() && last_bci >= 0) { 1.602 + print_prop("line", last->line_number_from_bci(last_bci)); 1.603 + } 1.604 + } 1.605 + 1.606 +#ifdef ASSERT 1.607 + if (node->debug_orig() != NULL) { 1.608 + temp_set->Clear(); 1.609 + stringStream dorigStream; 1.610 + Node* dorig = node->debug_orig(); 1.611 + while (dorig && temp_set->test_set(dorig->_idx)) { 1.612 + dorigStream.print("%d ", dorig->_idx); 1.613 + } 1.614 + print_prop("debug_orig", dorigStream.as_string()); 1.615 + } 1.616 +#endif 1.617 + 1.618 + if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) { 1.619 + buffer[0] = 0; 1.620 + _chaitin->dump_register(node, buffer); 1.621 + print_prop("reg", buffer); 1.622 + uint lrg_id = 0; 1.623 + if (node->_idx < _chaitin->_lrg_map.size()) { 1.624 + lrg_id = _chaitin->_lrg_map.live_range_id(node); 1.625 + } 1.626 + print_prop("lrg", lrg_id); 1.627 + } 1.628 + 1.629 + Compile::current()->_in_dump_cnt--; 1.630 +#endif 1.631 + 1.632 + tail(PROPERTIES_ELEMENT); 1.633 + tail(NODE_ELEMENT); 1.634 + } 1.635 +} 1.636 + 1.637 +void IdealGraphPrinter::walk_nodes(Node *start, bool edges, VectorSet* temp_set) { 1.638 + 1.639 + 1.640 + VectorSet visited(Thread::current()->resource_area()); 1.641 + GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL); 1.642 + nodeStack.push(start); 1.643 + visited.test_set(start->_idx); 1.644 + if (C->cfg() != NULL) { 1.645 + // once we have a CFG there are some nodes that aren't really 1.646 + // reachable but are in the CFG so add them here. 1.647 + for (uint i = 0; i < C->cfg()->number_of_blocks(); i++) { 1.648 + Block* block = C->cfg()->get_block(i); 1.649 + for (uint s = 0; s < block->number_of_nodes(); s++) { 1.650 + nodeStack.push(block->get_node(s)); 1.651 + } 1.652 + } 1.653 + } 1.654 + 1.655 + while(nodeStack.length() > 0) { 1.656 + 1.657 + Node *n = nodeStack.pop(); 1.658 + visit_node(n, edges, temp_set); 1.659 + 1.660 + if (_traverse_outs) { 1.661 + for (DUIterator i = n->outs(); n->has_out(i); i++) { 1.662 + Node* p = n->out(i); 1.663 + if (!visited.test_set(p->_idx)) { 1.664 + nodeStack.push(p); 1.665 + } 1.666 + } 1.667 + } 1.668 + 1.669 + for ( uint i = 0; i < n->len(); i++ ) { 1.670 + if ( n->in(i) ) { 1.671 + if (!visited.test_set(n->in(i)->_idx)) { 1.672 + nodeStack.push(n->in(i)); 1.673 + } 1.674 + } 1.675 + } 1.676 + } 1.677 +} 1.678 + 1.679 +void IdealGraphPrinter::print_method(Compile* compile, const char *name, int level, bool clear_nodes) { 1.680 + print(compile, name, (Node *)compile->root(), level, clear_nodes); 1.681 +} 1.682 + 1.683 +// Print current ideal graph 1.684 +void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) { 1.685 + 1.686 + if (!_current_method || !_should_send_method || level > PrintIdealGraphLevel) return; 1.687 + 1.688 + this->C = compile; 1.689 + 1.690 + // Warning, unsafe cast? 1.691 + _chaitin = (PhaseChaitin *)C->regalloc(); 1.692 + 1.693 + begin_head(GRAPH_ELEMENT); 1.694 + print_attr(GRAPH_NAME_PROPERTY, (const char *)name); 1.695 + end_head(); 1.696 + 1.697 + VectorSet temp_set(Thread::current()->resource_area()); 1.698 + 1.699 + head(NODES_ELEMENT); 1.700 + walk_nodes(node, false, &temp_set); 1.701 + tail(NODES_ELEMENT); 1.702 + 1.703 + head(EDGES_ELEMENT); 1.704 + walk_nodes(node, true, &temp_set); 1.705 + tail(EDGES_ELEMENT); 1.706 + if (C->cfg() != NULL) { 1.707 + head(CONTROL_FLOW_ELEMENT); 1.708 + for (uint i = 0; i < C->cfg()->number_of_blocks(); i++) { 1.709 + Block* block = C->cfg()->get_block(i); 1.710 + begin_head(BLOCK_ELEMENT); 1.711 + print_attr(BLOCK_NAME_PROPERTY, block->_pre_order); 1.712 + end_head(); 1.713 + 1.714 + head(SUCCESSORS_ELEMENT); 1.715 + for (uint s = 0; s < block->_num_succs; s++) { 1.716 + begin_elem(SUCCESSOR_ELEMENT); 1.717 + print_attr(BLOCK_NAME_PROPERTY, block->_succs[s]->_pre_order); 1.718 + end_elem(); 1.719 + } 1.720 + tail(SUCCESSORS_ELEMENT); 1.721 + 1.722 + head(NODES_ELEMENT); 1.723 + for (uint s = 0; s < block->number_of_nodes(); s++) { 1.724 + begin_elem(NODE_ELEMENT); 1.725 + print_attr(NODE_ID_PROPERTY, get_node_id(block->get_node(s))); 1.726 + end_elem(); 1.727 + } 1.728 + tail(NODES_ELEMENT); 1.729 + 1.730 + tail(BLOCK_ELEMENT); 1.731 + } 1.732 + tail(CONTROL_FLOW_ELEMENT); 1.733 + } 1.734 + tail(GRAPH_ELEMENT); 1.735 + output()->flush(); 1.736 +} 1.737 + 1.738 +extern const char *NodeClassNames[]; 1.739 + 1.740 +outputStream *IdealGraphPrinter::output() { 1.741 + return _xml; 1.742 +} 1.743 + 1.744 +#endif