475 #undef _LOG_PREFIX
476
477 // Log all the data [base...top). Pretend that the base address
478 // will be mapped to requested_base at run-time.
479 void AOTMapLogger::log_as_hex(address base, address top, address requested_base, bool is_heap) {
480 assert(top >= base, "must be");
481
482 LogStreamHandle(Trace, aot, map) lsh;
483 if (lsh.is_enabled()) {
484 int unitsize = sizeof(address);
485 if (is_heap && UseCompressedOops) {
486 // This makes the compressed oop pointers easier to read, but
487 // longs and doubles will be split into two words.
488 unitsize = sizeof(narrowOop);
489 }
490 os::print_hex_dump(&lsh, base, top, unitsize, /* print_ascii=*/true, /* bytes_per_line=*/32, requested_base);
491 }
492 }
493
494 #if INCLUDE_CDS_JAVA_HEAP
495 // FakeOop (and subclasses FakeMirror, FakeString, FakeObjArray, FakeTypeArray) are used to traverse
496 // and print the (image of) heap objects stored in the AOT cache. These objects are different than regular oops:
497 // - They do not reside inside the range of the heap.
498 // - For +UseCompressedOops: pointers may use a different narrowOop encoding: see FakeOop::read_oop_at(narrowOop*)
499 // - For -UseCompressedOops: pointers are not direct: see FakeOop::read_oop_at(oop*)
500 //
501 // Hence, in general, we cannot use regular oop API (such as oopDesc::obj_field()) on these objects. There
502 // are a few rare case where regular oop API work, but these are all guarded with the raw_oop() method and
503 // should be used with care.
504 //
505 // Each AOT heap reader and writer has its own oop_iterator() API that retrieves all the data required to build
506 // fake oops for logging.
507 class AOTMapLogger::FakeOop {
508 OopDataIterator* _iter;
509 OopData _data;
510
511 address* buffered_field_addr(int field_offset) {
512 return (address*)(buffered_addr() + field_offset);
513 }
514
515 public:
516 RequestedMetadataAddr metadata_field(int field_offset) {
517 return RequestedMetadataAddr(*(address*)(buffered_field_addr(field_offset)));
518 }
519
520 address buffered_addr() {
521 return _data._buffered_addr;
522 }
523
524 // Return an "oop" pointer so we can use APIs that accept regular oops. This
525 // must be used with care, as only a limited number of APIs can work with oops that
526 // live outside of the range of the heap.
527 oop raw_oop() { return _data._raw_oop; }
528
529 FakeOop() : _data() {}
530 FakeOop(OopDataIterator* iter, OopData data) : _iter(iter), _data(data) {}
531
532 FakeMirror as_mirror();
533 FakeObjArray as_obj_array();
534 FakeString as_string();
535 FakeTypeArray as_type_array();
536
537 RequestedMetadataAddr klass() {
538 address rk = (address)real_klass();
539 if (_is_runtime_logging) {
540 return RequestedMetadataAddr(rk - _requested_to_mapped_metadata_delta);
541 } else {
542 ArchiveBuilder* builder = ArchiveBuilder::current();
543 return builder->to_requested(builder->get_buffered_addr(rk));
544 }
545 }
546
547 Klass* real_klass() {
548 assert(UseCompressedClassPointers, "heap archiving requires UseCompressedClassPointers");
549 return _data._klass;
550 }
551
552 // in heap words
553 size_t size() {
601 fd->print_on_for(st, raw_oop());
602 }
603 }; // AOTMapLogger::FakeOop
604
605 class AOTMapLogger::FakeMirror : public AOTMapLogger::FakeOop {
606 public:
607 FakeMirror(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
608
609 void print_class_signature_on(outputStream* st);
610
611 Klass* real_mirrored_klass() {
612 RequestedMetadataAddr mirrored_klass = metadata_field(java_lang_Class::klass_offset());
613 return mirrored_klass.to_real_klass();
614 }
615
616 int static_oop_field_count() {
617 return java_lang_Class::static_oop_field_count(raw_oop());
618 }
619 }; // AOTMapLogger::FakeMirror
620
621 class AOTMapLogger::FakeObjArray : public AOTMapLogger::FakeOop {
622 objArrayOop raw_objArrayOop() {
623 return (objArrayOop)raw_oop();
624 }
625
626 public:
627 FakeObjArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
628
629 int length() {
630 return raw_objArrayOop()->length();
631 }
632 FakeOop obj_at(int i) {
633 if (UseCompressedOops) {
634 return read_oop_at(raw_objArrayOop()->obj_at_addr<narrowOop>(i));
635 } else {
636 return read_oop_at(raw_objArrayOop()->obj_at_addr<oop>(i));
637 }
638 }
639 }; // AOTMapLogger::FakeObjArray
640
641 class AOTMapLogger::FakeString : public AOTMapLogger::FakeOop {
642 public:
643 FakeString(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
644
645 bool is_latin1() {
646 jbyte coder = raw_oop()->byte_field(java_lang_String::coder_offset());
647 assert(CompactStrings || coder == java_lang_String::CODER_UTF16, "Must be UTF16 without CompactStrings");
648 return coder == java_lang_String::CODER_LATIN1;
649 }
650
651 FakeTypeArray value();
652
653 int length();
654 void print_on(outputStream* st, int max_length = MaxStringPrintSize);
655 }; // AOTMapLogger::FakeString
656
657 class AOTMapLogger::FakeTypeArray : public AOTMapLogger::FakeOop {
658 typeArrayOop raw_typeArrayOop() {
659 return (typeArrayOop)raw_oop();
660 }
661
662 public:
663 FakeTypeArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
664
665 void print_elements_on(outputStream* st) {
666 TypeArrayKlass::cast(real_klass())->oop_print_elements_on(raw_typeArrayOop(), st);
667 }
668
669 int length() { return raw_typeArrayOop()->length(); }
670 jbyte byte_at(int i) { return raw_typeArrayOop()->byte_at(i); }
671 jchar char_at(int i) { return raw_typeArrayOop()->char_at(i); }
672 }; // AOTMapLogger::FakeTypeArray
673
674 AOTMapLogger::FakeMirror AOTMapLogger::FakeOop::as_mirror() {
675 precond(real_klass() == vmClasses::Class_klass());
676 return FakeMirror(_iter, _data);
677 }
678
679 AOTMapLogger::FakeObjArray AOTMapLogger::FakeOop::as_obj_array() {
680 precond(real_klass()->is_objArray_klass());
681 return FakeObjArray(_iter, _data);
682 }
683
684 AOTMapLogger::FakeTypeArray AOTMapLogger::FakeOop::as_type_array() {
685 precond(real_klass()->is_typeArray_klass());
686 return FakeTypeArray(_iter, _data);
687 }
688
689 AOTMapLogger::FakeString AOTMapLogger::FakeOop::as_string() {
690 precond(real_klass() == vmClasses::String_klass());
691 return FakeString(_iter, _data);
692 }
693
694 void AOTMapLogger::FakeMirror::print_class_signature_on(outputStream* st) {
695 ResourceMark rm;
696 RequestedMetadataAddr requested_klass = metadata_field(java_lang_Class::klass_offset());
697 Klass* real_klass = requested_klass.to_real_klass();
698
699 if (real_klass == nullptr) {
700 // This is a primitive mirror (Java expressions of int.class, long.class, void.class, etc);
701 RequestedMetadataAddr requested_array_klass = metadata_field(java_lang_Class::array_klass_offset());
906 } else if (real_klass == vmClasses::Class_klass()) {
907 fake_oop.as_mirror().print_class_signature_on(st);
908 }
909
910 st->cr();
911 }
912 }
913 }
914
915 // Print the fields of instanceOops, or the elements of arrayOops
916 void AOTMapLogger::print_oop_details(FakeOop fake_oop, outputStream* st) {
917 Klass* real_klass = fake_oop.real_klass();
918
919 st->print(" - klass: ");
920 real_klass->print_value_on(st);
921 st->print(" " PTR_FORMAT, p2i(fake_oop.klass().raw_addr()));
922 st->cr();
923
924 if (real_klass->is_typeArray_klass()) {
925 fake_oop.as_type_array().print_elements_on(st);
926 } else if (real_klass->is_objArray_klass()) {
927 FakeObjArray fake_obj_array = fake_oop.as_obj_array();
928 bool is_logging_root_segment = fake_oop.is_root_segment();
929
930 for (int i = 0; i < fake_obj_array.length(); i++) {
931 FakeOop elm = fake_obj_array.obj_at(i);
932 if (is_logging_root_segment) {
933 st->print(" root[%4d]: ", _roots->length());
934 _roots->append(elm);
935 } else {
936 st->print(" -%4d: ", i);
937 }
938 print_oop_info_cr(st, elm);
939 }
940 } else {
941 st->print_cr(" - fields (%zu words):", fake_oop.size());
942
943 ArchivedFieldPrinter print_field(fake_oop, st);
944 InstanceKlass::cast(real_klass)->print_nonstatic_fields(&print_field);
945
946 if (real_klass == vmClasses::Class_klass()) {
947 FakeMirror fake_mirror = fake_oop.as_mirror();
|
475 #undef _LOG_PREFIX
476
477 // Log all the data [base...top). Pretend that the base address
478 // will be mapped to requested_base at run-time.
479 void AOTMapLogger::log_as_hex(address base, address top, address requested_base, bool is_heap) {
480 assert(top >= base, "must be");
481
482 LogStreamHandle(Trace, aot, map) lsh;
483 if (lsh.is_enabled()) {
484 int unitsize = sizeof(address);
485 if (is_heap && UseCompressedOops) {
486 // This makes the compressed oop pointers easier to read, but
487 // longs and doubles will be split into two words.
488 unitsize = sizeof(narrowOop);
489 }
490 os::print_hex_dump(&lsh, base, top, unitsize, /* print_ascii=*/true, /* bytes_per_line=*/32, requested_base);
491 }
492 }
493
494 #if INCLUDE_CDS_JAVA_HEAP
495 // FakeOop (and subclasses FakeMirror, FakeString, FakeRefArray, FakeFlatArray, FakeTypeArray) are used to traverse
496 // and print the (image of) heap objects stored in the AOT cache. These objects are different than regular oops:
497 // - They do not reside inside the range of the heap.
498 // - For +UseCompressedOops: pointers may use a different narrowOop encoding: see FakeOop::read_oop_at(narrowOop*)
499 // - For -UseCompressedOops: pointers are not direct: see FakeOop::read_oop_at(oop*)
500 //
501 // Hence, in general, we cannot use regular oop API (such as oopDesc::obj_field()) on these objects. There
502 // are a few rare case where regular oop API work, but these are all guarded with the raw_oop() method and
503 // should be used with care.
504 //
505 // Each AOT heap reader and writer has its own oop_iterator() API that retrieves all the data required to build
506 // fake oops for logging.
507 class AOTMapLogger::FakeOop {
508 OopDataIterator* _iter;
509 OopData _data;
510
511 address* buffered_field_addr(int field_offset) {
512 return (address*)(buffered_addr() + field_offset);
513 }
514
515 public:
516 RequestedMetadataAddr metadata_field(int field_offset) {
517 return RequestedMetadataAddr(*(address*)(buffered_field_addr(field_offset)));
518 }
519
520 address buffered_addr() {
521 return _data._buffered_addr;
522 }
523
524 // Return an "oop" pointer so we can use APIs that accept regular oops. This
525 // must be used with care, as only a limited number of APIs can work with oops that
526 // live outside of the range of the heap.
527 oop raw_oop() { return _data._raw_oop; }
528
529 FakeOop() : _data() {}
530 FakeOop(OopDataIterator* iter, OopData data) : _iter(iter), _data(data) {}
531
532 FakeMirror as_mirror();
533 FakeRefArray as_ref_array();
534 FakeFlatArray as_flat_array();
535 FakeString as_string();
536 FakeTypeArray as_type_array();
537
538 RequestedMetadataAddr klass() {
539 address rk = (address)real_klass();
540 if (_is_runtime_logging) {
541 return RequestedMetadataAddr(rk - _requested_to_mapped_metadata_delta);
542 } else {
543 ArchiveBuilder* builder = ArchiveBuilder::current();
544 return builder->to_requested(builder->get_buffered_addr(rk));
545 }
546 }
547
548 Klass* real_klass() {
549 assert(UseCompressedClassPointers, "heap archiving requires UseCompressedClassPointers");
550 return _data._klass;
551 }
552
553 // in heap words
554 size_t size() {
602 fd->print_on_for(st, raw_oop());
603 }
604 }; // AOTMapLogger::FakeOop
605
606 class AOTMapLogger::FakeMirror : public AOTMapLogger::FakeOop {
607 public:
608 FakeMirror(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
609
610 void print_class_signature_on(outputStream* st);
611
612 Klass* real_mirrored_klass() {
613 RequestedMetadataAddr mirrored_klass = metadata_field(java_lang_Class::klass_offset());
614 return mirrored_klass.to_real_klass();
615 }
616
617 int static_oop_field_count() {
618 return java_lang_Class::static_oop_field_count(raw_oop());
619 }
620 }; // AOTMapLogger::FakeMirror
621
622 class AOTMapLogger::FakeRefArray : public AOTMapLogger::FakeOop {
623 refArrayOop raw_refArrayOop() {
624 return (refArrayOop)raw_oop();
625 }
626
627 public:
628 FakeRefArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
629
630 int length() {
631 return raw_refArrayOop()->length();
632 }
633 FakeOop obj_at(int i) {
634 if (UseCompressedOops) {
635 return read_oop_at(raw_refArrayOop()->obj_at_addr<narrowOop>(i));
636 } else {
637 return read_oop_at(raw_refArrayOop()->obj_at_addr<oop>(i));
638 }
639 }
640 }; // AOTMapLogger::FakeRefArray
641
642 class AOTMapLogger::FakeFlatArray : public AOTMapLogger::FakeOop {
643 flatArrayOop raw_flatArrayOop() {
644 return (flatArrayOop)raw_oop();
645 }
646
647 public:
648 FakeFlatArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
649
650 int length() {
651 return raw_flatArrayOop()->length();
652 }
653 void print_elements_on(outputStream* st) {
654 FlatArrayKlass::cast(real_klass())->oop_print_elements_on(raw_flatArrayOop(), st);
655 }
656
657 }; // AOTMapLogger::FakeRefArray
658
659 class AOTMapLogger::FakeString : public AOTMapLogger::FakeOop {
660 public:
661 FakeString(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
662
663 bool is_latin1() {
664 jbyte coder = raw_oop()->byte_field(java_lang_String::coder_offset());
665 assert(CompactStrings || coder == java_lang_String::CODER_UTF16, "Must be UTF16 without CompactStrings");
666 return coder == java_lang_String::CODER_LATIN1;
667 }
668
669 FakeTypeArray value();
670
671 int length();
672 void print_on(outputStream* st, int max_length = MaxStringPrintSize);
673 }; // AOTMapLogger::FakeString
674
675 class AOTMapLogger::FakeTypeArray : public AOTMapLogger::FakeOop {
676 typeArrayOop raw_typeArrayOop() {
677 return (typeArrayOop)raw_oop();
678 }
679
680 public:
681 FakeTypeArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
682
683 void print_elements_on(outputStream* st) {
684 TypeArrayKlass::cast(real_klass())->oop_print_elements_on(raw_typeArrayOop(), st);
685 }
686
687 int length() { return raw_typeArrayOop()->length(); }
688 jbyte byte_at(int i) { return raw_typeArrayOop()->byte_at(i); }
689 jchar char_at(int i) { return raw_typeArrayOop()->char_at(i); }
690 }; // AOTMapLogger::FakeTypeArray
691
692 AOTMapLogger::FakeMirror AOTMapLogger::FakeOop::as_mirror() {
693 precond(real_klass() == vmClasses::Class_klass());
694 return FakeMirror(_iter, _data);
695 }
696
697 AOTMapLogger::FakeRefArray AOTMapLogger::FakeOop::as_ref_array() {
698 precond(real_klass()->is_refArray_klass());
699 return FakeRefArray(_iter, _data);
700 }
701
702 AOTMapLogger::FakeFlatArray AOTMapLogger::FakeOop::as_flat_array() {
703 precond(real_klass()->is_flatArray_klass());
704 return FakeFlatArray(_iter, _data);
705 }
706
707 AOTMapLogger::FakeTypeArray AOTMapLogger::FakeOop::as_type_array() {
708 precond(real_klass()->is_typeArray_klass());
709 return FakeTypeArray(_iter, _data);
710 }
711
712 AOTMapLogger::FakeString AOTMapLogger::FakeOop::as_string() {
713 precond(real_klass() == vmClasses::String_klass());
714 return FakeString(_iter, _data);
715 }
716
717 void AOTMapLogger::FakeMirror::print_class_signature_on(outputStream* st) {
718 ResourceMark rm;
719 RequestedMetadataAddr requested_klass = metadata_field(java_lang_Class::klass_offset());
720 Klass* real_klass = requested_klass.to_real_klass();
721
722 if (real_klass == nullptr) {
723 // This is a primitive mirror (Java expressions of int.class, long.class, void.class, etc);
724 RequestedMetadataAddr requested_array_klass = metadata_field(java_lang_Class::array_klass_offset());
929 } else if (real_klass == vmClasses::Class_klass()) {
930 fake_oop.as_mirror().print_class_signature_on(st);
931 }
932
933 st->cr();
934 }
935 }
936 }
937
938 // Print the fields of instanceOops, or the elements of arrayOops
939 void AOTMapLogger::print_oop_details(FakeOop fake_oop, outputStream* st) {
940 Klass* real_klass = fake_oop.real_klass();
941
942 st->print(" - klass: ");
943 real_klass->print_value_on(st);
944 st->print(" " PTR_FORMAT, p2i(fake_oop.klass().raw_addr()));
945 st->cr();
946
947 if (real_klass->is_typeArray_klass()) {
948 fake_oop.as_type_array().print_elements_on(st);
949 } else if (real_klass->is_flatArray_klass()) {
950 // Archiving FlatArrayOop with embedded oops is not supported.
951 // TODO: add restriction.
952 fake_oop.as_flat_array().print_elements_on(st);
953 } else if (real_klass->is_refArray_klass()) {
954 FakeRefArray fake_obj_array = fake_oop.as_ref_array();
955 bool is_logging_root_segment = fake_oop.is_root_segment();
956
957 for (int i = 0; i < fake_obj_array.length(); i++) {
958 FakeOop elm = fake_obj_array.obj_at(i);
959 if (is_logging_root_segment) {
960 st->print(" root[%4d]: ", _roots->length());
961 _roots->append(elm);
962 } else {
963 st->print(" -%4d: ", i);
964 }
965 print_oop_info_cr(st, elm);
966 }
967 } else {
968 st->print_cr(" - fields (%zu words):", fake_oop.size());
969
970 ArchivedFieldPrinter print_field(fake_oop, st);
971 InstanceKlass::cast(real_klass)->print_nonstatic_fields(&print_field);
972
973 if (real_klass == vmClasses::Class_klass()) {
974 FakeMirror fake_mirror = fake_oop.as_mirror();
|