Mercurial > hg > truffle
annotate src/share/vm/opto/idealGraphPrinter.cpp @ 1994:6cd6d394f280
7001033: assert(gch->gc_cause() == GCCause::_scavenge_alot || !gch->incremental_collection_failed())
7002546: regression on SpecJbb2005 on 7b118 comparing to 7b117 on small heaps
Summary: Relaxed assertion checking related to incremental_collection_failed flag to allow for ExplicitGCInvokesConcurrent behaviour where we do not want a failing scavenge to bail to a stop-world collection. Parameterized incremental_collection_will_fail() so we can selectively use, or not use, as appropriate, the statistical prediction at specific use sites. This essentially reverts the scavenge bail-out logic to what it was prior to some recent changes that had inadvertently started using the statistical prediction which can be noisy in the presence of bursty loads. Added some associated verbose non-product debugging messages.
Reviewed-by: johnc, tonyp
author | ysr |
---|---|
date | Tue, 07 Dec 2010 21:55:53 -0800 |
parents | f95d63e2154a |
children | 1927db75dd85 |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1490
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1490
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1490
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "opto/chaitin.hpp" | |
27 #include "opto/idealGraphPrinter.hpp" | |
28 #include "opto/machnode.hpp" | |
29 #include "opto/parse.hpp" | |
30 #include "runtime/threadCritical.hpp" | |
0 | 31 |
32 #ifndef PRODUCT | |
33 | |
34 // Constants | |
35 // Keep consistent with Java constants | |
36 const char *IdealGraphPrinter::INDENT = " "; | |
37 const char *IdealGraphPrinter::TOP_ELEMENT = "graphDocument"; | |
38 const char *IdealGraphPrinter::GROUP_ELEMENT = "group"; | |
39 const char *IdealGraphPrinter::GRAPH_ELEMENT = "graph"; | |
40 const char *IdealGraphPrinter::PROPERTIES_ELEMENT = "properties"; | |
41 const char *IdealGraphPrinter::EDGES_ELEMENT = "edges"; | |
42 const char *IdealGraphPrinter::PROPERTY_ELEMENT = "p"; | |
43 const char *IdealGraphPrinter::EDGE_ELEMENT = "edge"; | |
44 const char *IdealGraphPrinter::NODE_ELEMENT = "node"; | |
45 const char *IdealGraphPrinter::NODES_ELEMENT = "nodes"; | |
46 const char *IdealGraphPrinter::REMOVE_EDGE_ELEMENT = "removeEdge"; | |
47 const char *IdealGraphPrinter::REMOVE_NODE_ELEMENT = "removeNode"; | |
48 const char *IdealGraphPrinter::METHOD_NAME_PROPERTY = "name"; | |
49 const char *IdealGraphPrinter::METHOD_IS_PUBLIC_PROPERTY = "public"; | |
50 const char *IdealGraphPrinter::METHOD_IS_STATIC_PROPERTY = "static"; | |
51 const char *IdealGraphPrinter::TRUE_VALUE = "true"; | |
52 const char *IdealGraphPrinter::NODE_NAME_PROPERTY = "name"; | |
53 const char *IdealGraphPrinter::EDGE_NAME_PROPERTY = "name"; | |
54 const char *IdealGraphPrinter::NODE_ID_PROPERTY = "id"; | |
55 const char *IdealGraphPrinter::FROM_PROPERTY = "from"; | |
56 const char *IdealGraphPrinter::TO_PROPERTY = "to"; | |
57 const char *IdealGraphPrinter::PROPERTY_NAME_PROPERTY = "name"; | |
58 const char *IdealGraphPrinter::GRAPH_NAME_PROPERTY = "name"; | |
59 const char *IdealGraphPrinter::INDEX_PROPERTY = "index"; | |
60 const char *IdealGraphPrinter::METHOD_ELEMENT = "method"; | |
61 const char *IdealGraphPrinter::INLINE_ELEMENT = "inline"; | |
62 const char *IdealGraphPrinter::BYTECODES_ELEMENT = "bytecodes"; | |
63 const char *IdealGraphPrinter::METHOD_BCI_PROPERTY = "bci"; | |
64 const char *IdealGraphPrinter::METHOD_SHORT_NAME_PROPERTY = "shortName"; | |
65 const char *IdealGraphPrinter::CONTROL_FLOW_ELEMENT = "controlFlow"; | |
66 const char *IdealGraphPrinter::BLOCK_NAME_PROPERTY = "name"; | |
67 const char *IdealGraphPrinter::BLOCK_DOMINATOR_PROPERTY = "dom"; | |
68 const char *IdealGraphPrinter::BLOCK_ELEMENT = "block"; | |
69 const char *IdealGraphPrinter::SUCCESSORS_ELEMENT = "successors"; | |
70 const char *IdealGraphPrinter::SUCCESSOR_ELEMENT = "successor"; | |
71 const char *IdealGraphPrinter::ASSEMBLY_ELEMENT = "assembly"; | |
72 | |
73 int IdealGraphPrinter::_file_count = 0; | |
74 | |
75 IdealGraphPrinter *IdealGraphPrinter::printer() { | |
76 if (PrintIdealGraphLevel == 0) return NULL; | |
77 | |
78 JavaThread *thread = JavaThread::current(); | |
79 if (!thread->is_Compiler_thread()) return NULL; | |
80 | |
81 CompilerThread *compiler_thread = (CompilerThread *)thread; | |
82 if (compiler_thread->ideal_graph_printer() == NULL) { | |
83 IdealGraphPrinter *printer = new IdealGraphPrinter(); | |
84 compiler_thread->set_ideal_graph_printer(printer); | |
85 } | |
86 | |
87 return compiler_thread->ideal_graph_printer(); | |
88 } | |
89 | |
90 void IdealGraphPrinter::clean_up() { | |
91 JavaThread *p; | |
92 for (p = Threads::first(); p; p = p->next()) { | |
93 if (p->is_Compiler_thread()) { | |
94 CompilerThread *c = (CompilerThread *)p; | |
95 IdealGraphPrinter *printer = c->ideal_graph_printer(); | |
96 if (printer) { | |
97 delete printer; | |
98 } | |
99 c->set_ideal_graph_printer(NULL); | |
100 } | |
101 } | |
102 } | |
103 | |
104 // Constructor, either file or network output | |
105 IdealGraphPrinter::IdealGraphPrinter() { | |
106 | |
222 | 107 // By default dump both ins and outs since dead or unreachable code |
108 // needs to appear in the graph. There are also some special cases | |
109 // in the mach where kill projections have no users but should | |
110 // appear in the dump. | |
111 _traverse_outs = true; | |
0 | 112 _should_send_method = true; |
113 _output = NULL; | |
114 buffer[0] = 0; | |
115 _depth = 0; | |
116 _current_method = NULL; | |
117 assert(!_current_method, "current method must be initialized to NULL"); | |
222 | 118 _stream = NULL; |
0 | 119 |
120 if (PrintIdealGraphFile != NULL) { | |
121 ThreadCritical tc; | |
122 // User wants all output to go to files | |
123 if (_file_count != 0) { | |
124 ResourceMark rm; | |
125 stringStream st; | |
126 const char* dot = strrchr(PrintIdealGraphFile, '.'); | |
127 if (dot) { | |
128 st.write(PrintIdealGraphFile, dot - PrintIdealGraphFile); | |
129 st.print("%d%s", _file_count, dot); | |
130 } else { | |
131 st.print("%s%d", PrintIdealGraphFile, _file_count); | |
132 } | |
222 | 133 fileStream *stream = new (ResourceObj::C_HEAP) fileStream(st.as_string()); |
134 _output = stream; | |
0 | 135 } else { |
222 | 136 fileStream *stream = new (ResourceObj::C_HEAP) fileStream(PrintIdealGraphFile); |
137 _output = stream; | |
0 | 138 } |
139 _file_count++; | |
140 } else { | |
222 | 141 _stream = new (ResourceObj::C_HEAP) networkStream(); |
142 | |
0 | 143 // Try to connect to visualizer |
144 if (_stream->connect(PrintIdealGraphAddress, PrintIdealGraphPort)) { | |
145 char c = 0; | |
146 _stream->read(&c, 1); | |
147 if (c != 'y') { | |
148 tty->print_cr("Client available, but does not want to receive data!"); | |
149 _stream->close(); | |
150 delete _stream; | |
151 _stream = NULL; | |
152 return; | |
153 } | |
154 _output = _stream; | |
155 } else { | |
156 // It would be nice if we could shut down cleanly but it should | |
157 // be an error if we can't connect to the visualizer. | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
579
diff
changeset
|
158 fatal(err_msg("Couldn't connect to visualizer at %s:%d", |
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
579
diff
changeset
|
159 PrintIdealGraphAddress, PrintIdealGraphPort)); |
0 | 160 } |
161 } | |
162 | |
222 | 163 _xml = new (ResourceObj::C_HEAP) xmlStream(_output); |
164 | |
165 head(TOP_ELEMENT); | |
0 | 166 } |
167 | |
168 // Destructor, close file or network stream | |
169 IdealGraphPrinter::~IdealGraphPrinter() { | |
170 | |
222 | 171 tail(TOP_ELEMENT); |
172 | |
173 // tty->print_cr("Walk time: %d", (int)_walk_time.milliseconds()); | |
174 // tty->print_cr("Output time: %d", (int)_output_time.milliseconds()); | |
175 // tty->print_cr("Build blocks time: %d", (int)_build_blocks_time.milliseconds()); | |
176 | |
177 if(_xml) { | |
178 delete _xml; | |
179 _xml = NULL; | |
180 } | |
0 | 181 |
182 if (_stream) { | |
183 delete _stream; | |
184 if (_stream == _output) { | |
185 _output = NULL; | |
186 } | |
187 _stream = NULL; | |
188 } | |
189 | |
190 if (_output) { | |
191 delete _output; | |
192 _output = NULL; | |
193 } | |
194 } | |
195 | |
196 | |
222 | 197 void IdealGraphPrinter::begin_elem(const char *s) { |
198 _xml->begin_elem(s); | |
199 } | |
200 | |
201 void IdealGraphPrinter::end_elem() { | |
202 _xml->end_elem(); | |
203 } | |
0 | 204 |
222 | 205 void IdealGraphPrinter::begin_head(const char *s) { |
206 _xml->begin_head(s); | |
207 } | |
0 | 208 |
222 | 209 void IdealGraphPrinter::end_head() { |
210 _xml->end_head(); | |
211 } | |
0 | 212 |
222 | 213 void IdealGraphPrinter::print_attr(const char *name, intptr_t val) { |
214 stringStream stream; | |
215 stream.print(INTX_FORMAT, val); | |
216 print_attr(name, stream.as_string()); | |
217 } | |
0 | 218 |
222 | 219 void IdealGraphPrinter::print_attr(const char *name, const char *val) { |
220 _xml->print(" %s='", name); | |
221 text(val); | |
222 _xml->print("'"); | |
223 } | |
0 | 224 |
222 | 225 void IdealGraphPrinter::head(const char *name) { |
226 _xml->head(name); | |
227 } | |
228 | |
229 void IdealGraphPrinter::tail(const char *name) { | |
230 _xml->tail(name); | |
231 } | |
0 | 232 |
222 | 233 void IdealGraphPrinter::text(const char *s) { |
234 _xml->text(s); | |
235 } | |
236 | |
237 void IdealGraphPrinter::print_prop(const char *name, int val) { | |
0 | 238 |
222 | 239 stringStream stream; |
240 stream.print("%d", val); | |
241 print_prop(name, stream.as_string()); | |
242 } | |
243 | |
244 void IdealGraphPrinter::print_prop(const char *name, const char *val) { | |
245 begin_head(PROPERTY_ELEMENT); | |
246 print_attr(PROPERTY_NAME_PROPERTY, name); | |
247 end_head(); | |
248 text(val); | |
249 tail(PROPERTY_ELEMENT); | |
0 | 250 } |
251 | |
252 void IdealGraphPrinter::print_method(ciMethod *method, int bci, InlineTree *tree) { | |
222 | 253 begin_head(METHOD_ELEMENT); |
0 | 254 |
255 stringStream str; | |
256 method->print_name(&str); | |
257 | |
258 stringStream shortStr; | |
259 method->print_short_name(&shortStr); | |
260 | |
222 | 261 print_attr(METHOD_NAME_PROPERTY, str.as_string()); |
262 print_attr(METHOD_SHORT_NAME_PROPERTY, shortStr.as_string()); | |
263 print_attr(METHOD_BCI_PROPERTY, bci); | |
0 | 264 |
222 | 265 end_head(); |
0 | 266 |
222 | 267 head(BYTECODES_ELEMENT); |
0 | 268 output()->print_cr("<![CDATA["); |
269 method->print_codes_on(output()); | |
270 output()->print_cr("]]>"); | |
222 | 271 tail(BYTECODES_ELEMENT); |
0 | 272 |
222 | 273 head(INLINE_ELEMENT); |
0 | 274 if (tree != NULL) { |
275 GrowableArray<InlineTree *> subtrees = tree->subtrees(); | |
276 for (int i = 0; i < subtrees.length(); i++) { | |
277 print_inline_tree(subtrees.at(i)); | |
278 } | |
279 } | |
222 | 280 tail(INLINE_ELEMENT); |
0 | 281 |
222 | 282 tail(METHOD_ELEMENT); |
0 | 283 output()->flush(); |
284 } | |
285 | |
286 void IdealGraphPrinter::print_inline_tree(InlineTree *tree) { | |
287 | |
288 if (tree == NULL) return; | |
289 | |
290 ciMethod *method = tree->method(); | |
291 print_method(tree->method(), tree->caller_bci(), tree); | |
292 | |
293 } | |
294 | |
295 void IdealGraphPrinter::print_inlining(Compile* compile) { | |
296 | |
297 // Print inline tree | |
298 if (_should_send_method) { | |
299 InlineTree *inlineTree = compile->ilt(); | |
300 if (inlineTree != NULL) { | |
301 print_inline_tree(inlineTree); | |
302 } else { | |
303 // print this method only | |
304 } | |
305 } | |
306 } | |
307 | |
308 // Has to be called whenever a method is compiled | |
309 void IdealGraphPrinter::begin_method(Compile* compile) { | |
310 | |
311 ciMethod *method = compile->method(); | |
312 assert(_output, "output stream must exist!"); | |
313 assert(method, "null methods are not allowed!"); | |
314 assert(!_current_method, "current method must be null!"); | |
315 | |
222 | 316 head(GROUP_ELEMENT); |
0 | 317 |
222 | 318 head(PROPERTIES_ELEMENT); |
0 | 319 |
320 // Print properties | |
321 // Add method name | |
322 stringStream strStream; | |
323 method->print_name(&strStream); | |
222 | 324 print_prop(METHOD_NAME_PROPERTY, strStream.as_string()); |
0 | 325 |
326 if (method->flags().is_public()) { | |
222 | 327 print_prop(METHOD_IS_PUBLIC_PROPERTY, TRUE_VALUE); |
0 | 328 } |
329 | |
330 if (method->flags().is_static()) { | |
222 | 331 print_prop(METHOD_IS_STATIC_PROPERTY, TRUE_VALUE); |
0 | 332 } |
333 | |
222 | 334 tail(PROPERTIES_ELEMENT); |
0 | 335 |
336 if (_stream) { | |
337 char answer = 0; | |
222 | 338 _xml->flush(); |
0 | 339 int result = _stream->read(&answer, 1); |
340 _should_send_method = (answer == 'y'); | |
341 } | |
342 | |
343 this->_current_method = method; | |
344 | |
222 | 345 _xml->flush(); |
0 | 346 } |
347 | |
348 // Has to be called whenever a method has finished compilation | |
349 void IdealGraphPrinter::end_method() { | |
350 | |
351 nmethod* method = (nmethod*)this->_current_method->code(); | |
352 | |
222 | 353 tail(GROUP_ELEMENT); |
0 | 354 _current_method = NULL; |
222 | 355 _xml->flush(); |
0 | 356 } |
357 | |
358 // Print indent | |
359 void IdealGraphPrinter::print_indent() { | |
222 | 360 tty->print_cr("printing ident %d", _depth); |
0 | 361 for (int i = 0; i < _depth; i++) { |
222 | 362 _xml->print(INDENT); |
0 | 363 } |
364 } | |
365 | |
366 bool IdealGraphPrinter::traverse_outs() { | |
367 return _traverse_outs; | |
368 } | |
369 | |
370 void IdealGraphPrinter::set_traverse_outs(bool b) { | |
371 _traverse_outs = b; | |
372 } | |
373 | |
222 | 374 intptr_t IdealGraphPrinter::get_node_id(Node *n) { |
375 return (intptr_t)(n); | |
376 } | |
377 | |
378 void IdealGraphPrinter::visit_node(Node *n, void *param) { | |
379 | |
380 if(param) { | |
381 | |
382 // Output edge | |
383 intptr_t dest_id = get_node_id(n); | |
384 for ( uint i = 0; i < n->len(); i++ ) { | |
385 if ( n->in(i) ) { | |
386 Node *source = n->in(i); | |
387 begin_elem(EDGE_ELEMENT); | |
388 intptr_t source_id = get_node_id(source); | |
389 print_attr(FROM_PROPERTY, source_id); | |
390 print_attr(TO_PROPERTY, dest_id); | |
391 print_attr(INDEX_PROPERTY, i); | |
392 end_elem(); | |
393 } | |
394 } | |
395 | |
396 } else { | |
397 | |
398 // Output node | |
399 begin_head(NODE_ELEMENT); | |
400 print_attr(NODE_ID_PROPERTY, get_node_id(n)); | |
401 end_head(); | |
402 | |
403 head(PROPERTIES_ELEMENT); | |
404 | |
405 Node *node = n; | |
406 #ifndef PRODUCT | |
407 node->_in_dump_cnt++; | |
408 print_prop(NODE_NAME_PROPERTY, (const char *)node->Name()); | |
409 const Type *t = node->bottom_type(); | |
410 print_prop("type", (const char *)Type::msg[t->base()]); | |
411 print_prop("idx", node->_idx); | |
412 #ifdef ASSERT | |
413 print_prop("debug_idx", node->_debug_idx); | |
414 #endif | |
415 | |
416 if(C->cfg() != NULL) { | |
417 Block *block = C->cfg()->_bbs[node->_idx]; | |
418 if(block == NULL) { | |
419 print_prop("block", C->cfg()->_blocks[0]->_pre_order); | |
420 } else { | |
421 print_prop("block", block->_pre_order); | |
422 } | |
423 } | |
424 | |
425 const jushort flags = node->flags(); | |
426 if (flags & Node::Flag_is_Copy) { | |
427 print_prop("is_copy", "true"); | |
428 } | |
429 if (flags & Node::Flag_is_Call) { | |
430 print_prop("is_call", "true"); | |
431 } | |
432 if (flags & Node::Flag_rematerialize) { | |
433 print_prop("rematerialize", "true"); | |
434 } | |
435 if (flags & Node::Flag_needs_anti_dependence_check) { | |
436 print_prop("needs_anti_dependence_check", "true"); | |
437 } | |
438 if (flags & Node::Flag_is_macro) { | |
439 print_prop("is_macro", "true"); | |
440 } | |
441 if (flags & Node::Flag_is_Con) { | |
442 print_prop("is_con", "true"); | |
443 } | |
444 if (flags & Node::Flag_is_cisc_alternate) { | |
445 print_prop("is_cisc_alternate", "true"); | |
446 } | |
447 if (flags & Node::Flag_is_Branch) { | |
448 print_prop("is_branch", "true"); | |
449 } | |
450 if (flags & Node::Flag_is_block_start) { | |
451 print_prop("is_block_start", "true"); | |
452 } | |
453 if (flags & Node::Flag_is_Goto) { | |
454 print_prop("is_goto", "true"); | |
455 } | |
456 if (flags & Node::Flag_is_dead_loop_safe) { | |
457 print_prop("is_dead_loop_safe", "true"); | |
458 } | |
459 if (flags & Node::Flag_may_be_short_branch) { | |
460 print_prop("may_be_short_branch", "true"); | |
461 } | |
462 if (flags & Node::Flag_is_safepoint_node) { | |
463 print_prop("is_safepoint_node", "true"); | |
464 } | |
465 if (flags & Node::Flag_is_pc_relative) { | |
466 print_prop("is_pc_relative", "true"); | |
467 } | |
468 | |
469 if (C->matcher() != NULL) { | |
470 if (C->matcher()->is_shared(node)) { | |
471 print_prop("is_shared", "true"); | |
472 } else { | |
473 print_prop("is_shared", "false"); | |
474 } | |
475 if (C->matcher()->is_dontcare(node)) { | |
476 print_prop("is_dontcare", "true"); | |
477 } else { | |
478 print_prop("is_dontcare", "false"); | |
479 } | |
480 | |
250
6ca61c728c2d
6712835: Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform")
never
parents:
222
diff
changeset
|
481 #ifdef ASSERT |
222 | 482 Node* old = C->matcher()->find_old_node(node); |
483 if (old != NULL) { | |
484 print_prop("old_node_idx", old->_idx); | |
485 } | |
250
6ca61c728c2d
6712835: Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform")
never
parents:
222
diff
changeset
|
486 #endif |
222 | 487 } |
488 | |
489 if (node->is_Proj()) { | |
490 print_prop("con", (int)node->as_Proj()->_con); | |
491 } | |
492 | |
493 if (node->is_Mach()) { | |
494 print_prop("idealOpcode", (const char *)NodeClassNames[node->as_Mach()->ideal_Opcode()]); | |
495 } | |
496 | |
497 buffer[0] = 0; | |
498 stringStream s2(buffer, sizeof(buffer) - 1); | |
499 | |
500 node->dump_spec(&s2); | |
501 if (t != NULL && (t->isa_instptr() || t->isa_klassptr())) { | |
502 const TypeInstPtr *toop = t->isa_instptr(); | |
503 const TypeKlassPtr *tkls = t->isa_klassptr(); | |
504 ciKlass* klass = toop ? toop->klass() : (tkls ? tkls->klass() : NULL ); | |
505 if( klass && klass->is_loaded() && klass->is_interface() ) { | |
506 s2.print(" Interface:"); | |
507 } else if( toop ) { | |
508 s2.print(" Oop:"); | |
509 } else if( tkls ) { | |
510 s2.print(" Klass:"); | |
511 } | |
512 t->dump_on(&s2); | |
513 } else if( t == Type::MEMORY ) { | |
514 s2.print(" Memory:"); | |
515 MemNode::dump_adr_type(node, node->adr_type(), &s2); | |
516 } | |
517 | |
518 assert(s2.size() < sizeof(buffer), "size in range"); | |
519 print_prop("dump_spec", buffer); | |
520 | |
521 if (node->is_block_proj()) { | |
522 print_prop("is_block_proj", "true"); | |
523 } | |
524 | |
525 if (node->is_block_start()) { | |
526 print_prop("is_block_start", "true"); | |
527 } | |
528 | |
529 const char *short_name = "short_name"; | |
530 if (strcmp(node->Name(), "Parm") == 0 && node->as_Proj()->_con >= TypeFunc::Parms) { | |
531 int index = node->as_Proj()->_con - TypeFunc::Parms; | |
532 if (index >= 10) { | |
533 print_prop(short_name, "PA"); | |
534 } else { | |
535 sprintf(buffer, "P%d", index); | |
536 print_prop(short_name, buffer); | |
537 } | |
538 } else if (strcmp(node->Name(), "IfTrue") == 0) { | |
539 print_prop(short_name, "T"); | |
540 } else if (strcmp(node->Name(), "IfFalse") == 0) { | |
541 print_prop(short_name, "F"); | |
542 } else if ((node->is_Con() && node->is_Type()) || node->is_Proj()) { | |
543 | |
544 if (t->base() == Type::Int && t->is_int()->is_con()) { | |
545 const TypeInt *typeInt = t->is_int(); | |
546 assert(typeInt->is_con(), "must be constant"); | |
547 jint value = typeInt->get_con(); | |
548 | |
549 // max. 2 chars allowed | |
550 if (value >= -9 && value <= 99) { | |
551 sprintf(buffer, "%d", value); | |
552 print_prop(short_name, buffer); | |
553 } else { | |
554 print_prop(short_name, "I"); | |
555 } | |
556 } else if (t == Type::TOP) { | |
557 print_prop(short_name, "^"); | |
558 } else if (t->base() == Type::Long && t->is_long()->is_con()) { | |
559 const TypeLong *typeLong = t->is_long(); | |
560 assert(typeLong->is_con(), "must be constant"); | |
561 jlong value = typeLong->get_con(); | |
562 | |
563 // max. 2 chars allowed | |
564 if (value >= -9 && value <= 99) { | |
513
2328d1d3f8cf
6781583: Hotspot build fails on linux 64 bit platform with gcc 4.3.2
xlu
parents:
337
diff
changeset
|
565 sprintf(buffer, INT64_FORMAT, value); |
222 | 566 print_prop(short_name, buffer); |
567 } else { | |
568 print_prop(short_name, "L"); | |
569 } | |
570 } else if (t->base() == Type::KlassPtr) { | |
571 const TypeKlassPtr *typeKlass = t->is_klassptr(); | |
572 print_prop(short_name, "CP"); | |
573 } else if (t->base() == Type::Control) { | |
574 print_prop(short_name, "C"); | |
575 } else if (t->base() == Type::Memory) { | |
576 print_prop(short_name, "M"); | |
577 } else if (t->base() == Type::Abio) { | |
578 print_prop(short_name, "IO"); | |
579 } else if (t->base() == Type::Return_Address) { | |
580 print_prop(short_name, "RA"); | |
581 } else if (t->base() == Type::AnyPtr) { | |
582 print_prop(short_name, "P"); | |
583 } else if (t->base() == Type::RawPtr) { | |
584 print_prop(short_name, "RP"); | |
585 } else if (t->base() == Type::AryPtr) { | |
586 print_prop(short_name, "AP"); | |
587 } | |
588 } | |
589 | |
590 JVMState* caller = NULL; | |
591 if (node->is_SafePoint()) { | |
592 caller = node->as_SafePoint()->jvms(); | |
593 } else { | |
594 Node_Notes* notes = C->node_notes_at(node->_idx); | |
595 if (notes != NULL) { | |
596 caller = notes->jvms(); | |
597 } | |
598 } | |
599 | |
600 if (caller != NULL) { | |
601 stringStream bciStream; | |
602 while(caller) { | |
603 bciStream.print("%d ", caller->bci()); | |
604 caller = caller->caller(); | |
605 } | |
606 print_prop("bci", bciStream.as_string()); | |
607 } | |
608 | |
609 if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) { | |
610 buffer[0] = 0; | |
611 _chaitin->dump_register(node, buffer); | |
612 print_prop("reg", buffer); | |
613 print_prop("lrg", _chaitin->n2lidx(node)); | |
614 } | |
615 | |
616 node->_in_dump_cnt--; | |
617 #endif | |
618 | |
619 tail(PROPERTIES_ELEMENT); | |
620 tail(NODE_ELEMENT); | |
621 } | |
622 } | |
623 | |
624 void IdealGraphPrinter::walk_nodes(Node *start, void *param) { | |
0 | 625 |
626 | |
627 VectorSet visited(Thread::current()->resource_area()); | |
628 GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL); | |
629 nodeStack.push(start); | |
630 visited.test_set(start->_idx); | |
631 while(nodeStack.length() > 0) { | |
632 | |
633 Node *n = nodeStack.pop(); | |
222 | 634 visit_node(n, param); |
0 | 635 |
636 if (_traverse_outs) { | |
637 for (DUIterator i = n->outs(); n->has_out(i); i++) { | |
638 Node* p = n->out(i); | |
639 if (!visited.test_set(p->_idx)) { | |
640 nodeStack.push(p); | |
641 } | |
642 } | |
643 } | |
644 | |
645 for ( uint i = 0; i < n->len(); i++ ) { | |
646 if ( n->in(i) ) { | |
647 if (!visited.test_set(n->in(i)->_idx)) { | |
648 nodeStack.push(n->in(i)); | |
649 } | |
650 } | |
651 } | |
652 } | |
653 } | |
654 | |
655 void IdealGraphPrinter::print_method(Compile* compile, const char *name, int level, bool clear_nodes) { | |
656 print(compile, name, (Node *)compile->root(), level, clear_nodes); | |
657 } | |
658 | |
659 // Print current ideal graph | |
660 void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) { | |
661 | |
662 if (!_current_method || !_should_send_method || level > PrintIdealGraphLevel) return; | |
663 | |
222 | 664 this->C = compile; |
0 | 665 |
666 // Warning, unsafe cast? | |
222 | 667 _chaitin = (PhaseChaitin *)C->regalloc(); |
0 | 668 |
222 | 669 begin_head(GRAPH_ELEMENT); |
670 print_attr(GRAPH_NAME_PROPERTY, (const char *)name); | |
671 end_head(); | |
0 | 672 |
222 | 673 head(NODES_ELEMENT); |
674 walk_nodes(node, NULL); | |
675 tail(NODES_ELEMENT); | |
0 | 676 |
222 | 677 head(EDGES_ELEMENT); |
678 walk_nodes(node, (void *)1); | |
679 tail(EDGES_ELEMENT); | |
680 if (C->cfg() != NULL) { | |
681 head(CONTROL_FLOW_ELEMENT); | |
682 for (uint i = 0; i < C->cfg()->_blocks.size(); i++) { | |
683 Block *b = C->cfg()->_blocks[i]; | |
684 begin_head(BLOCK_ELEMENT); | |
685 print_attr(BLOCK_NAME_PROPERTY, b->_pre_order); | |
686 end_head(); | |
0 | 687 |
222 | 688 head(SUCCESSORS_ELEMENT); |
689 for (uint s = 0; s < C->cfg()->_blocks[i]->_num_succs; s++) { | |
690 begin_elem(SUCCESSOR_ELEMENT); | |
691 print_attr(BLOCK_NAME_PROPERTY, b->_succs[s]->_pre_order); | |
692 end_elem(); | |
0 | 693 } |
222 | 694 tail(SUCCESSORS_ELEMENT); |
0 | 695 |
222 | 696 tail(BLOCK_ELEMENT); |
697 } | |
0 | 698 |
222 | 699 tail(CONTROL_FLOW_ELEMENT); |
0 | 700 } |
222 | 701 tail(GRAPH_ELEMENT); |
702 output()->flush(); | |
0 | 703 } |
704 | |
705 extern const char *NodeClassNames[]; | |
706 | |
707 outputStream *IdealGraphPrinter::output() { | |
222 | 708 return _xml; |
0 | 709 } |
710 | |
711 #endif |