< prev index next >

src/hotspot/share/cds/aotMapLogger.cpp

Print this page

 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;

 613     return _data._target_location;
 614   }
 615 
 616   address requested_addr() {
 617     return _data._requested_addr;
 618   }
 619 
 620   uint32_t as_narrow_oop_value() {
 621     precond(UseCompressedOops);
 622     return _data._narrow_location;
 623   }
 624 
 625   FakeOop read_oop_at(narrowOop* addr) { // +UseCompressedOops
 626     return FakeOop(_iter, _iter->obj_at(addr));
 627   }
 628 
 629   FakeOop read_oop_at(oop* addr) { // -UseCompressedOops
 630     return FakeOop(_iter, _iter->obj_at(addr));
 631   }
 632 














 633   FakeOop obj_field(int field_offset) {
 634     if (UseCompressedOops) {
 635       return read_oop_at(raw_oop()->field_addr<narrowOop>(field_offset));
 636     } else {
 637       return read_oop_at(raw_oop()->field_addr<oop>(field_offset));
 638     }
 639   }
 640 
 641   void print_non_oop_field(outputStream* st, fieldDescriptor* fd) {
 642     // fd->print_on_for() works for non-oop fields in fake oops
 643     precond(fd->field_type() != T_ARRAY && fd->field_type() != T_OBJECT);
 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());

 795       abridge = false; // only do this once
 796     }
 797     jchar c = (!is_latin1) ?  v.char_at(index) :
 798                              ((jchar) v.byte_at(index)) & 0xff;
 799     if (c < ' ') {
 800       st->print("\\x%02X", c); // print control characters e.g. \x0A
 801     } else {
 802       st->print("%c", c);
 803     }
 804   }
 805   st->print("\"");
 806 
 807   if (length > max_length) {
 808     st->print(" (abridged) ");
 809   }
 810 }
 811 
 812 class AOTMapLogger::ArchivedFieldPrinter : public FieldClosure {
 813   FakeOop _fake_oop;
 814   outputStream* _st;


 815 public:
 816   ArchivedFieldPrinter(FakeOop fake_oop, outputStream* st) : _fake_oop(fake_oop), _st(st) {}

 817 
 818   void do_field(fieldDescriptor* fd) {

 819     _st->print(" - ");







 820     BasicType ft = fd->field_type();
 821     switch (ft) {
 822     case T_ARRAY:
 823     case T_OBJECT:
 824       {
 825         fd->print_on(_st); // print just the name and offset
 826         FakeOop field_value = _fake_oop.obj_field(fd->offset());
 827         print_oop_info_cr(_st, field_value);

































 828       }
 829       break;
 830     default:
 831       _fake_oop.print_non_oop_field(_st, fd); // name, offset, value
 832       _st->cr();
 833     }
 834   }
 835 }; // AOTMapLogger::ArchivedFieldPrinter
 836 
 837 void AOTMapLogger::dumptime_log_mapped_heap_region(AOTMappedHeapInfo* heap_info) {
 838   MemRegion r = heap_info->buffer_region();
 839   address buffer_start = address(r.start()); // start of the current oop inside the buffer
 840   address buffer_end = address(r.end());
 841 
 842   address requested_base = UseCompressedOops ? AOTMappedHeapWriter::narrow_oop_base() : (address)AOTMappedHeapWriter::NOCOOPS_REQUESTED_BASE;
 843   address requested_start = UseCompressedOops ? AOTMappedHeapWriter::buffered_addr_to_requested_addr(buffer_start) : requested_base;
 844 
 845   log_region_range("heap", buffer_start, buffer_end, requested_start);
 846   log_archived_objects(AOTMappedHeapWriter::oop_iterator(heap_info));
 847 }
 848 
 849 void AOTMapLogger::dumptime_log_streamed_heap_region(AOTStreamedHeapInfo* heap_info) {
 850   MemRegion r = heap_info->buffer_region();
 851   address buffer_start = address(r.start()); // start of the current oop inside the buffer

 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 public:
 556   RequestedMetadataAddr metadata_field(int field_offset) {
 557     return RequestedMetadataAddr(*(address*)(buffered_field_addr(field_offset)));
 558   }
 559 
 560   address buffered_addr() {
 561     return _data._buffered_addr;
 562   }
 563 
 564   address* buffered_field_addr(int field_offset) {
 565     return (address*)(buffered_addr() + field_offset);
 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;

 614     return _data._target_location;
 615   }
 616 
 617   address requested_addr() {
 618     return _data._requested_addr;
 619   }
 620 
 621   uint32_t as_narrow_oop_value() {
 622     precond(UseCompressedOops);
 623     return _data._narrow_location;
 624   }
 625 
 626   FakeOop read_oop_at(narrowOop* addr) { // +UseCompressedOops
 627     return FakeOop(_iter, _iter->obj_at(addr));
 628   }
 629 
 630   FakeOop read_oop_at(oop* addr) { // -UseCompressedOops
 631     return FakeOop(_iter, _iter->obj_at(addr));
 632   }
 633 
 634   FakeOop read_inline_oop_at(address value_addr, Klass* k) {
 635     OopData data = {
 636       value_addr,                                         // _buffered_addr, address of the flat value shifted by the payload offset
 637       requested_addr() + (value_addr - buffered_addr()),  // _requested_addr
 638       target_location() + (value_addr - buffered_addr()), // _target_location
 639       0,                                                  // _narrow_location, narrow oop not used
 640       cast_to_oop(value_addr),                            // _raw_oop
 641       k,                                                  // _klass
 642       0,                                                  // _size
 643       false                                               // _is_root_segment
 644     };
 645     return FakeOop(_iter, data);
 646   }
 647 
 648   FakeOop obj_field(int field_offset) {
 649     if (UseCompressedOops) {
 650       return read_oop_at(raw_oop()->field_addr<narrowOop>(field_offset));
 651     } else {
 652       return read_oop_at(raw_oop()->field_addr<oop>(field_offset));
 653     }
 654   }
 655 
 656   void print_non_oop_field(outputStream* st, fieldDescriptor* fd, int indent = 0, int base_offset = 0) {
 657     // fd->print_on_for() works for non-oop fields in fake oops
 658     precond(fd->field_type() != T_ARRAY && fd->field_type() != T_OBJECT);
 659     fd->print_on_for(st, raw_oop(), indent, base_offset);
 660   }
 661 }; // AOTMapLogger::FakeOop
 662 
 663 class AOTMapLogger::FakeMirror : public AOTMapLogger::FakeOop {
 664 public:
 665   FakeMirror(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
 666 
 667   void print_class_signature_on(outputStream* st);
 668 
 669   Klass* real_mirrored_klass() {
 670     RequestedMetadataAddr mirrored_klass = metadata_field(java_lang_Class::klass_offset());
 671     return mirrored_klass.to_real_klass();
 672   }
 673 
 674   int static_oop_field_count() {
 675     return java_lang_Class::static_oop_field_count(raw_oop());
 676   }
 677 }; // AOTMapLogger::FakeMirror
 678 
 679 class AOTMapLogger::FakeRefArray : public AOTMapLogger::FakeOop {
 680   refArrayOop raw_refArrayOop() {
 681     return (refArrayOop)raw_oop();
 682   }
 683 
 684 public:
 685   FakeRefArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
 686 
 687   int length() {
 688     return raw_refArrayOop()->length();
 689   }
 690   FakeOop obj_at(int i) {
 691     if (UseCompressedOops) {
 692       return read_oop_at(raw_refArrayOop()->obj_at_addr<narrowOop>(i));
 693     } else {
 694       return read_oop_at(raw_refArrayOop()->obj_at_addr<oop>(i));
 695     }
 696   }
 697 }; // AOTMapLogger::FakeRefArray
 698 
 699 class AOTMapLogger::FakeFlatArray : public AOTMapLogger::FakeOop {
 700   flatArrayOop raw_flatArrayOop() {
 701     return (flatArrayOop)raw_oop();
 702   }
 703 
 704 public:
 705   FakeFlatArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
 706 
 707   int length() {
 708     return raw_flatArrayOop()->length();
 709   }
 710 
 711   // Create a wrapper for an archived flat array element
 712   FakeOop element_at(int i) {
 713     InlineKlass* elem_k = ((FlatArrayKlass*)real_klass())->element_klass();
 714     address value_addr = (address)raw_flatArrayOop()->value_at_addr(i, real_klass()->layout_helper()) - elem_k->payload_offset();
 715     return read_inline_oop_at(value_addr, elem_k);
 716   }
 717 
 718   int element_offset_at(int i) {
 719     return (address)raw_flatArrayOop()->value_at_addr(i, real_klass()->layout_helper()) - cast_from_oop<address>(raw_flatArrayOop());
 720   }
 721 }; // AOTMapLogger::FakeFlatArray
 722 
 723 class AOTMapLogger::FakeString : public AOTMapLogger::FakeOop {
 724 public:
 725   FakeString(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
 726 
 727   bool is_latin1() {
 728     jbyte coder = raw_oop()->byte_field(java_lang_String::coder_offset());
 729     assert(CompactStrings || coder == java_lang_String::CODER_UTF16, "Must be UTF16 without CompactStrings");
 730     return coder == java_lang_String::CODER_LATIN1;
 731   }
 732 
 733   FakeTypeArray value();
 734 
 735   int length();
 736   void print_on(outputStream* st, int max_length = MaxStringPrintSize);
 737 }; // AOTMapLogger::FakeString
 738 
 739 class AOTMapLogger::FakeTypeArray : public AOTMapLogger::FakeOop {
 740   typeArrayOop raw_typeArrayOop() {
 741     return (typeArrayOop)raw_oop();
 742   }
 743 
 744 public:
 745   FakeTypeArray(OopDataIterator* iter, OopData data) : FakeOop(iter, data) {}
 746 
 747   void print_elements_on(outputStream* st) {
 748     TypeArrayKlass::cast(real_klass())->oop_print_elements_on(raw_typeArrayOop(), st);
 749   }
 750 
 751   int length() { return raw_typeArrayOop()->length(); }
 752   jbyte byte_at(int i) { return raw_typeArrayOop()->byte_at(i); }
 753   jchar char_at(int i) { return raw_typeArrayOop()->char_at(i); }
 754 }; // AOTMapLogger::FakeTypeArray
 755 
 756 AOTMapLogger::FakeMirror AOTMapLogger::FakeOop::as_mirror() {
 757   precond(real_klass() == vmClasses::Class_klass());
 758   return FakeMirror(_iter, _data);
 759 }
 760 
 761 AOTMapLogger::FakeRefArray AOTMapLogger::FakeOop::as_ref_array() {
 762   precond(real_klass()->is_refArray_klass());
 763   return FakeRefArray(_iter, _data);
 764 }
 765 
 766 AOTMapLogger::FakeFlatArray AOTMapLogger::FakeOop::as_flat_array() {
 767   precond(real_klass()->is_flatArray_klass());
 768   return FakeFlatArray(_iter, _data);
 769 }
 770 
 771 AOTMapLogger::FakeTypeArray AOTMapLogger::FakeOop::as_type_array() {
 772   precond(real_klass()->is_typeArray_klass());
 773   return FakeTypeArray(_iter, _data);
 774 }
 775 
 776 AOTMapLogger::FakeString AOTMapLogger::FakeOop::as_string() {
 777   precond(real_klass() == vmClasses::String_klass());
 778   return FakeString(_iter, _data);
 779 }
 780 
 781 void AOTMapLogger::FakeMirror::print_class_signature_on(outputStream* st) {
 782   ResourceMark rm;
 783   RequestedMetadataAddr requested_klass = metadata_field(java_lang_Class::klass_offset());
 784   Klass* real_klass = requested_klass.to_real_klass();
 785 
 786   if (real_klass == nullptr) {
 787     // This is a primitive mirror (Java expressions of int.class, long.class, void.class, etc);
 788     RequestedMetadataAddr requested_array_klass = metadata_field(java_lang_Class::array_klass_offset());

 839       abridge = false; // only do this once
 840     }
 841     jchar c = (!is_latin1) ?  v.char_at(index) :
 842                              ((jchar) v.byte_at(index)) & 0xff;
 843     if (c < ' ') {
 844       st->print("\\x%02X", c); // print control characters e.g. \x0A
 845     } else {
 846       st->print("%c", c);
 847     }
 848   }
 849   st->print("\"");
 850 
 851   if (length > max_length) {
 852     st->print(" (abridged) ");
 853   }
 854 }
 855 
 856 class AOTMapLogger::ArchivedFieldPrinter : public FieldClosure {
 857   FakeOop _fake_oop;
 858   outputStream* _st;
 859   int _indent;
 860   int _base_offset;
 861 public:
 862   ArchivedFieldPrinter(FakeOop fake_oop, outputStream* st, int indent = 1, int base_offset = 0) :
 863                        _fake_oop(fake_oop), _st(st), _indent(indent), _base_offset(base_offset) {}
 864 
 865   void do_field(fieldDescriptor* fd) {
 866     for (int i = 0; i < _indent; i++) _st->print("  ");
 867     _st->print(" - ");
 868 
 869     if (_fake_oop.raw_oop() == nullptr) {
 870       fd->print_on(_st, _base_offset);
 871       _st->cr();
 872       return;
 873     }
 874 
 875     BasicType ft = fd->field_type();
 876     switch (ft) {
 877     case T_ARRAY:
 878     case T_OBJECT:
 879       {
 880         if (fd->is_flat()) {
 881           int index = fd->index();
 882           InlineKlass* vk = fd->field_holder()->get_inline_type_field_klass(index);
 883           int field_offset = fd->offset() - vk->payload_offset();
 884           address field_addr = (address)_fake_oop.buffered_field_addr(field_offset);
 885           bool is_null = false;
 886 
 887           if (!fd->is_null_free_inline_type()) {
 888             assert(fd->has_null_marker(), "should have null marker");
 889             is_null = vk->is_payload_marked_as_null(_fake_oop.buffered_addr() + fd->offset());
 890             _st->print("Flat inline type field '%s':", vk->name()->as_C_string());
 891           } else {
 892             _st->print("Flat inline null-free type field '%s':", vk->name()->as_C_string());
 893           }
 894           // Print fields of flat field (recursively)
 895           if (!is_null) {
 896             _st->cr();
 897             FakeOop obj = _fake_oop.read_inline_oop_at(field_addr, vk);
 898             ArchivedFieldPrinter print_field(obj, _st, _indent + 1, _base_offset + field_offset);
 899             vk->do_nonstatic_fields(&print_field);
 900           } else {
 901             _st->print_cr(" null");
 902           }
 903 
 904           if (fd->field_flags().has_null_marker()) {
 905             for (int i = 0; i < _indent + 1; i++) _st->print("  ");
 906             _st->print_cr(" - [null_marker] @%d %s",
 907                       vk->null_marker_offset() + _base_offset + field_offset,
 908                       is_null ? "Field marked as null" : "Field marked as non-null");
 909           }
 910           return; // Do not print underlying representation
 911         } else {
 912           fd->print_on(_st); // print just the name and offset
 913           FakeOop field_value = _fake_oop.obj_field(fd->offset());
 914           print_oop_info_cr(_st, field_value);
 915         }
 916       }
 917       break;
 918     default:
 919       _fake_oop.print_non_oop_field(_st, fd, _indent, _base_offset); // name, offset, value
 920       _st->cr();
 921     }
 922   }
 923 }; // AOTMapLogger::ArchivedFieldPrinter
 924 
 925 void AOTMapLogger::dumptime_log_mapped_heap_region(AOTMappedHeapInfo* heap_info) {
 926   MemRegion r = heap_info->buffer_region();
 927   address buffer_start = address(r.start()); // start of the current oop inside the buffer
 928   address buffer_end = address(r.end());
 929 
 930   address requested_base = UseCompressedOops ? AOTMappedHeapWriter::narrow_oop_base() : (address)AOTMappedHeapWriter::NOCOOPS_REQUESTED_BASE;
 931   address requested_start = UseCompressedOops ? AOTMappedHeapWriter::buffered_addr_to_requested_addr(buffer_start) : requested_base;
 932 
 933   log_region_range("heap", buffer_start, buffer_end, requested_start);
 934   log_archived_objects(AOTMappedHeapWriter::oop_iterator(heap_info));
 935 }
 936 
 937 void AOTMapLogger::dumptime_log_streamed_heap_region(AOTStreamedHeapInfo* heap_info) {
 938   MemRegion r = heap_info->buffer_region();
 939   address buffer_start = address(r.start()); // start of the current oop inside the buffer

1037       } else if (real_klass == vmClasses::Class_klass()) {
1038         fake_oop.as_mirror().print_class_signature_on(st);
1039       }
1040 
1041       st->cr();
1042     }
1043   }
1044 }
1045 
1046 // Print the fields of instanceOops, or the elements of arrayOops
1047 void AOTMapLogger::print_oop_details(FakeOop fake_oop, outputStream* st) {
1048   Klass* real_klass = fake_oop.real_klass();
1049 
1050   st->print(" - klass: ");
1051   real_klass->print_value_on(st);
1052   st->print(" " PTR_FORMAT, p2i(fake_oop.klass().raw_addr()));
1053   st->cr();
1054 
1055   if (real_klass->is_typeArray_klass()) {
1056     fake_oop.as_type_array().print_elements_on(st);
1057   } else if (real_klass->is_flatArray_klass()) {
1058     FakeFlatArray fake_flat_array = fake_oop.as_flat_array();
1059     InlineKlass* elem_k = ((FlatArrayKlass*)real_klass)->element_klass();
1060     for (int i = 0; i < fake_flat_array.length(); i++) {
1061       bool is_null = false;
1062       int off = fake_flat_array.element_offset_at(i);
1063       FakeOop elm = fake_flat_array.element_at(i);
1064 
1065       if (!real_klass->is_null_free_array_klass()) {
1066         is_null = elem_k->is_payload_marked_as_null(elm.buffered_addr() + elem_k->payload_offset());
1067         st->print(" - Flat inline type element '%s':", elem_k->name()->as_C_string());
1068       } else {
1069         st->print(" - Flat inline null-free type element '%s':", elem_k->name()->as_C_string());
1070       }
1071       st->print(" - Index %3d offset %3d: ", i, off);
1072 
1073       if (!is_null) {
1074         st->cr();
1075         ArchivedFieldPrinter print_field(elm, st);
1076         elem_k->do_nonstatic_fields(&print_field);
1077       } else {
1078         assert(!real_klass->is_null_free_array_klass(), "must be");
1079         st->print_cr(" null");
1080       }
1081 
1082       if (!real_klass->is_null_free_array_klass()) {
1083         st->print_cr("   - [null_marker] @%d %s",
1084                      off + elem_k->null_marker_offset_in_payload(),
1085                      is_null ? "Field marked as null" : "Field marked as non-null");
1086       }
1087     }
1088   } else if (real_klass->is_refArray_klass()) {
1089     FakeRefArray fake_obj_array = fake_oop.as_ref_array();
1090     bool is_logging_root_segment = fake_oop.is_root_segment();
1091 
1092     for (int i = 0; i < fake_obj_array.length(); i++) {
1093       FakeOop elm = fake_obj_array.obj_at(i);
1094       if (is_logging_root_segment) {
1095         st->print(" root[%4d]: ", _roots->length());
1096         _roots->append(elm);
1097       } else {
1098         st->print(" -%4d: ", i);
1099       }
1100       print_oop_info_cr(st, elm);
1101     }
1102   } else {
1103     st->print_cr(" - fields (%zu words):", fake_oop.size());
1104 
1105     ArchivedFieldPrinter print_field(fake_oop, st);
1106     InstanceKlass::cast(real_klass)->print_nonstatic_fields(&print_field);
1107 
1108     if (real_klass == vmClasses::Class_klass()) {
1109       FakeMirror fake_mirror = fake_oop.as_mirror();
< prev index next >