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