519 #undef _LOG_PREFIX
520
521 // Log all the data [base...top). Pretend that the base address
522 // will be mapped to requested_base at run-time.
523 void AOTMapLogger::log_as_hex(address base, address top, address requested_base, bool is_heap) {
524 assert(top >= base, "must be");
525
526 LogStreamHandle(Trace, aot, map) lsh;
527 if (lsh.is_enabled()) {
528 int unitsize = sizeof(address);
529 if (is_heap && UseCompressedOops) {
530 // This makes the compressed oop pointers easier to read, but
531 // longs and doubles will be split into two words.
532 unitsize = sizeof(narrowOop);
533 }
534 os::print_hex_dump(&lsh, base, top, unitsize, /* print_ascii=*/true, /* bytes_per_line=*/32, requested_base);
535 }
536 }
537
538 #if INCLUDE_CDS_JAVA_HEAP
539 // FakeOop (and subclasses FakeMirror, FakeString, FakeObjArray, FakeTypeArray) are used to traverse
540 // and print the (image of) heap objects stored in the AOT cache. These objects are different than regular oops:
541 // - They do not reside inside the range of the heap.
542 // - For +UseCompressedOops: pointers may use a different narrowOop encoding: see FakeOop::read_oop_at(narrowOop*)
543 // - For -UseCompressedOops: pointers are not direct: see FakeOop::read_oop_at(oop*)
544 //
545 // Hence, in general, we cannot use regular oop API (such as oopDesc::obj_field()) on these objects. There
546 // are a few rare case where regular oop API work, but these are all guarded with the raw_oop() method and
547 // should be used with care.
548 //
549 // Each AOT heap reader and writer has its own oop_iterator() API that retrieves all the data required to build
550 // fake oops for logging.
551 class AOTMapLogger::FakeOop {
552 OopDataIterator* _iter;
553 OopData _data;
554
555 address* buffered_field_addr(int field_offset) {
556 return (address*)(buffered_addr() + field_offset);
557 }
558
559 public:
560 RequestedMetadataAddr metadata_field(int field_offset) {
561 return RequestedMetadataAddr(*(address*)(buffered_field_addr(field_offset)));
562 }
563
564 address buffered_addr() {
565 return _data._buffered_addr;
566 }
567
568 // Return an "oop" pointer so we can use APIs that accept regular oops. This
569 // must be used with care, as only a limited number of APIs can work with oops that
570 // live outside of the range of the heap.
571 oop raw_oop() { return _data._raw_oop; }
572
573 FakeOop() : _data() {}
574 FakeOop(OopDataIterator* iter, OopData data) : _iter(iter), _data(data) {}
575
576 FakeMirror as_mirror();
577 FakeObjArray as_obj_array();
578 FakeString as_string();
579 FakeTypeArray as_type_array();
580
581 RequestedMetadataAddr klass() {
582 address rk = (address)real_klass();
583 if (_is_runtime_logging) {
584 return RequestedMetadataAddr(rk - _requested_to_mapped_metadata_delta);
585 } else {
586 ArchiveBuilder* builder = ArchiveBuilder::current();
587 return builder->to_requested(builder->get_buffered_addr(rk));
588 }
589 }
590
591 Klass* real_klass() {
592 return _data._klass;
593 }
594
595 // in heap words
596 size_t size() {
597 return _data._size;
644 fd->print_on_for(st, raw_oop());
645 }
646 }; // AOTMapLogger::FakeOop
647
648 class AOTMapLogger::FakeMirror : public AOTMapLogger::FakeOop {
649 public:
650 FakeMirror(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
651
652 void print_class_signature_on(outputStream* st);
653
654 Klass* real_mirrored_klass() {
655 RequestedMetadataAddr mirrored_klass = metadata_field(java_lang_Class::klass_offset());
656 return mirrored_klass.to_real_klass();
657 }
658
659 int static_oop_field_count() {
660 return java_lang_Class::static_oop_field_count(raw_oop());
661 }
662 }; // AOTMapLogger::FakeMirror
663
664 class AOTMapLogger::FakeObjArray : public AOTMapLogger::FakeOop {
665 objArrayOop raw_objArrayOop() {
666 return (objArrayOop)raw_oop();
667 }
668
669 public:
670 FakeObjArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
671
672 int length() {
673 return raw_objArrayOop()->length();
674 }
675 FakeOop obj_at(int i) {
676 if (UseCompressedOops) {
677 return read_oop_at(raw_objArrayOop()->obj_at_addr<narrowOop>(i));
678 } else {
679 return read_oop_at(raw_objArrayOop()->obj_at_addr<oop>(i));
680 }
681 }
682 }; // AOTMapLogger::FakeObjArray
683
684 class AOTMapLogger::FakeString : public AOTMapLogger::FakeOop {
685 public:
686 FakeString(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
687
688 bool is_latin1() {
689 jbyte coder = raw_oop()->byte_field(java_lang_String::coder_offset());
690 assert(CompactStrings || coder == java_lang_String::CODER_UTF16, "Must be UTF16 without CompactStrings");
691 return coder == java_lang_String::CODER_LATIN1;
692 }
693
694 FakeTypeArray value();
695
696 int length();
697 void print_on(outputStream* st, int max_length = MaxStringPrintSize);
698 }; // AOTMapLogger::FakeString
699
700 class AOTMapLogger::FakeTypeArray : public AOTMapLogger::FakeOop {
701 typeArrayOop raw_typeArrayOop() {
702 return (typeArrayOop)raw_oop();
703 }
704
705 public:
706 FakeTypeArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
707
708 void print_elements_on(outputStream* st) {
709 TypeArrayKlass::cast(real_klass())->oop_print_elements_on(raw_typeArrayOop(), st);
710 }
711
712 int length() { return raw_typeArrayOop()->length(); }
713 jbyte byte_at(int i) { return raw_typeArrayOop()->byte_at(i); }
714 jchar char_at(int i) { return raw_typeArrayOop()->char_at(i); }
715 }; // AOTMapLogger::FakeTypeArray
716
717 AOTMapLogger::FakeMirror AOTMapLogger::FakeOop::as_mirror() {
718 precond(real_klass() == vmClasses::Class_klass());
719 return FakeMirror(_iter, _data);
720 }
721
722 AOTMapLogger::FakeObjArray AOTMapLogger::FakeOop::as_obj_array() {
723 precond(real_klass()->is_objArray_klass());
724 return FakeObjArray(_iter, _data);
725 }
726
727 AOTMapLogger::FakeTypeArray AOTMapLogger::FakeOop::as_type_array() {
728 precond(real_klass()->is_typeArray_klass());
729 return FakeTypeArray(_iter, _data);
730 }
731
732 AOTMapLogger::FakeString AOTMapLogger::FakeOop::as_string() {
733 precond(real_klass() == vmClasses::String_klass());
734 return FakeString(_iter, _data);
735 }
736
737 void AOTMapLogger::FakeMirror::print_class_signature_on(outputStream* st) {
738 ResourceMark rm;
739 RequestedMetadataAddr requested_klass = metadata_field(java_lang_Class::klass_offset());
740 Klass* real_klass = requested_klass.to_real_klass();
741
742 if (real_klass == nullptr) {
743 // This is a primitive mirror (Java expressions of int.class, long.class, void.class, etc);
744 RequestedMetadataAddr requested_array_klass = metadata_field(java_lang_Class::array_klass_offset());
949 } else if (real_klass == vmClasses::Class_klass()) {
950 fake_oop.as_mirror().print_class_signature_on(st);
951 }
952
953 st->cr();
954 }
955 }
956 }
957
958 // Print the fields of instanceOops, or the elements of arrayOops
959 void AOTMapLogger::print_oop_details(FakeOop fake_oop, outputStream* st) {
960 Klass* real_klass = fake_oop.real_klass();
961
962 st->print(" - klass: ");
963 real_klass->print_value_on(st);
964 st->print(" " PTR_FORMAT, p2i(fake_oop.klass().raw_addr()));
965 st->cr();
966
967 if (real_klass->is_typeArray_klass()) {
968 fake_oop.as_type_array().print_elements_on(st);
969 } else if (real_klass->is_objArray_klass()) {
970 FakeObjArray fake_obj_array = fake_oop.as_obj_array();
971 bool is_logging_root_segment = fake_oop.is_root_segment();
972
973 for (int i = 0; i < fake_obj_array.length(); i++) {
974 FakeOop elm = fake_obj_array.obj_at(i);
975 if (is_logging_root_segment) {
976 st->print(" root[%4d]: ", _roots->length());
977 _roots->append(elm);
978 } else {
979 st->print(" -%4d: ", i);
980 }
981 print_oop_info_cr(st, elm);
982 }
983 } else {
984 st->print_cr(" - fields (%zu words):", fake_oop.size());
985
986 ArchivedFieldPrinter print_field(fake_oop, st);
987 InstanceKlass::cast(real_klass)->print_nonstatic_fields(&print_field);
988
989 if (real_klass == vmClasses::Class_klass()) {
990 FakeMirror fake_mirror = fake_oop.as_mirror();
|
519 #undef _LOG_PREFIX
520
521 // Log all the data [base...top). Pretend that the base address
522 // will be mapped to requested_base at run-time.
523 void AOTMapLogger::log_as_hex(address base, address top, address requested_base, bool is_heap) {
524 assert(top >= base, "must be");
525
526 LogStreamHandle(Trace, aot, map) lsh;
527 if (lsh.is_enabled()) {
528 int unitsize = sizeof(address);
529 if (is_heap && UseCompressedOops) {
530 // This makes the compressed oop pointers easier to read, but
531 // longs and doubles will be split into two words.
532 unitsize = sizeof(narrowOop);
533 }
534 os::print_hex_dump(&lsh, base, top, unitsize, /* print_ascii=*/true, /* bytes_per_line=*/32, requested_base);
535 }
536 }
537
538 #if INCLUDE_CDS_JAVA_HEAP
539 // FakeOop (and subclasses FakeMirror, FakeString, FakeRefArray, FakeFlatArray, FakeTypeArray) are used to traverse
540 // and print the (image of) heap objects stored in the AOT cache. These objects are different than regular oops:
541 // - They do not reside inside the range of the heap.
542 // - For +UseCompressedOops: pointers may use a different narrowOop encoding: see FakeOop::read_oop_at(narrowOop*)
543 // - For -UseCompressedOops: pointers are not direct: see FakeOop::read_oop_at(oop*)
544 //
545 // Hence, in general, we cannot use regular oop API (such as oopDesc::obj_field()) on these objects. There
546 // are a few rare case where regular oop API work, but these are all guarded with the raw_oop() method and
547 // should be used with care.
548 //
549 // Each AOT heap reader and writer has its own oop_iterator() API that retrieves all the data required to build
550 // fake oops for logging.
551 class AOTMapLogger::FakeOop {
552 OopDataIterator* _iter;
553 OopData _data;
554
555 address* buffered_field_addr(int field_offset) {
556 return (address*)(buffered_addr() + field_offset);
557 }
558
559 public:
560 RequestedMetadataAddr metadata_field(int field_offset) {
561 return RequestedMetadataAddr(*(address*)(buffered_field_addr(field_offset)));
562 }
563
564 address buffered_addr() {
565 return _data._buffered_addr;
566 }
567
568 // Return an "oop" pointer so we can use APIs that accept regular oops. This
569 // must be used with care, as only a limited number of APIs can work with oops that
570 // live outside of the range of the heap.
571 oop raw_oop() { return _data._raw_oop; }
572
573 FakeOop() : _data() {}
574 FakeOop(OopDataIterator* iter, OopData data) : _iter(iter), _data(data) {}
575
576 FakeMirror as_mirror();
577 FakeRefArray as_ref_array();
578 FakeFlatArray as_flat_array();
579 FakeString as_string();
580 FakeTypeArray as_type_array();
581
582 RequestedMetadataAddr klass() {
583 address rk = (address)real_klass();
584 if (_is_runtime_logging) {
585 return RequestedMetadataAddr(rk - _requested_to_mapped_metadata_delta);
586 } else {
587 ArchiveBuilder* builder = ArchiveBuilder::current();
588 return builder->to_requested(builder->get_buffered_addr(rk));
589 }
590 }
591
592 Klass* real_klass() {
593 return _data._klass;
594 }
595
596 // in heap words
597 size_t size() {
598 return _data._size;
645 fd->print_on_for(st, raw_oop());
646 }
647 }; // AOTMapLogger::FakeOop
648
649 class AOTMapLogger::FakeMirror : public AOTMapLogger::FakeOop {
650 public:
651 FakeMirror(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
652
653 void print_class_signature_on(outputStream* st);
654
655 Klass* real_mirrored_klass() {
656 RequestedMetadataAddr mirrored_klass = metadata_field(java_lang_Class::klass_offset());
657 return mirrored_klass.to_real_klass();
658 }
659
660 int static_oop_field_count() {
661 return java_lang_Class::static_oop_field_count(raw_oop());
662 }
663 }; // AOTMapLogger::FakeMirror
664
665 class AOTMapLogger::FakeRefArray : public AOTMapLogger::FakeOop {
666 refArrayOop raw_refArrayOop() {
667 return (refArrayOop)raw_oop();
668 }
669
670 public:
671 FakeRefArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
672
673 int length() {
674 return raw_refArrayOop()->length();
675 }
676 FakeOop obj_at(int i) {
677 if (UseCompressedOops) {
678 return read_oop_at(raw_refArrayOop()->obj_at_addr<narrowOop>(i));
679 } else {
680 return read_oop_at(raw_refArrayOop()->obj_at_addr<oop>(i));
681 }
682 }
683 }; // AOTMapLogger::FakeRefArray
684
685 class AOTMapLogger::FakeFlatArray : public AOTMapLogger::FakeOop {
686 flatArrayOop raw_flatArrayOop() {
687 return (flatArrayOop)raw_oop();
688 }
689
690 public:
691 FakeFlatArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
692
693 int length() {
694 return raw_flatArrayOop()->length();
695 }
696 void print_elements_on(outputStream* st) {
697 FlatArrayKlass::cast(real_klass())->oop_print_elements_on(raw_flatArrayOop(), st);
698 }
699
700 }; // AOTMapLogger::FakeRefArray
701
702 class AOTMapLogger::FakeString : public AOTMapLogger::FakeOop {
703 public:
704 FakeString(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
705
706 bool is_latin1() {
707 jbyte coder = raw_oop()->byte_field(java_lang_String::coder_offset());
708 assert(CompactStrings || coder == java_lang_String::CODER_UTF16, "Must be UTF16 without CompactStrings");
709 return coder == java_lang_String::CODER_LATIN1;
710 }
711
712 FakeTypeArray value();
713
714 int length();
715 void print_on(outputStream* st, int max_length = MaxStringPrintSize);
716 }; // AOTMapLogger::FakeString
717
718 class AOTMapLogger::FakeTypeArray : public AOTMapLogger::FakeOop {
719 typeArrayOop raw_typeArrayOop() {
720 return (typeArrayOop)raw_oop();
721 }
722
723 public:
724 FakeTypeArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
725
726 void print_elements_on(outputStream* st) {
727 TypeArrayKlass::cast(real_klass())->oop_print_elements_on(raw_typeArrayOop(), st);
728 }
729
730 int length() { return raw_typeArrayOop()->length(); }
731 jbyte byte_at(int i) { return raw_typeArrayOop()->byte_at(i); }
732 jchar char_at(int i) { return raw_typeArrayOop()->char_at(i); }
733 }; // AOTMapLogger::FakeTypeArray
734
735 AOTMapLogger::FakeMirror AOTMapLogger::FakeOop::as_mirror() {
736 precond(real_klass() == vmClasses::Class_klass());
737 return FakeMirror(_iter, _data);
738 }
739
740 AOTMapLogger::FakeRefArray AOTMapLogger::FakeOop::as_ref_array() {
741 precond(real_klass()->is_refArray_klass());
742 return FakeRefArray(_iter, _data);
743 }
744
745 AOTMapLogger::FakeFlatArray AOTMapLogger::FakeOop::as_flat_array() {
746 precond(real_klass()->is_flatArray_klass());
747 return FakeFlatArray(_iter, _data);
748 }
749
750 AOTMapLogger::FakeTypeArray AOTMapLogger::FakeOop::as_type_array() {
751 precond(real_klass()->is_typeArray_klass());
752 return FakeTypeArray(_iter, _data);
753 }
754
755 AOTMapLogger::FakeString AOTMapLogger::FakeOop::as_string() {
756 precond(real_klass() == vmClasses::String_klass());
757 return FakeString(_iter, _data);
758 }
759
760 void AOTMapLogger::FakeMirror::print_class_signature_on(outputStream* st) {
761 ResourceMark rm;
762 RequestedMetadataAddr requested_klass = metadata_field(java_lang_Class::klass_offset());
763 Klass* real_klass = requested_klass.to_real_klass();
764
765 if (real_klass == nullptr) {
766 // This is a primitive mirror (Java expressions of int.class, long.class, void.class, etc);
767 RequestedMetadataAddr requested_array_klass = metadata_field(java_lang_Class::array_klass_offset());
972 } else if (real_klass == vmClasses::Class_klass()) {
973 fake_oop.as_mirror().print_class_signature_on(st);
974 }
975
976 st->cr();
977 }
978 }
979 }
980
981 // Print the fields of instanceOops, or the elements of arrayOops
982 void AOTMapLogger::print_oop_details(FakeOop fake_oop, outputStream* st) {
983 Klass* real_klass = fake_oop.real_klass();
984
985 st->print(" - klass: ");
986 real_klass->print_value_on(st);
987 st->print(" " PTR_FORMAT, p2i(fake_oop.klass().raw_addr()));
988 st->cr();
989
990 if (real_klass->is_typeArray_klass()) {
991 fake_oop.as_type_array().print_elements_on(st);
992 } else if (real_klass->is_flatArray_klass()) {
993 // Archiving FlatArrayOop with embedded oops is not supported.
994 // TODO: add restriction.
995 fake_oop.as_flat_array().print_elements_on(st);
996 } else if (real_klass->is_refArray_klass()) {
997 FakeRefArray fake_obj_array = fake_oop.as_ref_array();
998 bool is_logging_root_segment = fake_oop.is_root_segment();
999
1000 for (int i = 0; i < fake_obj_array.length(); i++) {
1001 FakeOop elm = fake_obj_array.obj_at(i);
1002 if (is_logging_root_segment) {
1003 st->print(" root[%4d]: ", _roots->length());
1004 _roots->append(elm);
1005 } else {
1006 st->print(" -%4d: ", i);
1007 }
1008 print_oop_info_cr(st, elm);
1009 }
1010 } else {
1011 st->print_cr(" - fields (%zu words):", fake_oop.size());
1012
1013 ArchivedFieldPrinter print_field(fake_oop, st);
1014 InstanceKlass::cast(real_klass)->print_nonstatic_fields(&print_field);
1015
1016 if (real_klass == vmClasses::Class_klass()) {
1017 FakeMirror fake_mirror = fake_oop.as_mirror();
|