Mercurial > hg > truffle
comparison src/share/vm/opto/idealGraphPrinter.cpp @ 222:2a1a77d3458f
6718676: putback for 6604014 is incomplete
Reviewed-by: kvn, jrose
author | never |
---|---|
date | Tue, 24 Jun 2008 16:00:14 -0700 |
parents | a61af66fc99e |
children | 6ca61c728c2d |
comparison
equal
deleted
inserted
replaced
221:1e026f8da827 | 222:2a1a77d3458f |
---|---|
98 } | 98 } |
99 | 99 |
100 // Constructor, either file or network output | 100 // Constructor, either file or network output |
101 IdealGraphPrinter::IdealGraphPrinter() { | 101 IdealGraphPrinter::IdealGraphPrinter() { |
102 | 102 |
103 _traverse_outs = false; | 103 // By default dump both ins and outs since dead or unreachable code |
104 // needs to appear in the graph. There are also some special cases | |
105 // in the mach where kill projections have no users but should | |
106 // appear in the dump. | |
107 _traverse_outs = true; | |
104 _should_send_method = true; | 108 _should_send_method = true; |
105 _output = NULL; | 109 _output = NULL; |
106 buffer[0] = 0; | 110 buffer[0] = 0; |
107 _depth = 0; | 111 _depth = 0; |
108 _current_method = NULL; | 112 _current_method = NULL; |
109 assert(!_current_method, "current method must be initialized to NULL"); | 113 assert(!_current_method, "current method must be initialized to NULL"); |
110 _arena = new Arena(); | 114 _stream = NULL; |
111 | |
112 _stream = new (ResourceObj::C_HEAP) networkStream(); | |
113 | 115 |
114 if (PrintIdealGraphFile != NULL) { | 116 if (PrintIdealGraphFile != NULL) { |
115 ThreadCritical tc; | 117 ThreadCritical tc; |
116 // User wants all output to go to files | 118 // User wants all output to go to files |
117 if (_file_count != 0) { | 119 if (_file_count != 0) { |
122 st.write(PrintIdealGraphFile, dot - PrintIdealGraphFile); | 124 st.write(PrintIdealGraphFile, dot - PrintIdealGraphFile); |
123 st.print("%d%s", _file_count, dot); | 125 st.print("%d%s", _file_count, dot); |
124 } else { | 126 } else { |
125 st.print("%s%d", PrintIdealGraphFile, _file_count); | 127 st.print("%s%d", PrintIdealGraphFile, _file_count); |
126 } | 128 } |
127 _output = new (ResourceObj::C_HEAP) fileStream(st.as_string()); | 129 fileStream *stream = new (ResourceObj::C_HEAP) fileStream(st.as_string()); |
130 _output = stream; | |
128 } else { | 131 } else { |
129 _output = new (ResourceObj::C_HEAP) fileStream(PrintIdealGraphFile); | 132 fileStream *stream = new (ResourceObj::C_HEAP) fileStream(PrintIdealGraphFile); |
133 _output = stream; | |
130 } | 134 } |
131 _file_count++; | 135 _file_count++; |
132 } else { | 136 } else { |
137 _stream = new (ResourceObj::C_HEAP) networkStream(); | |
138 | |
133 // Try to connect to visualizer | 139 // Try to connect to visualizer |
134 if (_stream->connect(PrintIdealGraphAddress, PrintIdealGraphPort)) { | 140 if (_stream->connect(PrintIdealGraphAddress, PrintIdealGraphPort)) { |
135 char c = 0; | 141 char c = 0; |
136 _stream->read(&c, 1); | 142 _stream->read(&c, 1); |
137 if (c != 'y') { | 143 if (c != 'y') { |
147 // be an error if we can't connect to the visualizer. | 153 // be an error if we can't connect to the visualizer. |
148 fatal2("Couldn't connect to visualizer at %s:%d", PrintIdealGraphAddress, PrintIdealGraphPort); | 154 fatal2("Couldn't connect to visualizer at %s:%d", PrintIdealGraphAddress, PrintIdealGraphPort); |
149 } | 155 } |
150 } | 156 } |
151 | 157 |
152 start_element(TOP_ELEMENT); | 158 _xml = new (ResourceObj::C_HEAP) xmlStream(_output); |
159 | |
160 head(TOP_ELEMENT); | |
153 } | 161 } |
154 | 162 |
155 // Destructor, close file or network stream | 163 // Destructor, close file or network stream |
156 IdealGraphPrinter::~IdealGraphPrinter() { | 164 IdealGraphPrinter::~IdealGraphPrinter() { |
157 | 165 |
158 end_element(TOP_ELEMENT); | 166 tail(TOP_ELEMENT); |
167 | |
168 // tty->print_cr("Walk time: %d", (int)_walk_time.milliseconds()); | |
169 // tty->print_cr("Output time: %d", (int)_output_time.milliseconds()); | |
170 // tty->print_cr("Build blocks time: %d", (int)_build_blocks_time.milliseconds()); | |
171 | |
172 if(_xml) { | |
173 delete _xml; | |
174 _xml = NULL; | |
175 } | |
159 | 176 |
160 if (_stream) { | 177 if (_stream) { |
161 delete _stream; | 178 delete _stream; |
162 if (_stream == _output) { | 179 if (_stream == _output) { |
163 _output = NULL; | 180 _output = NULL; |
169 delete _output; | 186 delete _output; |
170 _output = NULL; | 187 _output = NULL; |
171 } | 188 } |
172 } | 189 } |
173 | 190 |
174 void IdealGraphPrinter::print_ifg(PhaseIFG* ifg) { | 191 |
175 | 192 void IdealGraphPrinter::begin_elem(const char *s) { |
176 // Code to print an interference graph to tty, currently not used | 193 _xml->begin_elem(s); |
177 | 194 } |
178 /* | 195 |
179 if (!_current_method) return; | 196 void IdealGraphPrinter::end_elem() { |
180 // Remove neighbor colors | 197 _xml->end_elem(); |
181 | 198 } |
182 for (uint i = 0; i < ifg._maxlrg; i++) { | 199 |
183 | 200 void IdealGraphPrinter::begin_head(const char *s) { |
184 IndexSet *s = ifg.neighbors(i); | 201 _xml->begin_head(s); |
185 IndexSetIterator elements(s); | 202 } |
186 uint neighbor; | 203 |
187 while ((neighbor = elements.next()) != 0) { | 204 void IdealGraphPrinter::end_head() { |
188 tty->print_cr("Edge between %d and %d\n", i, neighbor); | 205 _xml->end_head(); |
189 } | 206 } |
190 } | 207 |
191 | 208 void IdealGraphPrinter::print_attr(const char *name, intptr_t val) { |
192 | 209 stringStream stream; |
193 for (uint i = 0; i < ifg._maxlrg; i++) { | 210 stream.print(INTX_FORMAT, val); |
194 LRG &l = ifg.lrgs(i); | 211 print_attr(name, stream.as_string()); |
195 if (l._def) { | 212 } |
196 OptoReg::Name name = l.reg(); | 213 |
197 tty->print("OptoReg::dump: "); | 214 void IdealGraphPrinter::print_attr(const char *name, const char *val) { |
198 OptoReg::dump(name); | 215 _xml->print(" %s='", name); |
199 tty->print_cr(""); | 216 text(val); |
200 tty->print_cr("name=%d\n", name); | 217 _xml->print("'"); |
201 if (name) { | 218 } |
202 if (OptoReg::is_stack(name)) { | 219 |
203 tty->print_cr("Stack number %d\n", OptoReg::reg2stack(name)); | 220 void IdealGraphPrinter::head(const char *name) { |
204 | 221 _xml->head(name); |
205 } else if (!OptoReg::is_valid(name)) { | 222 } |
206 tty->print_cr("BAD!!!"); | 223 |
207 } else { | 224 void IdealGraphPrinter::tail(const char *name) { |
208 | 225 _xml->tail(name); |
209 if (OptoReg::is_reg(name)) { | 226 } |
210 tty->print_cr(OptoReg::regname(name)); | 227 |
211 } else { | 228 void IdealGraphPrinter::text(const char *s) { |
212 int x = 0; | 229 _xml->text(s); |
213 } | 230 } |
214 } | 231 |
215 int x = 0; | 232 void IdealGraphPrinter::print_prop(const char *name, int val) { |
216 } | 233 |
217 | 234 stringStream stream; |
218 if (l._def == NodeSentinel) { | 235 stream.print("%d", val); |
219 tty->print("multiple mapping from %d: ", i); | 236 print_prop(name, stream.as_string()); |
220 for (int j=0; j<l._defs->length(); j++) { | 237 } |
221 tty->print("%d ", l._defs->at(j)->_idx); | 238 |
222 } | 239 void IdealGraphPrinter::print_prop(const char *name, const char *val) { |
223 tty->print_cr(""); | 240 begin_head(PROPERTY_ELEMENT); |
224 } else { | 241 print_attr(PROPERTY_NAME_PROPERTY, name); |
225 tty->print_cr("mapping between %d and %d\n", i, l._def->_idx); | 242 end_head(); |
226 } | 243 text(val); |
227 } | 244 tail(PROPERTY_ELEMENT); |
228 }*/ | |
229 } | 245 } |
230 | 246 |
231 void IdealGraphPrinter::print_method(ciMethod *method, int bci, InlineTree *tree) { | 247 void IdealGraphPrinter::print_method(ciMethod *method, int bci, InlineTree *tree) { |
232 | 248 begin_head(METHOD_ELEMENT); |
233 Properties properties; | 249 |
234 stringStream str; | 250 stringStream str; |
235 method->print_name(&str); | 251 method->print_name(&str); |
236 | 252 |
237 stringStream shortStr; | 253 stringStream shortStr; |
238 method->print_short_name(&shortStr); | 254 method->print_short_name(&shortStr); |
239 | 255 |
240 | 256 print_attr(METHOD_NAME_PROPERTY, str.as_string()); |
241 properties.add(new Property(METHOD_NAME_PROPERTY, str.as_string())); | 257 print_attr(METHOD_SHORT_NAME_PROPERTY, shortStr.as_string()); |
242 properties.add(new Property(METHOD_SHORT_NAME_PROPERTY, shortStr.as_string())); | 258 print_attr(METHOD_BCI_PROPERTY, bci); |
243 properties.add(new Property(METHOD_BCI_PROPERTY, bci)); | 259 |
244 start_element(METHOD_ELEMENT, &properties); | 260 end_head(); |
245 | 261 |
246 start_element(BYTECODES_ELEMENT); | 262 head(BYTECODES_ELEMENT); |
247 output()->print_cr("<![CDATA["); | 263 output()->print_cr("<![CDATA["); |
248 method->print_codes_on(output()); | 264 method->print_codes_on(output()); |
249 output()->print_cr("]]>"); | 265 output()->print_cr("]]>"); |
250 end_element(BYTECODES_ELEMENT); | 266 tail(BYTECODES_ELEMENT); |
251 | 267 |
252 start_element(INLINE_ELEMENT); | 268 head(INLINE_ELEMENT); |
253 if (tree != NULL) { | 269 if (tree != NULL) { |
254 GrowableArray<InlineTree *> subtrees = tree->subtrees(); | 270 GrowableArray<InlineTree *> subtrees = tree->subtrees(); |
255 for (int i = 0; i < subtrees.length(); i++) { | 271 for (int i = 0; i < subtrees.length(); i++) { |
256 print_inline_tree(subtrees.at(i)); | 272 print_inline_tree(subtrees.at(i)); |
257 } | 273 } |
258 } | 274 } |
259 end_element(INLINE_ELEMENT); | 275 tail(INLINE_ELEMENT); |
260 | 276 |
261 end_element(METHOD_ELEMENT); | 277 tail(METHOD_ELEMENT); |
262 output()->flush(); | 278 output()->flush(); |
263 } | 279 } |
264 | 280 |
265 void IdealGraphPrinter::print_inline_tree(InlineTree *tree) { | 281 void IdealGraphPrinter::print_inline_tree(InlineTree *tree) { |
266 | 282 |
267 if (tree == NULL) return; | 283 if (tree == NULL) return; |
268 | 284 |
269 ciMethod *method = tree->method(); | 285 ciMethod *method = tree->method(); |
270 print_method(tree->method(), tree->caller_bci(), tree); | 286 print_method(tree->method(), tree->caller_bci(), tree); |
271 | 287 |
272 } | |
273 | |
274 void IdealGraphPrinter::clear_nodes() { | |
275 // for (int i = 0; i < _nodes.length(); i++) { | |
276 // _nodes.at(i)->clear_node(); | |
277 // } | |
278 } | 288 } |
279 | 289 |
280 void IdealGraphPrinter::print_inlining(Compile* compile) { | 290 void IdealGraphPrinter::print_inlining(Compile* compile) { |
281 | 291 |
282 // Print inline tree | 292 // Print inline tree |
296 ciMethod *method = compile->method(); | 306 ciMethod *method = compile->method(); |
297 assert(_output, "output stream must exist!"); | 307 assert(_output, "output stream must exist!"); |
298 assert(method, "null methods are not allowed!"); | 308 assert(method, "null methods are not allowed!"); |
299 assert(!_current_method, "current method must be null!"); | 309 assert(!_current_method, "current method must be null!"); |
300 | 310 |
301 _arena->destruct_contents(); | 311 head(GROUP_ELEMENT); |
302 | 312 |
303 start_element(GROUP_ELEMENT); | 313 head(PROPERTIES_ELEMENT); |
304 | 314 |
305 // Print properties | 315 // Print properties |
306 Properties properties; | |
307 | |
308 // Add method name | 316 // Add method name |
309 stringStream strStream; | 317 stringStream strStream; |
310 method->print_name(&strStream); | 318 method->print_name(&strStream); |
311 properties.add(new Property(METHOD_NAME_PROPERTY, strStream.as_string())); | 319 print_prop(METHOD_NAME_PROPERTY, strStream.as_string()); |
312 | 320 |
313 if (method->flags().is_public()) { | 321 if (method->flags().is_public()) { |
314 properties.add(new Property(METHOD_IS_PUBLIC_PROPERTY, TRUE_VALUE)); | 322 print_prop(METHOD_IS_PUBLIC_PROPERTY, TRUE_VALUE); |
315 } | 323 } |
316 | 324 |
317 if (method->flags().is_static()) { | 325 if (method->flags().is_static()) { |
318 properties.add(new Property(METHOD_IS_STATIC_PROPERTY, TRUE_VALUE)); | 326 print_prop(METHOD_IS_STATIC_PROPERTY, TRUE_VALUE); |
319 } | 327 } |
320 | 328 |
321 properties.print(this); | 329 tail(PROPERTIES_ELEMENT); |
322 | 330 |
323 if (_stream) { | 331 if (_stream) { |
324 char answer = 0; | 332 char answer = 0; |
325 _stream->flush(); | 333 _xml->flush(); |
326 int result = _stream->read(&answer, 1); | 334 int result = _stream->read(&answer, 1); |
327 _should_send_method = (answer == 'y'); | 335 _should_send_method = (answer == 'y'); |
328 } | 336 } |
329 | 337 |
330 this->_nodes = GrowableArray<NodeDescription *>(_arena, 2, 0, NULL); | |
331 this->_edges = GrowableArray< EdgeDescription * >(_arena, 2, 0, NULL); | |
332 | |
333 | |
334 this->_current_method = method; | 338 this->_current_method = method; |
335 | 339 |
336 | 340 _xml->flush(); |
337 | |
338 _output->flush(); | |
339 } | 341 } |
340 | 342 |
341 // Has to be called whenever a method has finished compilation | 343 // Has to be called whenever a method has finished compilation |
342 void IdealGraphPrinter::end_method() { | 344 void IdealGraphPrinter::end_method() { |
343 | 345 |
344 // if (finish && !in_method) return; | |
345 | |
346 nmethod* method = (nmethod*)this->_current_method->code(); | 346 nmethod* method = (nmethod*)this->_current_method->code(); |
347 | 347 |
348 start_element(ASSEMBLY_ELEMENT); | 348 tail(GROUP_ELEMENT); |
349 // Disassembler::decode(method, _output); | |
350 end_element(ASSEMBLY_ELEMENT); | |
351 | |
352 | |
353 end_element(GROUP_ELEMENT); | |
354 _current_method = NULL; | 349 _current_method = NULL; |
355 _output->flush(); | 350 _xml->flush(); |
356 for (int i = 0; i < _nodes.length(); i++) { | |
357 NodeDescription *desc = _nodes.at(i); | |
358 if (desc) { | |
359 delete desc; | |
360 _nodes.at_put(i, NULL); | |
361 } | |
362 } | |
363 this->_nodes.clear(); | |
364 | |
365 | |
366 for (int i = 0; i < _edges.length(); i++) { | |
367 // for (int j=0; j<_edges.at(i)->length(); j++) { | |
368 EdgeDescription *conn = _edges.at(i); | |
369 conn->print(this); | |
370 if (conn) { | |
371 delete conn; | |
372 _edges.at_put(i, NULL); | |
373 } | |
374 //} | |
375 //_edges.at(i)->clear(); | |
376 //delete _edges.at(i); | |
377 //_edges.at_put(i, NULL); | |
378 } | |
379 this->_edges.clear(); | |
380 | |
381 // in_method = false; | |
382 } | |
383 | |
384 // Outputs an XML start element | |
385 void IdealGraphPrinter::start_element(const char *s, Properties *properties /* = NULL */, bool print_indent /* = false */, bool print_return /* = true */) { | |
386 | |
387 start_element_helper(s, properties, false, print_indent, print_return); | |
388 _depth++; | |
389 | |
390 } | |
391 | |
392 // Outputs an XML start element without body | |
393 void IdealGraphPrinter::simple_element(const char *s, Properties *properties /* = NULL */, bool print_indent /* = false */) { | |
394 start_element_helper(s, properties, true, print_indent, true); | |
395 } | |
396 | |
397 // Outputs an XML start element. If outputEnd is true, the element has no body. | |
398 void IdealGraphPrinter::start_element_helper(const char *s, Properties *properties, bool outputEnd, bool print_indent /* = false */, bool print_return /* = true */) { | |
399 | |
400 assert(_output, "output stream must exist!"); | |
401 | |
402 if (print_indent) this->print_indent(); | |
403 _output->print("<"); | |
404 _output->print(s); | |
405 if (properties) properties->print_as_attributes(this); | |
406 | |
407 if (outputEnd) { | |
408 _output->print("/"); | |
409 } | |
410 | |
411 _output->print(">"); | |
412 if (print_return) _output->print_cr(""); | |
413 | |
414 } | 351 } |
415 | 352 |
416 // Print indent | 353 // Print indent |
417 void IdealGraphPrinter::print_indent() { | 354 void IdealGraphPrinter::print_indent() { |
355 tty->print_cr("printing ident %d", _depth); | |
418 for (int i = 0; i < _depth; i++) { | 356 for (int i = 0; i < _depth; i++) { |
419 _output->print(INDENT); | 357 _xml->print(INDENT); |
420 } | 358 } |
421 } | |
422 | |
423 // Outputs an XML end element | |
424 void IdealGraphPrinter::end_element(const char *s, bool print_indent /* = true */, bool print_return /* = true */) { | |
425 | |
426 assert(_output, "output stream must exist!"); | |
427 | |
428 _depth--; | |
429 | |
430 if (print_indent) this->print_indent(); | |
431 _output->print("</"); | |
432 _output->print(s); | |
433 _output->print(">"); | |
434 if (print_return) _output->print_cr(""); | |
435 | |
436 } | 359 } |
437 | 360 |
438 bool IdealGraphPrinter::traverse_outs() { | 361 bool IdealGraphPrinter::traverse_outs() { |
439 return _traverse_outs; | 362 return _traverse_outs; |
440 } | 363 } |
441 | 364 |
442 void IdealGraphPrinter::set_traverse_outs(bool b) { | 365 void IdealGraphPrinter::set_traverse_outs(bool b) { |
443 _traverse_outs = b; | 366 _traverse_outs = b; |
444 } | 367 } |
445 | 368 |
446 void IdealGraphPrinter::walk(Node *start) { | 369 intptr_t IdealGraphPrinter::get_node_id(Node *n) { |
370 return (intptr_t)(n); | |
371 } | |
372 | |
373 void IdealGraphPrinter::visit_node(Node *n, void *param) { | |
374 | |
375 if(param) { | |
376 | |
377 // Output edge | |
378 intptr_t dest_id = get_node_id(n); | |
379 for ( uint i = 0; i < n->len(); i++ ) { | |
380 if ( n->in(i) ) { | |
381 Node *source = n->in(i); | |
382 begin_elem(EDGE_ELEMENT); | |
383 intptr_t source_id = get_node_id(source); | |
384 print_attr(FROM_PROPERTY, source_id); | |
385 print_attr(TO_PROPERTY, dest_id); | |
386 print_attr(INDEX_PROPERTY, i); | |
387 end_elem(); | |
388 } | |
389 } | |
390 | |
391 } else { | |
392 | |
393 // Output node | |
394 begin_head(NODE_ELEMENT); | |
395 print_attr(NODE_ID_PROPERTY, get_node_id(n)); | |
396 end_head(); | |
397 | |
398 head(PROPERTIES_ELEMENT); | |
399 | |
400 Node *node = n; | |
401 #ifndef PRODUCT | |
402 node->_in_dump_cnt++; | |
403 print_prop(NODE_NAME_PROPERTY, (const char *)node->Name()); | |
404 const Type *t = node->bottom_type(); | |
405 print_prop("type", (const char *)Type::msg[t->base()]); | |
406 print_prop("idx", node->_idx); | |
407 #ifdef ASSERT | |
408 print_prop("debug_idx", node->_debug_idx); | |
409 #endif | |
410 | |
411 if(C->cfg() != NULL) { | |
412 Block *block = C->cfg()->_bbs[node->_idx]; | |
413 if(block == NULL) { | |
414 print_prop("block", C->cfg()->_blocks[0]->_pre_order); | |
415 } else { | |
416 print_prop("block", block->_pre_order); | |
417 } | |
418 } | |
419 | |
420 const jushort flags = node->flags(); | |
421 if (flags & Node::Flag_is_Copy) { | |
422 print_prop("is_copy", "true"); | |
423 } | |
424 if (flags & Node::Flag_is_Call) { | |
425 print_prop("is_call", "true"); | |
426 } | |
427 if (flags & Node::Flag_rematerialize) { | |
428 print_prop("rematerialize", "true"); | |
429 } | |
430 if (flags & Node::Flag_needs_anti_dependence_check) { | |
431 print_prop("needs_anti_dependence_check", "true"); | |
432 } | |
433 if (flags & Node::Flag_is_macro) { | |
434 print_prop("is_macro", "true"); | |
435 } | |
436 if (flags & Node::Flag_is_Con) { | |
437 print_prop("is_con", "true"); | |
438 } | |
439 if (flags & Node::Flag_is_cisc_alternate) { | |
440 print_prop("is_cisc_alternate", "true"); | |
441 } | |
442 if (flags & Node::Flag_is_Branch) { | |
443 print_prop("is_branch", "true"); | |
444 } | |
445 if (flags & Node::Flag_is_block_start) { | |
446 print_prop("is_block_start", "true"); | |
447 } | |
448 if (flags & Node::Flag_is_Goto) { | |
449 print_prop("is_goto", "true"); | |
450 } | |
451 if (flags & Node::Flag_is_dead_loop_safe) { | |
452 print_prop("is_dead_loop_safe", "true"); | |
453 } | |
454 if (flags & Node::Flag_may_be_short_branch) { | |
455 print_prop("may_be_short_branch", "true"); | |
456 } | |
457 if (flags & Node::Flag_is_safepoint_node) { | |
458 print_prop("is_safepoint_node", "true"); | |
459 } | |
460 if (flags & Node::Flag_is_pc_relative) { | |
461 print_prop("is_pc_relative", "true"); | |
462 } | |
463 | |
464 if (C->matcher() != NULL) { | |
465 if (C->matcher()->is_shared(node)) { | |
466 print_prop("is_shared", "true"); | |
467 } else { | |
468 print_prop("is_shared", "false"); | |
469 } | |
470 if (C->matcher()->is_dontcare(node)) { | |
471 print_prop("is_dontcare", "true"); | |
472 } else { | |
473 print_prop("is_dontcare", "false"); | |
474 } | |
475 | |
476 Node* old = C->matcher()->find_old_node(node); | |
477 if (old != NULL) { | |
478 print_prop("old_node_idx", old->_idx); | |
479 } | |
480 } | |
481 | |
482 if (node->is_Proj()) { | |
483 print_prop("con", (int)node->as_Proj()->_con); | |
484 } | |
485 | |
486 if (node->is_Mach()) { | |
487 print_prop("idealOpcode", (const char *)NodeClassNames[node->as_Mach()->ideal_Opcode()]); | |
488 } | |
489 | |
490 buffer[0] = 0; | |
491 stringStream s2(buffer, sizeof(buffer) - 1); | |
492 | |
493 node->dump_spec(&s2); | |
494 if (t != NULL && (t->isa_instptr() || t->isa_klassptr())) { | |
495 const TypeInstPtr *toop = t->isa_instptr(); | |
496 const TypeKlassPtr *tkls = t->isa_klassptr(); | |
497 ciKlass* klass = toop ? toop->klass() : (tkls ? tkls->klass() : NULL ); | |
498 if( klass && klass->is_loaded() && klass->is_interface() ) { | |
499 s2.print(" Interface:"); | |
500 } else if( toop ) { | |
501 s2.print(" Oop:"); | |
502 } else if( tkls ) { | |
503 s2.print(" Klass:"); | |
504 } | |
505 t->dump_on(&s2); | |
506 } else if( t == Type::MEMORY ) { | |
507 s2.print(" Memory:"); | |
508 MemNode::dump_adr_type(node, node->adr_type(), &s2); | |
509 } | |
510 | |
511 assert(s2.size() < sizeof(buffer), "size in range"); | |
512 print_prop("dump_spec", buffer); | |
513 | |
514 if (node->is_block_proj()) { | |
515 print_prop("is_block_proj", "true"); | |
516 } | |
517 | |
518 if (node->is_block_start()) { | |
519 print_prop("is_block_start", "true"); | |
520 } | |
521 | |
522 const char *short_name = "short_name"; | |
523 if (strcmp(node->Name(), "Parm") == 0 && node->as_Proj()->_con >= TypeFunc::Parms) { | |
524 int index = node->as_Proj()->_con - TypeFunc::Parms; | |
525 if (index >= 10) { | |
526 print_prop(short_name, "PA"); | |
527 } else { | |
528 sprintf(buffer, "P%d", index); | |
529 print_prop(short_name, buffer); | |
530 } | |
531 } else if (strcmp(node->Name(), "IfTrue") == 0) { | |
532 print_prop(short_name, "T"); | |
533 } else if (strcmp(node->Name(), "IfFalse") == 0) { | |
534 print_prop(short_name, "F"); | |
535 } else if ((node->is_Con() && node->is_Type()) || node->is_Proj()) { | |
536 | |
537 if (t->base() == Type::Int && t->is_int()->is_con()) { | |
538 const TypeInt *typeInt = t->is_int(); | |
539 assert(typeInt->is_con(), "must be constant"); | |
540 jint value = typeInt->get_con(); | |
541 | |
542 // max. 2 chars allowed | |
543 if (value >= -9 && value <= 99) { | |
544 sprintf(buffer, "%d", value); | |
545 print_prop(short_name, buffer); | |
546 } else { | |
547 print_prop(short_name, "I"); | |
548 } | |
549 } else if (t == Type::TOP) { | |
550 print_prop(short_name, "^"); | |
551 } else if (t->base() == Type::Long && t->is_long()->is_con()) { | |
552 const TypeLong *typeLong = t->is_long(); | |
553 assert(typeLong->is_con(), "must be constant"); | |
554 jlong value = typeLong->get_con(); | |
555 | |
556 // max. 2 chars allowed | |
557 if (value >= -9 && value <= 99) { | |
558 sprintf(buffer, "%d", value); | |
559 print_prop(short_name, buffer); | |
560 } else { | |
561 print_prop(short_name, "L"); | |
562 } | |
563 } else if (t->base() == Type::KlassPtr) { | |
564 const TypeKlassPtr *typeKlass = t->is_klassptr(); | |
565 print_prop(short_name, "CP"); | |
566 } else if (t->base() == Type::Control) { | |
567 print_prop(short_name, "C"); | |
568 } else if (t->base() == Type::Memory) { | |
569 print_prop(short_name, "M"); | |
570 } else if (t->base() == Type::Abio) { | |
571 print_prop(short_name, "IO"); | |
572 } else if (t->base() == Type::Return_Address) { | |
573 print_prop(short_name, "RA"); | |
574 } else if (t->base() == Type::AnyPtr) { | |
575 print_prop(short_name, "P"); | |
576 } else if (t->base() == Type::RawPtr) { | |
577 print_prop(short_name, "RP"); | |
578 } else if (t->base() == Type::AryPtr) { | |
579 print_prop(short_name, "AP"); | |
580 } | |
581 } | |
582 | |
583 JVMState* caller = NULL; | |
584 if (node->is_SafePoint()) { | |
585 caller = node->as_SafePoint()->jvms(); | |
586 } else { | |
587 Node_Notes* notes = C->node_notes_at(node->_idx); | |
588 if (notes != NULL) { | |
589 caller = notes->jvms(); | |
590 } | |
591 } | |
592 | |
593 if (caller != NULL) { | |
594 stringStream bciStream; | |
595 while(caller) { | |
596 bciStream.print("%d ", caller->bci()); | |
597 caller = caller->caller(); | |
598 } | |
599 print_prop("bci", bciStream.as_string()); | |
600 } | |
601 | |
602 if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) { | |
603 buffer[0] = 0; | |
604 _chaitin->dump_register(node, buffer); | |
605 print_prop("reg", buffer); | |
606 print_prop("lrg", _chaitin->n2lidx(node)); | |
607 } | |
608 | |
609 node->_in_dump_cnt--; | |
610 #endif | |
611 | |
612 tail(PROPERTIES_ELEMENT); | |
613 tail(NODE_ELEMENT); | |
614 } | |
615 } | |
616 | |
617 void IdealGraphPrinter::walk_nodes(Node *start, void *param) { | |
447 | 618 |
448 | 619 |
449 VectorSet visited(Thread::current()->resource_area()); | 620 VectorSet visited(Thread::current()->resource_area()); |
450 GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL); | 621 GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL); |
451 nodeStack.push(start); | 622 nodeStack.push(start); |
452 visited.test_set(start->_idx); | 623 visited.test_set(start->_idx); |
453 while(nodeStack.length() > 0) { | 624 while(nodeStack.length() > 0) { |
454 | 625 |
455 Node *n = nodeStack.pop(); | 626 Node *n = nodeStack.pop(); |
456 IdealGraphPrinter::pre_node(n, this); | 627 visit_node(n, param); |
457 | 628 |
458 if (_traverse_outs) { | 629 if (_traverse_outs) { |
459 for (DUIterator i = n->outs(); n->has_out(i); i++) { | 630 for (DUIterator i = n->outs(); n->has_out(i); i++) { |
460 Node* p = n->out(i); | 631 Node* p = n->out(i); |
461 if (!visited.test_set(p->_idx)) { | 632 if (!visited.test_set(p->_idx)) { |
472 } | 643 } |
473 } | 644 } |
474 } | 645 } |
475 } | 646 } |
476 | 647 |
477 void IdealGraphPrinter::compress(int index, GrowableArray<Block>* blocks) { | |
478 Block *block = blocks->adr_at(index); | |
479 | |
480 int ancestor = block->ancestor(); | |
481 assert(ancestor != -1, ""); | |
482 | |
483 Block *ancestor_block = blocks->adr_at(ancestor); | |
484 if (ancestor_block->ancestor() != -1) { | |
485 compress(ancestor, blocks); | |
486 | |
487 int label = block->label(); | |
488 Block *label_block = blocks->adr_at(label); | |
489 | |
490 int ancestor_label = ancestor_block->label(); | |
491 Block *ancestor_label_block = blocks->adr_at(label); | |
492 if (ancestor_label_block->semi() < label_block->semi()) { | |
493 block->set_label(ancestor_label); | |
494 } | |
495 | |
496 block->set_ancestor(ancestor_block->ancestor()); | |
497 } | |
498 } | |
499 | |
500 int IdealGraphPrinter::eval(int index, GrowableArray<Block>* blocks) { | |
501 Block *block = blocks->adr_at(index); | |
502 if (block->ancestor() == -1) { | |
503 return index; | |
504 } else { | |
505 compress(index, blocks); | |
506 return block->label(); | |
507 } | |
508 } | |
509 | |
510 void IdealGraphPrinter::link(int index1, int index2, GrowableArray<Block>* blocks) { | |
511 Block *block2 = blocks->adr_at(index2); | |
512 block2->set_ancestor(index1); | |
513 } | |
514 | |
515 void IdealGraphPrinter::build_dominators(GrowableArray<Block>* blocks) { | |
516 | |
517 if (blocks->length() == 0) return; | |
518 | |
519 GrowableArray<int> stack; | |
520 stack.append(0); | |
521 | |
522 GrowableArray<Block *> array; | |
523 | |
524 assert(blocks->length() > 0, ""); | |
525 blocks->adr_at(0)->set_dominator(0); | |
526 | |
527 int n = 0; | |
528 while(!stack.is_empty()) { | |
529 int index = stack.pop(); | |
530 Block *block = blocks->adr_at(index); | |
531 block->set_semi(n); | |
532 array.append(block); | |
533 n = n + 1; | |
534 for (int i = 0; i < block->succs()->length(); i++) { | |
535 int succ_index = block->succs()->at(i); | |
536 Block *succ = blocks->adr_at(succ_index); | |
537 if (succ->semi() == -1) { | |
538 succ->set_parent(index); | |
539 stack.push(succ_index); | |
540 } | |
541 succ->add_pred(index); | |
542 } | |
543 } | |
544 | |
545 for (int i=n-1; i>0; i--) { | |
546 Block *block = array.at(i); | |
547 int block_index = block->index(); | |
548 for (int j=0; j<block->pred()->length(); j++) { | |
549 int pred_index = block->pred()->at(j); | |
550 int cur_index = eval(pred_index, blocks); | |
551 | |
552 Block *cur_block = blocks->adr_at(cur_index); | |
553 if (cur_block->semi() < block->semi()) { | |
554 block->set_semi(cur_block->semi()); | |
555 } | |
556 } | |
557 | |
558 int semi_index = block->semi(); | |
559 Block *semi_block = array.at(semi_index); | |
560 semi_block->add_to_bucket(block_index); | |
561 | |
562 link(block->parent(), block_index, blocks); | |
563 Block *parent_block = blocks->adr_at(block->parent()); | |
564 | |
565 for (int j=0; j<parent_block->bucket()->length(); j++) { | |
566 int cur_index = parent_block->bucket()->at(j); | |
567 int new_index = eval(cur_index, blocks); | |
568 Block *cur_block = blocks->adr_at(cur_index); | |
569 Block *new_block = blocks->adr_at(new_index); | |
570 int dom = block->parent(); | |
571 | |
572 if (new_block->semi() < cur_block->semi()) { | |
573 dom = new_index; | |
574 } | |
575 | |
576 cur_block->set_dominator(dom); | |
577 } | |
578 | |
579 parent_block->clear_bucket(); | |
580 } | |
581 | |
582 for (int i=1; i < n; i++) { | |
583 | |
584 Block *block = array.at(i); | |
585 int block_index = block->index(); | |
586 | |
587 int semi_index = block->semi(); | |
588 Block *semi_block = array.at(semi_index); | |
589 | |
590 if (block->dominator() != semi_block->index()) { | |
591 int new_dom = blocks->adr_at(block->dominator())->dominator(); | |
592 block->set_dominator(new_dom); | |
593 } | |
594 } | |
595 | |
596 for (int i = 0; i < blocks->length(); i++) { | |
597 if (blocks->adr_at(i)->dominator() == -1) { | |
598 blocks->adr_at(i)->set_dominator(0); | |
599 } | |
600 } | |
601 | |
602 // Build dominates array | |
603 for (int i=1; i < blocks->length(); i++) { | |
604 Block *block = blocks->adr_at(i); | |
605 int dominator = block->dominator(); | |
606 Block *dom_block = blocks->adr_at(dominator); | |
607 dom_block->add_dominates(i); | |
608 dom_block->add_child(i); | |
609 | |
610 while(dominator != 0) { | |
611 dominator = dom_block->dominator(); | |
612 dom_block = blocks->adr_at(dominator); | |
613 dom_block->add_child(i); | |
614 } | |
615 } | |
616 } | |
617 | |
618 void IdealGraphPrinter::build_common_dominator(int **common_dominator, int index, GrowableArray<Block>* blocks) { | |
619 | |
620 common_dominator[index][index] = index; | |
621 Block *block = blocks->adr_at(index); | |
622 for (int i = 0; i < block->dominates()->length(); i++) { | |
623 Block *dominated = blocks->adr_at(block->dominates()->at(i)); | |
624 | |
625 for (int j=0; j<dominated->children()->length(); j++) { | |
626 Block *child = blocks->adr_at(dominated->children()->at(j)); | |
627 common_dominator[index][child->index()] = common_dominator[child->index()][index] = index; | |
628 | |
629 for (int k=0; k<i; k++) { | |
630 Block *other_dominated = blocks->adr_at(block->dominates()->at(k)); | |
631 common_dominator[child->index()][other_dominated->index()] = common_dominator[other_dominated->index()][child->index()] = index; | |
632 | |
633 for (int l=0 ; l<other_dominated->children()->length(); l++) { | |
634 Block *other_child = blocks->adr_at(other_dominated->children()->at(l)); | |
635 common_dominator[child->index()][other_child->index()] = common_dominator[other_child->index()][child->index()] = index; | |
636 } | |
637 } | |
638 } | |
639 | |
640 build_common_dominator(common_dominator, dominated->index(), blocks); | |
641 } | |
642 } | |
643 | |
644 void IdealGraphPrinter::schedule_latest(int **common_dominator, GrowableArray<Block>* blocks) { | |
645 | |
646 int queue_size = _nodes.length() + 1; | |
647 NodeDescription **queue = NEW_RESOURCE_ARRAY(NodeDescription *, queue_size); | |
648 int queue_start = 0; | |
649 int queue_end = 0; | |
650 Arena *a = new Arena(); | |
651 VectorSet on_queue(a); | |
652 | |
653 for (int i = 0; i < _nodes.length(); i++) { | |
654 NodeDescription *desc = _nodes.at(i); | |
655 if (desc) { | |
656 desc->init_succs(); | |
657 } | |
658 } | |
659 | |
660 for (int i = 0; i < _nodes.length(); i++) { | |
661 NodeDescription *desc = _nodes.at(i); | |
662 if (desc) { | |
663 for (uint j=0; j<desc->node()->len(); j++) { | |
664 Node *n = desc->node()->in(j); | |
665 if (n) { | |
666 NodeDescription *other_desc = _nodes.at(n->_idx); | |
667 other_desc->add_succ(desc); | |
668 } | |
669 } | |
670 } | |
671 } | |
672 | |
673 for (int i = 0; i < _nodes.length(); i++) { | |
674 NodeDescription *desc = _nodes.at(i); | |
675 if (desc && desc->block_index() == -1) { | |
676 | |
677 // Put Phi into same block as region | |
678 if (desc->node()->is_Phi() && desc->node()->in(0) && _nodes.at(desc->node()->in(0)->_idx)->block_index() != -1) { | |
679 int index = _nodes.at(desc->node()->in(0)->_idx)->block_index(); | |
680 desc->set_block_index(index); | |
681 blocks->adr_at(index)->add_node(desc); | |
682 | |
683 // Put Projections to same block as parent | |
684 } else if (desc->node()->is_block_proj() && _nodes.at(desc->node()->is_block_proj()->_idx)->block_index() != -1) { | |
685 int index = _nodes.at(desc->node()->is_block_proj()->_idx)->block_index(); | |
686 desc->set_block_index(index); | |
687 blocks->adr_at(index)->add_node(desc); | |
688 } else { | |
689 queue[queue_end] = desc; | |
690 queue_end++; | |
691 on_queue.set(desc->node()->_idx); | |
692 } | |
693 } | |
694 } | |
695 | |
696 | |
697 int z = 0; | |
698 while(queue_start != queue_end && z < 10000) { | |
699 | |
700 NodeDescription *desc = queue[queue_start]; | |
701 queue_start = (queue_start + 1) % queue_size; | |
702 on_queue >>= desc->node()->_idx; | |
703 | |
704 Node* node = desc->node(); | |
705 | |
706 if (desc->succs()->length() == 0) { | |
707 int x = 0; | |
708 } | |
709 | |
710 int block_index = -1; | |
711 if (desc->succs()->length() != 0) { | |
712 for (int i = 0; i < desc->succs()->length(); i++) { | |
713 NodeDescription *cur_desc = desc->succs()->at(i); | |
714 if (cur_desc != desc) { | |
715 if (cur_desc->succs()->length() == 0) { | |
716 | |
717 // Ignore nodes with 0 successors | |
718 | |
719 } else if (cur_desc->block_index() == -1) { | |
720 | |
721 // Let this node schedule first | |
722 block_index = -1; | |
723 break; | |
724 | |
725 } else if (cur_desc->node()->is_Phi()){ | |
726 | |
727 // Special treatment for Phi functions | |
728 PhiNode *phi = cur_desc->node()->as_Phi(); | |
729 assert(phi->in(0) && phi->in(0)->is_Region(), "Must have region node in first input"); | |
730 RegionNode *region = phi->in(0)->as_Region(); | |
731 | |
732 for (uint j=1; j<phi->len(); j++) { | |
733 Node *cur_phi_input = phi->in(j); | |
734 if (cur_phi_input == desc->node() && region->in(j)) { | |
735 NodeDescription *cur_region_input = _nodes.at(region->in(j)->_idx); | |
736 if (cur_region_input->block_index() == -1) { | |
737 | |
738 // Let this node schedule first | |
739 block_index = -1; | |
740 break; | |
741 } else { | |
742 if (block_index == -1) { | |
743 block_index = cur_region_input->block_index(); | |
744 } else { | |
745 block_index = common_dominator[block_index][cur_region_input->block_index()]; | |
746 } | |
747 } | |
748 } | |
749 } | |
750 | |
751 } else { | |
752 if (block_index == -1) { | |
753 block_index = cur_desc->block_index(); | |
754 } else { | |
755 block_index = common_dominator[block_index][cur_desc->block_index()]; | |
756 } | |
757 } | |
758 } | |
759 } | |
760 } | |
761 | |
762 if (block_index == -1) { | |
763 queue[queue_end] = desc; | |
764 queue_end = (queue_end + 1) % queue_size; | |
765 on_queue.set(desc->node()->_idx); | |
766 z++; | |
767 } else { | |
768 assert(desc->block_index() == -1, ""); | |
769 desc->set_block_index(block_index); | |
770 blocks->adr_at(block_index)->add_node(desc); | |
771 z = 0; | |
772 } | |
773 } | |
774 | |
775 for (int i = 0; i < _nodes.length(); i++) { | |
776 NodeDescription *desc = _nodes.at(i); | |
777 if (desc && desc->block_index() == -1) { | |
778 | |
779 //if (desc->node()->is_Proj() || desc->node()->is_Con()) { | |
780 Node *parent = desc->node()->in(0); | |
781 uint cur = 1; | |
782 while(!parent && cur < desc->node()->len()) { | |
783 parent = desc->node()->in(cur); | |
784 cur++; | |
785 } | |
786 | |
787 if (parent && _nodes.at(parent->_idx)->block_index() != -1) { | |
788 int index = _nodes.at(parent->_idx)->block_index(); | |
789 desc->set_block_index(index); | |
790 blocks->adr_at(index)->add_node(desc); | |
791 } else { | |
792 desc->set_block_index(0); | |
793 blocks->adr_at(0)->add_node(desc); | |
794 //ShouldNotReachHere(); | |
795 } | |
796 //} | |
797 /* | |
798 if (desc->node()->is_block_proj() && _nodes.at(desc->node()->is_block_proj()->_idx)->block_index() != -1) { | |
799 int index = _nodes.at(desc->node()->is_block_proj()->_idx)->block_index(); | |
800 desc->set_block_index(index); | |
801 blocks->adr_at(index)->add_node(desc); | |
802 } */ | |
803 } | |
804 } | |
805 | |
806 for (int i = 0; i < _nodes.length(); i++) { | |
807 NodeDescription *desc = _nodes.at(i); | |
808 if (desc) { | |
809 desc->clear_succs(); | |
810 } | |
811 } | |
812 | |
813 for (int i = 0; i < _nodes.length(); i++) { | |
814 NodeDescription *desc = _nodes.at(i); | |
815 if (desc) { | |
816 int block_index = desc->block_index(); | |
817 | |
818 assert(block_index >= 0 && block_index < blocks->length(), "Block index must be in range"); | |
819 assert(blocks->adr_at(block_index)->nodes()->contains(desc), "Node must be child of block"); | |
820 } | |
821 } | |
822 a->destruct_contents(); | |
823 } | |
824 | |
825 void IdealGraphPrinter::build_blocks(Node *root) { | |
826 | |
827 Arena *a = new Arena(); | |
828 Node_Stack stack(a, 100); | |
829 | |
830 VectorSet visited(a); | |
831 stack.push(root, 0); | |
832 GrowableArray<Block> blocks(a, 2, 0, Block(0)); | |
833 | |
834 for (int i = 0; i < _nodes.length(); i++) { | |
835 if (_nodes.at(i)) _nodes.at(i)->set_block_index(-1); | |
836 } | |
837 | |
838 | |
839 // Order nodes such that node index is equal to idx | |
840 for (int i = 0; i < _nodes.length(); i++) { | |
841 | |
842 if (_nodes.at(i)) { | |
843 NodeDescription *node = _nodes.at(i); | |
844 int index = node->node()->_idx; | |
845 if (index != i) { | |
846 _nodes.at_grow(index); | |
847 NodeDescription *tmp = _nodes.at(index); | |
848 *(_nodes.adr_at(index)) = node; | |
849 *(_nodes.adr_at(i)) = tmp; | |
850 i--; | |
851 } | |
852 } | |
853 } | |
854 | |
855 for (int i = 0; i < _nodes.length(); i++) { | |
856 NodeDescription *node = _nodes.at(i); | |
857 if (node) { | |
858 assert(node->node()->_idx == (uint)i, ""); | |
859 } | |
860 } | |
861 | |
862 while(stack.is_nonempty()) { | |
863 | |
864 //Node *n = stack.node(); | |
865 //int index = stack.index(); | |
866 Node *proj = stack.node();//n->in(index); | |
867 const Node *parent = proj->is_block_proj(); | |
868 if (parent == NULL) { | |
869 parent = proj; | |
870 } | |
871 | |
872 if (!visited.test_set(parent->_idx)) { | |
873 | |
874 NodeDescription *end_desc = _nodes.at(parent->_idx); | |
875 int block_index = blocks.length(); | |
876 Block block(block_index); | |
877 blocks.append(block); | |
878 Block *b = blocks.adr_at(block_index); | |
879 b->set_start(end_desc); | |
880 // assert(end_desc->block_index() == -1, ""); | |
881 end_desc->set_block_index(block_index); | |
882 b->add_node(end_desc); | |
883 | |
884 // Skip any control-pinned middle'in stuff | |
885 Node *p = proj; | |
886 NodeDescription *start_desc = NULL; | |
887 do { | |
888 proj = p; // Update pointer to last Control | |
889 if (p->in(0) == NULL) { | |
890 start_desc = end_desc; | |
891 break; | |
892 } | |
893 p = p->in(0); // Move control forward | |
894 start_desc = _nodes.at(p->_idx); | |
895 assert(start_desc, ""); | |
896 | |
897 if (start_desc != end_desc && start_desc->block_index() == -1) { | |
898 assert(start_desc->block_index() == -1, ""); | |
899 assert(block_index < blocks.length(), ""); | |
900 start_desc->set_block_index(block_index); | |
901 b->add_node(start_desc); | |
902 } | |
903 } while( !p->is_block_proj() && | |
904 !p->is_block_start() ); | |
905 | |
906 for (uint i = 0; i < start_desc->node()->len(); i++) { | |
907 | |
908 Node *pred_node = start_desc->node()->in(i); | |
909 | |
910 | |
911 if (pred_node && pred_node != start_desc->node()) { | |
912 const Node *cur_parent = pred_node->is_block_proj(); | |
913 if (cur_parent != NULL) { | |
914 pred_node = (Node *)cur_parent; | |
915 } | |
916 | |
917 NodeDescription *pred_node_desc = _nodes.at(pred_node->_idx); | |
918 if (pred_node_desc->block_index() != -1) { | |
919 blocks.adr_at(pred_node_desc->block_index())->add_succ(block_index); | |
920 } | |
921 } | |
922 } | |
923 | |
924 for (DUIterator_Fast dmax, i = end_desc->node()->fast_outs(dmax); i < dmax; i++) { | |
925 Node* cur_succ = end_desc->node()->fast_out(i); | |
926 NodeDescription *cur_succ_desc = _nodes.at(cur_succ->_idx); | |
927 | |
928 DUIterator_Fast dmax2, i2 = cur_succ->fast_outs(dmax2); | |
929 if (cur_succ->is_block_proj() && i2 < dmax2 && !cur_succ->is_Root()) { | |
930 | |
931 for (; i2<dmax2; i2++) { | |
932 Node *cur_succ2 = cur_succ->fast_out(i2); | |
933 if (cur_succ2) { | |
934 cur_succ_desc = _nodes.at(cur_succ2->_idx); | |
935 if (cur_succ_desc == NULL) { | |
936 // dead node so skip it | |
937 continue; | |
938 } | |
939 if (cur_succ2 != end_desc->node() && cur_succ_desc->block_index() != -1) { | |
940 b->add_succ(cur_succ_desc->block_index()); | |
941 } | |
942 } | |
943 } | |
944 | |
945 } else { | |
946 | |
947 if (cur_succ != end_desc->node() && cur_succ_desc && cur_succ_desc->block_index() != -1) { | |
948 b->add_succ(cur_succ_desc->block_index()); | |
949 } | |
950 } | |
951 } | |
952 | |
953 | |
954 int num_preds = p->len(); | |
955 int bottom = -1; | |
956 if (p->is_Region() || p->is_Phi()) { | |
957 bottom = 0; | |
958 } | |
959 | |
960 int pushed = 0; | |
961 for (int i=num_preds - 1; i > bottom; i--) { | |
962 if (p->in(i) != NULL && p->in(i) != p) { | |
963 stack.push(p->in(i), 0); | |
964 pushed++; | |
965 } | |
966 } | |
967 | |
968 if (pushed == 0 && p->is_Root() && !_matcher) { | |
969 // Special case when backedges to root are not yet built | |
970 for (int i = 0; i < _nodes.length(); i++) { | |
971 if (_nodes.at(i) && _nodes.at(i)->node()->is_SafePoint() && _nodes.at(i)->node()->outcnt() == 0) { | |
972 stack.push(_nodes.at(i)->node(), 0); | |
973 } | |
974 } | |
975 } | |
976 | |
977 } else { | |
978 stack.pop(); | |
979 } | |
980 } | |
981 | |
982 build_dominators(&blocks); | |
983 | |
984 int **common_dominator = NEW_RESOURCE_ARRAY(int *, blocks.length()); | |
985 for (int i = 0; i < blocks.length(); i++) { | |
986 int *cur = NEW_RESOURCE_ARRAY(int, blocks.length()); | |
987 common_dominator[i] = cur; | |
988 | |
989 for (int j=0; j<blocks.length(); j++) { | |
990 cur[j] = 0; | |
991 } | |
992 } | |
993 | |
994 for (int i = 0; i < blocks.length(); i++) { | |
995 blocks.adr_at(i)->add_child(blocks.adr_at(i)->index()); | |
996 } | |
997 build_common_dominator(common_dominator, 0, &blocks); | |
998 | |
999 schedule_latest(common_dominator, &blocks); | |
1000 | |
1001 start_element(CONTROL_FLOW_ELEMENT); | |
1002 | |
1003 for (int i = 0; i < blocks.length(); i++) { | |
1004 Block *block = blocks.adr_at(i); | |
1005 | |
1006 Properties props; | |
1007 props.add(new Property(BLOCK_NAME_PROPERTY, i)); | |
1008 props.add(new Property(BLOCK_DOMINATOR_PROPERTY, block->dominator())); | |
1009 start_element(BLOCK_ELEMENT, &props); | |
1010 | |
1011 if (block->succs()->length() > 0) { | |
1012 start_element(SUCCESSORS_ELEMENT); | |
1013 for (int j=0; j<block->succs()->length(); j++) { | |
1014 int cur_index = block->succs()->at(j); | |
1015 if (cur_index != 0 /* start_block has must not have inputs */) { | |
1016 Properties properties; | |
1017 properties.add(new Property(BLOCK_NAME_PROPERTY, cur_index)); | |
1018 simple_element(SUCCESSOR_ELEMENT, &properties); | |
1019 } | |
1020 } | |
1021 end_element(SUCCESSORS_ELEMENT); | |
1022 } | |
1023 | |
1024 start_element(NODES_ELEMENT); | |
1025 | |
1026 for (int j=0; j<block->nodes()->length(); j++) { | |
1027 NodeDescription *n = block->nodes()->at(j); | |
1028 Properties properties; | |
1029 properties.add(new Property(NODE_ID_PROPERTY, n->id())); | |
1030 simple_element(NODE_ELEMENT, &properties); | |
1031 } | |
1032 | |
1033 end_element(NODES_ELEMENT); | |
1034 | |
1035 end_element(BLOCK_ELEMENT); | |
1036 } | |
1037 | |
1038 | |
1039 end_element(CONTROL_FLOW_ELEMENT); | |
1040 | |
1041 a->destruct_contents(); | |
1042 } | |
1043 | |
1044 void IdealGraphPrinter::print_method(Compile* compile, const char *name, int level, bool clear_nodes) { | 648 void IdealGraphPrinter::print_method(Compile* compile, const char *name, int level, bool clear_nodes) { |
1045 print(compile, name, (Node *)compile->root(), level, clear_nodes); | 649 print(compile, name, (Node *)compile->root(), level, clear_nodes); |
1046 } | 650 } |
1047 | 651 |
1048 // Print current ideal graph | 652 // Print current ideal graph |
1049 void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) { | 653 void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) { |
1050 | 654 |
1051 // if (finish && !in_method) return; | |
1052 if (!_current_method || !_should_send_method || level > PrintIdealGraphLevel) return; | 655 if (!_current_method || !_should_send_method || level > PrintIdealGraphLevel) return; |
1053 | 656 |
1054 assert(_current_method, "newMethod has to be called first!"); | 657 this->C = compile; |
1055 | |
1056 if (clear_nodes) { | |
1057 int x = 0; | |
1058 } | |
1059 | |
1060 _clear_nodes = clear_nodes; | |
1061 | 658 |
1062 // Warning, unsafe cast? | 659 // Warning, unsafe cast? |
1063 _chaitin = (PhaseChaitin *)compile->regalloc(); | 660 _chaitin = (PhaseChaitin *)C->regalloc(); |
1064 _matcher = compile->matcher(); | 661 |
1065 | 662 begin_head(GRAPH_ELEMENT); |
1066 | 663 print_attr(GRAPH_NAME_PROPERTY, (const char *)name); |
1067 // Update nodes | 664 end_head(); |
1068 for (int i = 0; i < _nodes.length(); i++) { | 665 |
1069 NodeDescription *desc = _nodes.at(i); | 666 head(NODES_ELEMENT); |
1070 if (desc) { | 667 walk_nodes(node, NULL); |
1071 desc->set_state(Invalid); | 668 tail(NODES_ELEMENT); |
1072 } | 669 |
1073 } | 670 head(EDGES_ELEMENT); |
1074 Node *n = node; | 671 walk_nodes(node, (void *)1); |
1075 walk(n); | 672 tail(EDGES_ELEMENT); |
1076 | 673 if (C->cfg() != NULL) { |
1077 // Update edges | 674 head(CONTROL_FLOW_ELEMENT); |
1078 for (int i = 0; i < _edges.length(); i++) { | 675 for (uint i = 0; i < C->cfg()->_blocks.size(); i++) { |
1079 _edges.at(i)->set_state(Invalid); | 676 Block *b = C->cfg()->_blocks[i]; |
1080 } | 677 begin_head(BLOCK_ELEMENT); |
1081 | 678 print_attr(BLOCK_NAME_PROPERTY, b->_pre_order); |
1082 for (int i = 0; i < _nodes.length(); i++) { | 679 end_head(); |
1083 NodeDescription *desc = _nodes.at(i); | 680 |
1084 if (desc && desc->state() != Invalid) { | 681 head(SUCCESSORS_ELEMENT); |
1085 | 682 for (uint s = 0; s < C->cfg()->_blocks[i]->_num_succs; s++) { |
1086 int to = desc->id(); | 683 begin_elem(SUCCESSOR_ELEMENT); |
1087 uint len = desc->node()->len(); | 684 print_attr(BLOCK_NAME_PROPERTY, b->_succs[s]->_pre_order); |
1088 for (uint j=0; j<len; j++) { | 685 end_elem(); |
1089 Node *n = desc->node()->in(j); | 686 } |
1090 | 687 tail(SUCCESSORS_ELEMENT); |
1091 if (n) { | 688 |
1092 | 689 tail(BLOCK_ELEMENT); |
1093 | 690 } |
1094 intptr_t from = (intptr_t)n; | 691 |
1095 | 692 tail(CONTROL_FLOW_ELEMENT); |
1096 // Assert from node is valid | 693 } |
1097 /* | 694 tail(GRAPH_ELEMENT); |
1098 bool ok = false; | 695 output()->flush(); |
1099 for (int k=0; k<_nodes.length(); k++) { | |
1100 NodeDescription *desc = _nodes.at(k); | |
1101 if (desc && desc->id() == from) { | |
1102 assert(desc->state() != Invalid, ""); | |
1103 ok = true; | |
1104 } | |
1105 } | |
1106 assert(ok, "");*/ | |
1107 | |
1108 uint index = j; | |
1109 if (index >= desc->node()->req()) { | |
1110 index = desc->node()->req(); | |
1111 } | |
1112 | |
1113 print_edge(from, to, index); | |
1114 } | |
1115 } | |
1116 } | |
1117 } | |
1118 | |
1119 bool is_different = false; | |
1120 | |
1121 for (int i = 0; i < _nodes.length(); i++) { | |
1122 NodeDescription *desc = _nodes.at(i); | |
1123 if (desc && desc->state() != Valid) { | |
1124 is_different = true; | |
1125 break; | |
1126 } | |
1127 } | |
1128 | |
1129 if (!is_different) { | |
1130 for (int i = 0; i < _edges.length(); i++) { | |
1131 EdgeDescription *conn = _edges.at(i); | |
1132 if (conn && conn->state() != Valid) { | |
1133 is_different = true; | |
1134 break; | |
1135 } | |
1136 } | |
1137 } | |
1138 | |
1139 // No changes -> do not print graph | |
1140 if (!is_different) return; | |
1141 | |
1142 Properties properties; | |
1143 properties.add(new Property(GRAPH_NAME_PROPERTY, (const char *)name)); | |
1144 start_element(GRAPH_ELEMENT, &properties); | |
1145 | |
1146 start_element(NODES_ELEMENT); | |
1147 for (int i = 0; i < _nodes.length(); i++) { | |
1148 NodeDescription *desc = _nodes.at(i); | |
1149 if (desc) { | |
1150 desc->print(this); | |
1151 if (desc->state() == Invalid) { | |
1152 delete desc; | |
1153 _nodes.at_put(i, NULL); | |
1154 } else { | |
1155 desc->set_state(Valid); | |
1156 } | |
1157 } | |
1158 } | |
1159 end_element(NODES_ELEMENT); | |
1160 | |
1161 build_blocks(node); | |
1162 | |
1163 start_element(EDGES_ELEMENT); | |
1164 for (int i = 0; i < _edges.length(); i++) { | |
1165 EdgeDescription *conn = _edges.at(i); | |
1166 | |
1167 // Assert from and to nodes are valid | |
1168 /* | |
1169 if (!conn->state() == Invalid) { | |
1170 bool ok1 = false; | |
1171 bool ok2 = false; | |
1172 for (int j=0; j<_nodes.length(); j++) { | |
1173 NodeDescription *desc = _nodes.at(j); | |
1174 if (desc && desc->id() == conn->from()) { | |
1175 ok1 = true; | |
1176 } | |
1177 | |
1178 if (desc && desc->id() == conn->to()) { | |
1179 ok2 = true; | |
1180 } | |
1181 } | |
1182 | |
1183 assert(ok1, "from node not found!"); | |
1184 assert(ok2, "to node not found!"); | |
1185 }*/ | |
1186 | |
1187 conn->print(this); | |
1188 if (conn->state() == Invalid) { | |
1189 _edges.remove_at(i); | |
1190 delete conn; | |
1191 i--; | |
1192 } | |
1193 } | |
1194 | |
1195 end_element(EDGES_ELEMENT); | |
1196 | |
1197 end_element(GRAPH_ELEMENT); | |
1198 | |
1199 _output->flush(); | |
1200 } | |
1201 | |
1202 // Print edge | |
1203 void IdealGraphPrinter::print_edge(int from, int to, int index) { | |
1204 | |
1205 EdgeDescription *conn = new EdgeDescription(from, to, index); | |
1206 for (int i = 0; i < _edges.length(); i++) { | |
1207 if (_edges.at(i)->equals(conn)) { | |
1208 conn->set_state(Valid); | |
1209 delete _edges.at(i); | |
1210 _edges.at_put(i, conn); | |
1211 return; | |
1212 } | |
1213 } | |
1214 | |
1215 _edges.append(conn); | |
1216 } | 696 } |
1217 | 697 |
1218 extern const char *NodeClassNames[]; | 698 extern const char *NodeClassNames[]; |
1219 | 699 |
1220 // Create node description | 700 outputStream *IdealGraphPrinter::output() { |
1221 IdealGraphPrinter::NodeDescription *IdealGraphPrinter::create_node_description(Node* node) { | 701 return _xml; |
1222 | 702 } |
1223 #ifndef PRODUCT | 703 |
1224 node->_in_dump_cnt++; | |
1225 NodeDescription *desc = new NodeDescription(node); | |
1226 desc->properties()->add(new Property(NODE_NAME_PROPERTY, (const char *)node->Name())); | |
1227 | |
1228 const Type *t = node->bottom_type(); | |
1229 desc->properties()->add(new Property("type", (const char *)Type::msg[t->base()])); | |
1230 | |
1231 desc->properties()->add(new Property("idx", node->_idx)); | |
1232 #ifdef ASSERT | |
1233 desc->properties()->add(new Property("debug_idx", node->_debug_idx)); | |
1234 #endif | 704 #endif |
1235 | |
1236 | |
1237 const jushort flags = node->flags(); | |
1238 if (flags & Node::Flag_is_Copy) { | |
1239 desc->properties()->add(new Property("is_copy", "true")); | |
1240 } | |
1241 if (flags & Node::Flag_is_Call) { | |
1242 desc->properties()->add(new Property("is_call", "true")); | |
1243 } | |
1244 if (flags & Node::Flag_rematerialize) { | |
1245 desc->properties()->add(new Property("rematerialize", "true")); | |
1246 } | |
1247 if (flags & Node::Flag_needs_anti_dependence_check) { | |
1248 desc->properties()->add(new Property("needs_anti_dependence_check", "true")); | |
1249 } | |
1250 if (flags & Node::Flag_is_macro) { | |
1251 desc->properties()->add(new Property("is_macro", "true")); | |
1252 } | |
1253 if (flags & Node::Flag_is_Con) { | |
1254 desc->properties()->add(new Property("is_con", "true")); | |
1255 } | |
1256 if (flags & Node::Flag_is_cisc_alternate) { | |
1257 desc->properties()->add(new Property("is_cisc_alternate", "true")); | |
1258 } | |
1259 if (flags & Node::Flag_is_Branch) { | |
1260 desc->properties()->add(new Property("is_branch", "true")); | |
1261 } | |
1262 if (flags & Node::Flag_is_block_start) { | |
1263 desc->properties()->add(new Property("is_block_start", "true")); | |
1264 } | |
1265 if (flags & Node::Flag_is_Goto) { | |
1266 desc->properties()->add(new Property("is_goto", "true")); | |
1267 } | |
1268 if (flags & Node::Flag_is_dead_loop_safe) { | |
1269 desc->properties()->add(new Property("is_dead_loop_safe", "true")); | |
1270 } | |
1271 if (flags & Node::Flag_may_be_short_branch) { | |
1272 desc->properties()->add(new Property("may_be_short_branch", "true")); | |
1273 } | |
1274 if (flags & Node::Flag_is_safepoint_node) { | |
1275 desc->properties()->add(new Property("is_safepoint_node", "true")); | |
1276 } | |
1277 if (flags & Node::Flag_is_pc_relative) { | |
1278 desc->properties()->add(new Property("is_pc_relative", "true")); | |
1279 } | |
1280 | |
1281 if (_matcher) { | |
1282 if (_matcher->is_shared(desc->node())) { | |
1283 desc->properties()->add(new Property("is_shared", "true")); | |
1284 } else { | |
1285 desc->properties()->add(new Property("is_shared", "false")); | |
1286 } | |
1287 | |
1288 if (_matcher->is_dontcare(desc->node())) { | |
1289 desc->properties()->add(new Property("is_dontcare", "true")); | |
1290 } else { | |
1291 desc->properties()->add(new Property("is_dontcare", "false")); | |
1292 } | |
1293 } | |
1294 | |
1295 if (node->is_Proj()) { | |
1296 desc->properties()->add(new Property("con", (int)node->as_Proj()->_con)); | |
1297 } | |
1298 | |
1299 if (node->is_Mach()) { | |
1300 desc->properties()->add(new Property("idealOpcode", (const char *)NodeClassNames[node->as_Mach()->ideal_Opcode()])); | |
1301 } | |
1302 | |
1303 | |
1304 | |
1305 | |
1306 | |
1307 outputStream *oldTty = tty; | |
1308 buffer[0] = 0; | |
1309 stringStream s2(buffer, sizeof(buffer) - 1); | |
1310 | |
1311 node->dump_spec(&s2); | |
1312 assert(s2.size() < sizeof(buffer), "size in range"); | |
1313 desc->properties()->add(new Property("dump_spec", buffer)); | |
1314 | |
1315 if (node->is_block_proj()) { | |
1316 desc->properties()->add(new Property("is_block_proj", "true")); | |
1317 } | |
1318 | |
1319 if (node->is_block_start()) { | |
1320 desc->properties()->add(new Property("is_block_start", "true")); | |
1321 } | |
1322 | |
1323 const char *short_name = "short_name"; | |
1324 if (strcmp(node->Name(), "Parm") == 0 && node->as_Proj()->_con >= TypeFunc::Parms) { | |
1325 int index = node->as_Proj()->_con - TypeFunc::Parms; | |
1326 if (index >= 10) { | |
1327 desc->properties()->add(new Property(short_name, "PA")); | |
1328 } else { | |
1329 sprintf(buffer, "P%d", index); | |
1330 desc->properties()->add(new Property(short_name, buffer)); | |
1331 } | |
1332 } else if (strcmp(node->Name(), "IfTrue") == 0) { | |
1333 desc->properties()->add(new Property(short_name, "T")); | |
1334 } else if (strcmp(node->Name(), "IfFalse") == 0) { | |
1335 desc->properties()->add(new Property(short_name, "F")); | |
1336 } else if ((node->is_Con() && node->is_Type()) || node->is_Proj()) { | |
1337 | |
1338 if (t->base() == Type::Int && t->is_int()->is_con()) { | |
1339 const TypeInt *typeInt = t->is_int(); | |
1340 assert(typeInt->is_con(), "must be constant"); | |
1341 jint value = typeInt->get_con(); | |
1342 | |
1343 // max. 2 chars allowed | |
1344 if (value >= -9 && value <= 99) { | |
1345 sprintf(buffer, "%d", value); | |
1346 desc->properties()->add(new Property(short_name, buffer)); | |
1347 } | |
1348 else | |
1349 { | |
1350 desc->properties()->add(new Property(short_name, "I")); | |
1351 } | |
1352 } else if (t == Type::TOP) { | |
1353 desc->properties()->add(new Property(short_name, "^")); | |
1354 } else if (t->base() == Type::Long && t->is_long()->is_con()) { | |
1355 const TypeLong *typeLong = t->is_long(); | |
1356 assert(typeLong->is_con(), "must be constant"); | |
1357 jlong value = typeLong->get_con(); | |
1358 | |
1359 // max. 2 chars allowed | |
1360 if (value >= -9 && value <= 99) { | |
1361 sprintf(buffer, "%d", value); | |
1362 desc->properties()->add(new Property(short_name, buffer)); | |
1363 } | |
1364 else | |
1365 { | |
1366 desc->properties()->add(new Property(short_name, "L")); | |
1367 } | |
1368 } else if (t->base() == Type::KlassPtr) { | |
1369 const TypeKlassPtr *typeKlass = t->is_klassptr(); | |
1370 desc->properties()->add(new Property(short_name, "CP")); | |
1371 } else if (t->base() == Type::Control) { | |
1372 desc->properties()->add(new Property(short_name, "C")); | |
1373 } else if (t->base() == Type::Memory) { | |
1374 desc->properties()->add(new Property(short_name, "M")); | |
1375 } else if (t->base() == Type::Abio) { | |
1376 desc->properties()->add(new Property(short_name, "IO")); | |
1377 } else if (t->base() == Type::Return_Address) { | |
1378 desc->properties()->add(new Property(short_name, "RA")); | |
1379 } else if (t->base() == Type::AnyPtr) { | |
1380 desc->properties()->add(new Property(short_name, "P")); | |
1381 } else if (t->base() == Type::RawPtr) { | |
1382 desc->properties()->add(new Property(short_name, "RP")); | |
1383 } else if (t->base() == Type::AryPtr) { | |
1384 desc->properties()->add(new Property(short_name, "AP")); | |
1385 } | |
1386 } | |
1387 | |
1388 if (node->is_SafePoint()) { | |
1389 SafePointNode *safePointNode = node->as_SafePoint(); | |
1390 if (safePointNode->jvms()) { | |
1391 stringStream bciStream; | |
1392 bciStream.print("%d ", safePointNode->jvms()->bci()); | |
1393 JVMState *caller = safePointNode->jvms()->caller(); | |
1394 while(caller) { | |
1395 bciStream.print("%d ", caller->bci()); | |
1396 | |
1397 caller = caller->caller(); | |
1398 } | |
1399 desc->properties()->add(new Property("bci", bciStream.as_string())); | |
1400 } | |
1401 } | |
1402 | |
1403 if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) { | |
1404 buffer[0] = 0; | |
1405 _chaitin->dump_register(node, buffer); | |
1406 desc->properties()->add(new Property("reg", buffer)); | |
1407 desc->properties()->add(new Property("lrg", _chaitin->n2lidx(node))); | |
1408 } | |
1409 | |
1410 | |
1411 node->_in_dump_cnt--; | |
1412 return desc; | |
1413 #else | |
1414 return NULL; | |
1415 #endif | |
1416 } | |
1417 | |
1418 void IdealGraphPrinter::pre_node(Node* node, void *env) { | |
1419 | |
1420 IdealGraphPrinter *printer = (IdealGraphPrinter *)env; | |
1421 | |
1422 NodeDescription *newDesc = printer->create_node_description(node); | |
1423 | |
1424 if (printer->_clear_nodes) { | |
1425 | |
1426 printer->_nodes.append(newDesc); | |
1427 } else { | |
1428 | |
1429 NodeDescription *desc = printer->_nodes.at_grow(node->_idx, NULL); | |
1430 | |
1431 if (desc && desc->equals(newDesc)) { | |
1432 //desc->set_state(Valid); | |
1433 //desc->set_node(node); | |
1434 delete desc; | |
1435 printer->_nodes.at_put(node->_idx, NULL); | |
1436 newDesc->set_state(Valid); | |
1437 //printer->_nodes.at_put(node->_idx, newDesc); | |
1438 } else { | |
1439 | |
1440 if (desc && desc->id() == newDesc->id()) { | |
1441 delete desc; | |
1442 printer->_nodes.at_put(node->_idx, NULL); | |
1443 newDesc->set_state(New); | |
1444 | |
1445 } | |
1446 | |
1447 //if (desc) { | |
1448 // delete desc; | |
1449 //} | |
1450 | |
1451 //printer->_nodes.at_put(node->_idx, newDesc); | |
1452 } | |
1453 | |
1454 printer->_nodes.append(newDesc); | |
1455 } | |
1456 } | |
1457 | |
1458 void IdealGraphPrinter::post_node(Node* node, void *env) { | |
1459 } | |
1460 | |
1461 outputStream *IdealGraphPrinter::output() { | |
1462 return _output; | |
1463 } | |
1464 | |
1465 IdealGraphPrinter::Description::Description() { | |
1466 _state = New; | |
1467 } | |
1468 | |
1469 void IdealGraphPrinter::Description::print(IdealGraphPrinter *printer) { | |
1470 if (_state == Invalid) { | |
1471 print_removed(printer); | |
1472 } else if (_state == New) { | |
1473 print_changed(printer); | |
1474 } | |
1475 } | |
1476 | |
1477 void IdealGraphPrinter::Description::set_state(State s) { | |
1478 _state = s; | |
1479 } | |
1480 | |
1481 IdealGraphPrinter::State IdealGraphPrinter::Description::state() { | |
1482 return _state; | |
1483 } | |
1484 | |
1485 void IdealGraphPrinter::Block::set_proj(NodeDescription *n) { | |
1486 _proj = n; | |
1487 } | |
1488 | |
1489 void IdealGraphPrinter::Block::set_start(NodeDescription *n) { | |
1490 _start = n; | |
1491 } | |
1492 | |
1493 int IdealGraphPrinter::Block::semi() { | |
1494 return _semi; | |
1495 } | |
1496 | |
1497 int IdealGraphPrinter::Block::parent() { | |
1498 return _parent; | |
1499 } | |
1500 | |
1501 GrowableArray<int>* IdealGraphPrinter::Block::bucket() { | |
1502 return &_bucket; | |
1503 } | |
1504 | |
1505 GrowableArray<int>* IdealGraphPrinter::Block::children() { | |
1506 return &_children; | |
1507 } | |
1508 | |
1509 void IdealGraphPrinter::Block::add_child(int i) { | |
1510 _children.append(i); | |
1511 } | |
1512 | |
1513 GrowableArray<int>* IdealGraphPrinter::Block::dominates() { | |
1514 return &_dominates; | |
1515 } | |
1516 | |
1517 void IdealGraphPrinter::Block::add_dominates(int i) { | |
1518 _dominates.append(i); | |
1519 } | |
1520 | |
1521 void IdealGraphPrinter::Block::add_to_bucket(int i) { | |
1522 _bucket.append(i); | |
1523 } | |
1524 | |
1525 void IdealGraphPrinter::Block::clear_bucket() { | |
1526 _bucket.clear(); | |
1527 } | |
1528 | |
1529 void IdealGraphPrinter::Block::set_dominator(int i) { | |
1530 _dominator = i; | |
1531 } | |
1532 | |
1533 void IdealGraphPrinter::Block::set_label(int i) { | |
1534 _label = i; | |
1535 } | |
1536 | |
1537 int IdealGraphPrinter::Block::label() { | |
1538 return _label; | |
1539 } | |
1540 | |
1541 int IdealGraphPrinter::Block::ancestor() { | |
1542 return _ancestor; | |
1543 } | |
1544 | |
1545 void IdealGraphPrinter::Block::set_ancestor(int i) { | |
1546 _ancestor = i; | |
1547 } | |
1548 | |
1549 int IdealGraphPrinter::Block::dominator() { | |
1550 return _dominator; | |
1551 } | |
1552 | |
1553 int IdealGraphPrinter::Block::index() { | |
1554 return _index; | |
1555 } | |
1556 | |
1557 void IdealGraphPrinter::Block::set_parent(int i) { | |
1558 _parent = i; | |
1559 } | |
1560 | |
1561 GrowableArray<int>* IdealGraphPrinter::Block::pred() { | |
1562 return &_pred; | |
1563 } | |
1564 | |
1565 void IdealGraphPrinter::Block::set_semi(int i) { | |
1566 _semi = i; | |
1567 } | |
1568 | |
1569 IdealGraphPrinter::Block::Block() { | |
1570 } | |
1571 | |
1572 IdealGraphPrinter::Block::Block(int index) { | |
1573 _index = index; | |
1574 _label = index; | |
1575 _semi = -1; | |
1576 _ancestor = -1; | |
1577 _dominator = -1; | |
1578 } | |
1579 | |
1580 void IdealGraphPrinter::Block::add_pred(int i) { | |
1581 _pred.append(i); | |
1582 } | |
1583 | |
1584 IdealGraphPrinter::NodeDescription *IdealGraphPrinter::Block::proj() { | |
1585 return _proj; | |
1586 } | |
1587 | |
1588 IdealGraphPrinter::NodeDescription *IdealGraphPrinter::Block::start() { | |
1589 return _start; | |
1590 } | |
1591 | |
1592 GrowableArray<int>* IdealGraphPrinter::Block::succs() { | |
1593 return &_succs; | |
1594 } | |
1595 | |
1596 void IdealGraphPrinter::Block::add_succ(int index) { | |
1597 | |
1598 if (this->_index == 16 && index == 15) { | |
1599 int x = 0; | |
1600 } | |
1601 | |
1602 if (!_succs.contains(index)) { | |
1603 _succs.append(index); | |
1604 } | |
1605 } | |
1606 | |
1607 | |
1608 void IdealGraphPrinter::Block::add_node(NodeDescription *n) { | |
1609 if (!_nodes.contains(n)) { | |
1610 _nodes.append(n); | |
1611 } | |
1612 } | |
1613 | |
1614 GrowableArray<IdealGraphPrinter::NodeDescription *>* IdealGraphPrinter::Block::nodes() { | |
1615 return &_nodes; | |
1616 } | |
1617 | |
1618 int IdealGraphPrinter::NodeDescription::count = 0; | |
1619 | |
1620 IdealGraphPrinter::NodeDescription::NodeDescription(Node* node) : _node(node) { | |
1621 _id = (intptr_t)(node); | |
1622 _block_index = -1; | |
1623 } | |
1624 | |
1625 IdealGraphPrinter::NodeDescription::~NodeDescription() { | |
1626 _properties.clean(); | |
1627 } | |
1628 | |
1629 // void IdealGraphPrinter::NodeDescription::set_node(Node* node) { | |
1630 // //this->_node = node; | |
1631 // } | |
1632 | |
1633 int IdealGraphPrinter::NodeDescription::block_index() { | |
1634 return _block_index; | |
1635 } | |
1636 | |
1637 | |
1638 GrowableArray<IdealGraphPrinter::NodeDescription *>* IdealGraphPrinter::NodeDescription::succs() { | |
1639 return &_succs; | |
1640 } | |
1641 | |
1642 void IdealGraphPrinter::NodeDescription::clear_succs() { | |
1643 _succs.clear(); | |
1644 } | |
1645 | |
1646 void IdealGraphPrinter::NodeDescription::init_succs() { | |
1647 _succs = GrowableArray<NodeDescription *>(); | |
1648 } | |
1649 | |
1650 void IdealGraphPrinter::NodeDescription::add_succ(NodeDescription *desc) { | |
1651 _succs.append(desc); | |
1652 } | |
1653 | |
1654 void IdealGraphPrinter::NodeDescription::set_block_index(int i) { | |
1655 _block_index = i; | |
1656 } | |
1657 | |
1658 bool IdealGraphPrinter::NodeDescription::equals(NodeDescription *desc) { | |
1659 if (desc == NULL) return false; | |
1660 if (desc->id() != id()) return false; | |
1661 return properties()->equals(desc->properties()); | |
1662 } | |
1663 | |
1664 Node* IdealGraphPrinter::NodeDescription::node() { | |
1665 return _node; | |
1666 } | |
1667 | |
1668 IdealGraphPrinter::Properties* IdealGraphPrinter::NodeDescription::properties() { | |
1669 return &_properties; | |
1670 } | |
1671 | |
1672 uint IdealGraphPrinter::NodeDescription::id() { | |
1673 return _id; | |
1674 } | |
1675 | |
1676 void IdealGraphPrinter::NodeDescription::print_changed(IdealGraphPrinter *printer) { | |
1677 | |
1678 | |
1679 Properties properties; | |
1680 properties.add(new Property(NODE_ID_PROPERTY, id())); | |
1681 printer->start_element(NODE_ELEMENT, &properties); | |
1682 | |
1683 this->properties()->print(printer); | |
1684 | |
1685 | |
1686 printer->end_element(NODE_ELEMENT); | |
1687 } | |
1688 | |
1689 void IdealGraphPrinter::NodeDescription::print_removed(IdealGraphPrinter *printer) { | |
1690 | |
1691 Properties properties; | |
1692 properties.add(new Property(NODE_ID_PROPERTY, id())); | |
1693 printer->simple_element(REMOVE_NODE_ELEMENT, &properties); | |
1694 } | |
1695 | |
1696 IdealGraphPrinter::EdgeDescription::EdgeDescription(int from, int to, int index) { | |
1697 this->_from = from; | |
1698 this->_to = to; | |
1699 this->_index = index; | |
1700 } | |
1701 | |
1702 IdealGraphPrinter::EdgeDescription::~EdgeDescription() { | |
1703 } | |
1704 | |
1705 int IdealGraphPrinter::EdgeDescription::from() { | |
1706 return _from; | |
1707 } | |
1708 | |
1709 int IdealGraphPrinter::EdgeDescription::to() { | |
1710 return _to; | |
1711 } | |
1712 | |
1713 void IdealGraphPrinter::EdgeDescription::print_changed(IdealGraphPrinter *printer) { | |
1714 | |
1715 Properties properties; | |
1716 properties.add(new Property(INDEX_PROPERTY, _index)); | |
1717 properties.add(new Property(FROM_PROPERTY, _from)); | |
1718 properties.add(new Property(TO_PROPERTY, _to)); | |
1719 printer->simple_element(EDGE_ELEMENT, &properties); | |
1720 } | |
1721 | |
1722 void IdealGraphPrinter::EdgeDescription::print_removed(IdealGraphPrinter *printer) { | |
1723 | |
1724 Properties properties; | |
1725 properties.add(new Property(INDEX_PROPERTY, _index)); | |
1726 properties.add(new Property(FROM_PROPERTY, _from)); | |
1727 properties.add(new Property(TO_PROPERTY, _to)); | |
1728 printer->simple_element(REMOVE_EDGE_ELEMENT, &properties); | |
1729 } | |
1730 | |
1731 bool IdealGraphPrinter::EdgeDescription::equals(IdealGraphPrinter::EdgeDescription *desc) { | |
1732 if (desc == NULL) return false; | |
1733 return (_from == desc->_from && _to == desc->_to && _index == desc->_index); | |
1734 } | |
1735 | |
1736 IdealGraphPrinter::Properties::Properties() : list(new (ResourceObj::C_HEAP) GrowableArray<Property *>(2, 0, NULL, true)) { | |
1737 } | |
1738 | |
1739 IdealGraphPrinter::Properties::~Properties() { | |
1740 clean(); | |
1741 delete list; | |
1742 } | |
1743 | |
1744 void IdealGraphPrinter::Properties::add(Property *p) { | |
1745 assert(p != NULL, "Property not NULL"); | |
1746 list->append(p); | |
1747 } | |
1748 | |
1749 void IdealGraphPrinter::Properties::print(IdealGraphPrinter *printer) { | |
1750 printer->start_element(PROPERTIES_ELEMENT); | |
1751 | |
1752 for (int i = 0; i < list->length(); i++) { | |
1753 list->at(i)->print(printer); | |
1754 } | |
1755 | |
1756 printer->end_element(PROPERTIES_ELEMENT); | |
1757 } | |
1758 | |
1759 void IdealGraphPrinter::Properties::clean() { | |
1760 for (int i = 0; i < list->length(); i++) { | |
1761 delete list->at(i); | |
1762 list->at_put(i, NULL); | |
1763 } | |
1764 list->clear(); | |
1765 assert(list->length() == 0, "List cleared"); | |
1766 } | |
1767 | |
1768 void IdealGraphPrinter::Properties::remove(const char *name) { | |
1769 for (int i = 0; i < list->length(); i++) { | |
1770 if (strcmp(list->at(i)->name(), name) == 0) { | |
1771 delete list->at(i); | |
1772 list->remove_at(i); | |
1773 i--; | |
1774 } | |
1775 } | |
1776 } | |
1777 | |
1778 void IdealGraphPrinter::Properties::print_as_attributes(IdealGraphPrinter *printer) { | |
1779 | |
1780 for (int i = 0; i < list->length(); i++) { | |
1781 assert(list->at(i) != NULL, "Property not null!"); | |
1782 printer->output()->print(" "); | |
1783 list->at(i)->print_as_attribute(printer); | |
1784 } | |
1785 } | |
1786 | |
1787 bool IdealGraphPrinter::Properties::equals(Properties* p) { | |
1788 if (p->list->length() != this->list->length()) return false; | |
1789 | |
1790 for (int i = 0; i < list->length(); i++) { | |
1791 assert(list->at(i) != NULL, "Property not null!"); | |
1792 if (!list->at(i)->equals(p->list->at(i))) return false; | |
1793 } | |
1794 | |
1795 return true; | |
1796 } | |
1797 | |
1798 IdealGraphPrinter::Property::Property() { | |
1799 _name = NULL; | |
1800 _value = NULL; | |
1801 } | |
1802 | |
1803 const char *IdealGraphPrinter::Property::name() { | |
1804 return _name; | |
1805 } | |
1806 | |
1807 IdealGraphPrinter::Property::Property(const Property* p) { | |
1808 | |
1809 this->_name = NULL; | |
1810 this->_value = NULL; | |
1811 | |
1812 if (p->_name != NULL) { | |
1813 _name = dup(p->_name); | |
1814 } | |
1815 | |
1816 if (p->_value) { | |
1817 _value = dup(p->_value); | |
1818 } | |
1819 } | |
1820 | |
1821 IdealGraphPrinter::Property::~Property() { | |
1822 | |
1823 clean(); | |
1824 } | |
1825 | |
1826 IdealGraphPrinter::Property::Property(const char *name, const char *value) { | |
1827 | |
1828 assert(name, "Name must not be null!"); | |
1829 assert(value, "Value must not be null!"); | |
1830 | |
1831 _name = dup(name); | |
1832 _value = dup(value); | |
1833 } | |
1834 | |
1835 IdealGraphPrinter::Property::Property(const char *name, int intValue) { | |
1836 _name = dup(name); | |
1837 | |
1838 stringStream stream; | |
1839 stream.print("%d", intValue); | |
1840 _value = dup(stream.as_string()); | |
1841 } | |
1842 | |
1843 void IdealGraphPrinter::Property::clean() { | |
1844 if (_name) { | |
1845 delete _name; | |
1846 _name = NULL; | |
1847 } | |
1848 | |
1849 if (_value) { | |
1850 delete _value; | |
1851 _value = NULL; | |
1852 } | |
1853 } | |
1854 | |
1855 | |
1856 bool IdealGraphPrinter::Property::is_null() { | |
1857 return _name == NULL; | |
1858 } | |
1859 | |
1860 void IdealGraphPrinter::Property::print(IdealGraphPrinter *printer) { | |
1861 | |
1862 assert(!is_null(), "null properties cannot be printed!"); | |
1863 Properties properties; | |
1864 properties.add(new Property(PROPERTY_NAME_PROPERTY, _name)); | |
1865 printer->start_element(PROPERTY_ELEMENT, &properties, false, false); | |
1866 printer->print_xml(_value); | |
1867 printer->end_element(PROPERTY_ELEMENT, false, true); | |
1868 } | |
1869 | |
1870 void IdealGraphPrinter::Property::print_as_attribute(IdealGraphPrinter *printer) { | |
1871 | |
1872 printer->output()->print(_name); | |
1873 printer->output()->print("=\""); | |
1874 printer->print_xml(_value); | |
1875 printer->output()->print("\""); | |
1876 } | |
1877 | |
1878 | |
1879 bool IdealGraphPrinter::Property::equals(Property* p) { | |
1880 | |
1881 if (is_null() && p->is_null()) return true; | |
1882 if (is_null()) return false; | |
1883 if (p->is_null()) return false; | |
1884 | |
1885 int cmp1 = strcmp(p->_name, _name); | |
1886 if (cmp1 != 0) return false; | |
1887 | |
1888 int cmp2 = strcmp(p->_value, _value); | |
1889 if (cmp2 != 0) return false; | |
1890 | |
1891 return true; | |
1892 } | |
1893 | |
1894 void IdealGraphPrinter::print_xml(const char *value) { | |
1895 size_t len = strlen(value); | |
1896 | |
1897 char buf[2]; | |
1898 buf[1] = 0; | |
1899 for (size_t i = 0; i < len; i++) { | |
1900 char c = value[i]; | |
1901 | |
1902 switch(c) { | |
1903 case '<': | |
1904 output()->print("<"); | |
1905 break; | |
1906 | |
1907 case '>': | |
1908 output()->print(">"); | |
1909 break; | |
1910 | |
1911 default: | |
1912 buf[0] = c; | |
1913 output()->print(buf); | |
1914 break; | |
1915 } | |
1916 } | |
1917 } | |
1918 | |
1919 #endif |