@@ -482,6 +482,8 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {
482482 print_prop (" idealOpcode" , (const char *)NodeClassNames[node->as_Mach ()->ideal_Opcode ()]);
483483 }
484484
485+ print_field (node);
486+
485487 buffer[0 ] = 0 ;
486488 stringStream s2 (buffer, sizeof (buffer) - 1 );
487489
@@ -630,9 +632,96 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {
630632 }
631633}
632634
633- void IdealGraphPrinter::walk_nodes (Node *start, bool edges, VectorSet* temp_set) {
635+ void IdealGraphPrinter::print_field (const Node* node) {
636+ buffer[0 ] = 0 ;
637+ stringStream ss (buffer, sizeof (buffer) - 1 );
638+ ciField* field = get_field (node);
639+ uint depth = 0 ;
640+ if (field == NULL ) {
641+ depth++;
642+ field = find_source_field_of_array_access (node, depth);
643+ }
644+
645+ if (field != NULL ) {
646+ // Either direct field access or array access
647+ field->print_name_on (&ss);
648+ for (uint i = 0 ; i < depth; i++) {
649+ // For arrays: Add [] for each dimension
650+ ss.print (" []" );
651+ }
652+ if (node->is_Store ()) {
653+ print_prop (" destination" , buffer);
654+ } else {
655+ print_prop (" source" , buffer);
656+ }
657+ }
658+ }
659+
660+ ciField* IdealGraphPrinter::get_field (const Node* node) {
661+ const TypePtr* adr_type = node->adr_type ();
662+ Compile::AliasType* atp = NULL ;
663+ if (C->have_alias_type (adr_type)) {
664+ atp = C->alias_type (adr_type);
665+ }
666+ if (atp != NULL ) {
667+ ciField* field = atp->field ();
668+ if (field != NULL ) {
669+ // Found field associated with 'node'.
670+ return field;
671+ }
672+ }
673+ return NULL ;
674+ }
675+
676+ // Try to find the field that is associated with a memory node belonging to an array access.
677+ ciField* IdealGraphPrinter::find_source_field_of_array_access (const Node* node, uint& depth) {
678+ if (!node->is_Mem ()) {
679+ // Not an array access
680+ return NULL ;
681+ }
682+
683+ do {
684+ if (node->adr_type () != NULL && node->adr_type ()->isa_aryptr ()) {
685+ // Only process array accesses. Pattern match to find actual field source access.
686+ node = get_load_node (node);
687+ if (node != NULL ) {
688+ ciField* field = get_field (node);
689+ if (field != NULL ) {
690+ return field;
691+ }
692+ // Could be a multi-dimensional array. Repeat loop.
693+ depth++;
694+ continue ;
695+ }
696+ }
697+ // Not an array access with a field source.
698+ break ;
699+ } while (depth < 256 ); // Cannot have more than 255 dimensions
634700
701+ return NULL ;
702+ }
703+
704+ // Pattern match on the inputs of 'node' to find load node for the field access.
705+ Node* IdealGraphPrinter::get_load_node (const Node* node) {
706+ Node* load = NULL ;
707+ Node* addr = node->as_Mem ()->in (MemNode::Address);
708+ if (addr != NULL && addr->is_AddP ()) {
709+ Node* base = addr->as_AddP ()->base_node ();
710+ if (base != NULL ) {
711+ base = base->uncast ();
712+ if (base->is_Load ()) {
713+ // Mem(AddP([ConstraintCast*](LoadP))) for non-compressed oops.
714+ load = base;
715+ } else if (base->is_DecodeN () && base->in (1 )->is_Load ()) {
716+ // Mem(AddP([ConstraintCast*](DecodeN(LoadN)))) for compressed oops.
717+ load = base->in (1 );
718+ }
719+ }
720+ }
721+ return load;
722+ }
635723
724+ void IdealGraphPrinter::walk_nodes (Node* start, bool edges, VectorSet* temp_set) {
636725 VectorSet visited;
637726 GrowableArray<Node *> nodeStack (Thread::current ()->resource_area (), 0 , 0 , NULL );
638727 nodeStack.push (start);
0 commit comments