Mercurial > hg > graal-compiler
annotate src/share/vm/opto/idealGraphPrinter.cpp @ 3992:d1bdeef3e3e2
7098282: G1: assert(interval >= 0) failed: Sanity check, referencePolicy.cpp: 76
Summary: There is a race between one thread successfully forwarding and copying the klass mirror for the SoftReference class (including the static master clock) and another thread attempting to use the master clock while attempting to discover a soft reference object. Maintain a shadow copy of the soft reference master clock and use the shadow during reference discovery and reference processing.
Reviewed-by: tonyp, brutisso, ysr
author | johnc |
---|---|
date | Wed, 12 Oct 2011 10:25:51 -0700 |
parents | c26de9aef2ed |
children | f03a3c8bd5e5 |
rev | line source |
---|---|
0 | 1 /* |
2403 | 2 * Copyright (c) 2007, 2011, 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 | |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3853
diff
changeset
|
378 void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { |
222 | 379 |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3853
diff
changeset
|
380 if (edges) { |
222 | 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_rematerialize) { | |
430 print_prop("rematerialize", "true"); | |
431 } | |
432 if (flags & Node::Flag_needs_anti_dependence_check) { | |
433 print_prop("needs_anti_dependence_check", "true"); | |
434 } | |
435 if (flags & Node::Flag_is_macro) { | |
436 print_prop("is_macro", "true"); | |
437 } | |
438 if (flags & Node::Flag_is_Con) { | |
439 print_prop("is_con", "true"); | |
440 } | |
441 if (flags & Node::Flag_is_cisc_alternate) { | |
442 print_prop("is_cisc_alternate", "true"); | |
443 } | |
444 if (flags & Node::Flag_is_dead_loop_safe) { | |
445 print_prop("is_dead_loop_safe", "true"); | |
446 } | |
447 if (flags & Node::Flag_may_be_short_branch) { | |
448 print_prop("may_be_short_branch", "true"); | |
449 } | |
450 | |
451 if (C->matcher() != NULL) { | |
452 if (C->matcher()->is_shared(node)) { | |
453 print_prop("is_shared", "true"); | |
454 } else { | |
455 print_prop("is_shared", "false"); | |
456 } | |
457 if (C->matcher()->is_dontcare(node)) { | |
458 print_prop("is_dontcare", "true"); | |
459 } else { | |
460 print_prop("is_dontcare", "false"); | |
461 } | |
462 | |
250
6ca61c728c2d
6712835: Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform")
never
parents:
222
diff
changeset
|
463 #ifdef ASSERT |
222 | 464 Node* old = C->matcher()->find_old_node(node); |
465 if (old != NULL) { | |
466 print_prop("old_node_idx", old->_idx); | |
467 } | |
250
6ca61c728c2d
6712835: Server compiler fails with assertion (loop_count < K,"infinite loop in PhaseIterGVN::transform")
never
parents:
222
diff
changeset
|
468 #endif |
222 | 469 } |
470 | |
471 if (node->is_Proj()) { | |
472 print_prop("con", (int)node->as_Proj()->_con); | |
473 } | |
474 | |
475 if (node->is_Mach()) { | |
476 print_prop("idealOpcode", (const char *)NodeClassNames[node->as_Mach()->ideal_Opcode()]); | |
477 } | |
478 | |
479 buffer[0] = 0; | |
480 stringStream s2(buffer, sizeof(buffer) - 1); | |
481 | |
482 node->dump_spec(&s2); | |
483 if (t != NULL && (t->isa_instptr() || t->isa_klassptr())) { | |
484 const TypeInstPtr *toop = t->isa_instptr(); | |
485 const TypeKlassPtr *tkls = t->isa_klassptr(); | |
486 ciKlass* klass = toop ? toop->klass() : (tkls ? tkls->klass() : NULL ); | |
487 if( klass && klass->is_loaded() && klass->is_interface() ) { | |
488 s2.print(" Interface:"); | |
489 } else if( toop ) { | |
490 s2.print(" Oop:"); | |
491 } else if( tkls ) { | |
492 s2.print(" Klass:"); | |
493 } | |
494 t->dump_on(&s2); | |
495 } else if( t == Type::MEMORY ) { | |
496 s2.print(" Memory:"); | |
497 MemNode::dump_adr_type(node, node->adr_type(), &s2); | |
498 } | |
499 | |
500 assert(s2.size() < sizeof(buffer), "size in range"); | |
501 print_prop("dump_spec", buffer); | |
502 | |
503 if (node->is_block_proj()) { | |
504 print_prop("is_block_proj", "true"); | |
505 } | |
506 | |
507 if (node->is_block_start()) { | |
508 print_prop("is_block_start", "true"); | |
509 } | |
510 | |
511 const char *short_name = "short_name"; | |
512 if (strcmp(node->Name(), "Parm") == 0 && node->as_Proj()->_con >= TypeFunc::Parms) { | |
513 int index = node->as_Proj()->_con - TypeFunc::Parms; | |
514 if (index >= 10) { | |
515 print_prop(short_name, "PA"); | |
516 } else { | |
517 sprintf(buffer, "P%d", index); | |
518 print_prop(short_name, buffer); | |
519 } | |
520 } else if (strcmp(node->Name(), "IfTrue") == 0) { | |
521 print_prop(short_name, "T"); | |
522 } else if (strcmp(node->Name(), "IfFalse") == 0) { | |
523 print_prop(short_name, "F"); | |
524 } else if ((node->is_Con() && node->is_Type()) || node->is_Proj()) { | |
525 | |
526 if (t->base() == Type::Int && t->is_int()->is_con()) { | |
527 const TypeInt *typeInt = t->is_int(); | |
528 assert(typeInt->is_con(), "must be constant"); | |
529 jint value = typeInt->get_con(); | |
530 | |
531 // max. 2 chars allowed | |
532 if (value >= -9 && value <= 99) { | |
533 sprintf(buffer, "%d", value); | |
534 print_prop(short_name, buffer); | |
535 } else { | |
536 print_prop(short_name, "I"); | |
537 } | |
538 } else if (t == Type::TOP) { | |
539 print_prop(short_name, "^"); | |
540 } else if (t->base() == Type::Long && t->is_long()->is_con()) { | |
541 const TypeLong *typeLong = t->is_long(); | |
542 assert(typeLong->is_con(), "must be constant"); | |
543 jlong value = typeLong->get_con(); | |
544 | |
545 // max. 2 chars allowed | |
546 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
|
547 sprintf(buffer, INT64_FORMAT, value); |
222 | 548 print_prop(short_name, buffer); |
549 } else { | |
550 print_prop(short_name, "L"); | |
551 } | |
552 } else if (t->base() == Type::KlassPtr) { | |
553 const TypeKlassPtr *typeKlass = t->is_klassptr(); | |
554 print_prop(short_name, "CP"); | |
555 } else if (t->base() == Type::Control) { | |
556 print_prop(short_name, "C"); | |
557 } else if (t->base() == Type::Memory) { | |
558 print_prop(short_name, "M"); | |
559 } else if (t->base() == Type::Abio) { | |
560 print_prop(short_name, "IO"); | |
561 } else if (t->base() == Type::Return_Address) { | |
562 print_prop(short_name, "RA"); | |
563 } else if (t->base() == Type::AnyPtr) { | |
564 print_prop(short_name, "P"); | |
565 } else if (t->base() == Type::RawPtr) { | |
566 print_prop(short_name, "RP"); | |
567 } else if (t->base() == Type::AryPtr) { | |
568 print_prop(short_name, "AP"); | |
569 } | |
570 } | |
571 | |
572 JVMState* caller = NULL; | |
573 if (node->is_SafePoint()) { | |
574 caller = node->as_SafePoint()->jvms(); | |
575 } else { | |
576 Node_Notes* notes = C->node_notes_at(node->_idx); | |
577 if (notes != NULL) { | |
578 caller = notes->jvms(); | |
579 } | |
580 } | |
581 | |
582 if (caller != NULL) { | |
583 stringStream bciStream; | |
2403 | 584 ciMethod* last = NULL; |
585 int last_bci; | |
222 | 586 while(caller) { |
2403 | 587 if (caller->has_method()) { |
588 last = caller->method(); | |
589 last_bci = caller->bci(); | |
590 } | |
222 | 591 bciStream.print("%d ", caller->bci()); |
592 caller = caller->caller(); | |
593 } | |
594 print_prop("bci", bciStream.as_string()); | |
2403 | 595 if (last != NULL && last->has_linenumber_table() && last_bci >= 0) { |
596 print_prop("line", last->line_number_from_bci(last_bci)); | |
597 } | |
598 } | |
599 | |
3388
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2403
diff
changeset
|
600 #ifdef ASSERT |
2403 | 601 if (node->debug_orig() != NULL) { |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3853
diff
changeset
|
602 temp_set->Clear(); |
2403 | 603 stringStream dorigStream; |
604 Node* dorig = node->debug_orig(); | |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3853
diff
changeset
|
605 while (dorig && temp_set->test_set(dorig->_idx)) { |
2403 | 606 dorigStream.print("%d ", dorig->_idx); |
607 } | |
608 print_prop("debug_orig", dorigStream.as_string()); | |
222 | 609 } |
3388
a80577f854f9
7045513: JSR 292 inlining causes crashes in methodHandleWalk.cpp
never
parents:
2403
diff
changeset
|
610 #endif |
222 | 611 |
612 if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) { | |
613 buffer[0] = 0; | |
614 _chaitin->dump_register(node, buffer); | |
615 print_prop("reg", buffer); | |
616 print_prop("lrg", _chaitin->n2lidx(node)); | |
617 } | |
618 | |
619 node->_in_dump_cnt--; | |
620 #endif | |
621 | |
622 tail(PROPERTIES_ELEMENT); | |
623 tail(NODE_ELEMENT); | |
624 } | |
625 } | |
626 | |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3853
diff
changeset
|
627 void IdealGraphPrinter::walk_nodes(Node *start, bool edges, VectorSet* temp_set) { |
0 | 628 |
629 | |
630 VectorSet visited(Thread::current()->resource_area()); | |
631 GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL); | |
632 nodeStack.push(start); | |
633 visited.test_set(start->_idx); | |
2403 | 634 if (C->cfg() != NULL) { |
635 // once we have a CFG there are some nodes that aren't really | |
636 // reachable but are in the CFG so add them here. | |
637 for (uint i = 0; i < C->cfg()->_blocks.size(); i++) { | |
638 Block *b = C->cfg()->_blocks[i]; | |
639 for (uint s = 0; s < b->_nodes.size(); s++) { | |
640 nodeStack.push(b->_nodes[s]); | |
641 } | |
642 } | |
643 } | |
644 | |
0 | 645 while(nodeStack.length() > 0) { |
646 | |
647 Node *n = nodeStack.pop(); | |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3853
diff
changeset
|
648 visit_node(n, edges, temp_set); |
0 | 649 |
650 if (_traverse_outs) { | |
651 for (DUIterator i = n->outs(); n->has_out(i); i++) { | |
652 Node* p = n->out(i); | |
653 if (!visited.test_set(p->_idx)) { | |
654 nodeStack.push(p); | |
655 } | |
656 } | |
657 } | |
658 | |
659 for ( uint i = 0; i < n->len(); i++ ) { | |
660 if ( n->in(i) ) { | |
661 if (!visited.test_set(n->in(i)->_idx)) { | |
662 nodeStack.push(n->in(i)); | |
663 } | |
664 } | |
665 } | |
666 } | |
667 } | |
668 | |
669 void IdealGraphPrinter::print_method(Compile* compile, const char *name, int level, bool clear_nodes) { | |
670 print(compile, name, (Node *)compile->root(), level, clear_nodes); | |
671 } | |
672 | |
673 // Print current ideal graph | |
674 void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) { | |
675 | |
676 if (!_current_method || !_should_send_method || level > PrintIdealGraphLevel) return; | |
677 | |
222 | 678 this->C = compile; |
0 | 679 |
680 // Warning, unsafe cast? | |
222 | 681 _chaitin = (PhaseChaitin *)C->regalloc(); |
0 | 682 |
222 | 683 begin_head(GRAPH_ELEMENT); |
684 print_attr(GRAPH_NAME_PROPERTY, (const char *)name); | |
685 end_head(); | |
0 | 686 |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3853
diff
changeset
|
687 VectorSet temp_set(Thread::current()->resource_area()); |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3853
diff
changeset
|
688 |
222 | 689 head(NODES_ELEMENT); |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3853
diff
changeset
|
690 walk_nodes(node, false, &temp_set); |
222 | 691 tail(NODES_ELEMENT); |
0 | 692 |
222 | 693 head(EDGES_ELEMENT); |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3853
diff
changeset
|
694 walk_nodes(node, true, &temp_set); |
222 | 695 tail(EDGES_ELEMENT); |
696 if (C->cfg() != NULL) { | |
697 head(CONTROL_FLOW_ELEMENT); | |
698 for (uint i = 0; i < C->cfg()->_blocks.size(); i++) { | |
699 Block *b = C->cfg()->_blocks[i]; | |
700 begin_head(BLOCK_ELEMENT); | |
701 print_attr(BLOCK_NAME_PROPERTY, b->_pre_order); | |
702 end_head(); | |
0 | 703 |
222 | 704 head(SUCCESSORS_ELEMENT); |
2403 | 705 for (uint s = 0; s < b->_num_succs; s++) { |
222 | 706 begin_elem(SUCCESSOR_ELEMENT); |
707 print_attr(BLOCK_NAME_PROPERTY, b->_succs[s]->_pre_order); | |
708 end_elem(); | |
0 | 709 } |
222 | 710 tail(SUCCESSORS_ELEMENT); |
0 | 711 |
2403 | 712 head(NODES_ELEMENT); |
713 for (uint s = 0; s < b->_nodes.size(); s++) { | |
714 begin_elem(NODE_ELEMENT); | |
715 print_attr(NODE_ID_PROPERTY, get_node_id(b->_nodes[s])); | |
716 end_elem(); | |
717 } | |
718 tail(NODES_ELEMENT); | |
719 | |
222 | 720 tail(BLOCK_ELEMENT); |
721 } | |
722 tail(CONTROL_FLOW_ELEMENT); | |
0 | 723 } |
222 | 724 tail(GRAPH_ELEMENT); |
725 output()->flush(); | |
0 | 726 } |
727 | |
728 extern const char *NodeClassNames[]; | |
729 | |
730 outputStream *IdealGraphPrinter::output() { | |
222 | 731 return _xml; |
0 | 732 } |
733 | |
734 #endif |