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 |
|