From b6518a5db08959a5d1a22ccff9c1795ce7f9bf85 Mon Sep 17 00:00:00 2001 From: Matias Saavedra Silva Date: Tue, 23 Apr 2024 15:07:55 +0000 Subject: [PATCH] 8329417: Remove objects with no pointers from relocation bitmap Reviewed-by: ccheung, iklam --- src/hotspot/share/cds/archiveBuilder.cpp | 22 ++++++++++++++++++++++ src/hotspot/share/cds/archiveBuilder.hpp | 13 +++++++++++-- src/hotspot/share/cds/filemap.cpp | 17 +++++++++++------ src/hotspot/share/cds/filemap.hpp | 12 +++++++++--- src/hotspot/share/cds/metaspaceShared.cpp | 1 + 5 files changed, 54 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index 0eee36eec21..51399f03434 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -77,6 +77,7 @@ ArchiveBuilder::SourceObjList::~SourceObjList() { void ArchiveBuilder::SourceObjList::append(SourceObjInfo* src_info) { // Save this source object for copying + src_info->set_id(_objs->length()); _objs->append(src_info); // Prepare for marking the pointers in this source object @@ -94,6 +95,7 @@ void ArchiveBuilder::SourceObjList::append(SourceObjInfo* src_info) { void ArchiveBuilder::SourceObjList::remember_embedded_pointer(SourceObjInfo* src_info, MetaspaceClosure::Ref* ref) { // src_obj contains a pointer. Remember the location of this pointer in _ptrmap, // so that we can copy/relocate it later. + src_info->set_has_embedded_pointer(); address src_obj = src_info->source_addr(); address* field_addr = ref->addr(); assert(src_info->ptrmap_start() < _total_bytes, "sanity"); @@ -589,6 +591,26 @@ char* ArchiveBuilder::ro_strdup(const char* s) { return archived_str; } +// The objects that have embedded pointers will sink +// towards the end of the list. This ensures we have a maximum +// number of leading zero bits in the relocation bitmap. +int ArchiveBuilder::compare_src_objs(SourceObjInfo** a, SourceObjInfo** b) { + if ((*a)->has_embedded_pointer() && !(*b)->has_embedded_pointer()) { + return 1; + } else if (!(*a)->has_embedded_pointer() && (*b)->has_embedded_pointer()) { + return -1; + } else { + // This is necessary to keep the sorting order stable. Otherwise the + // archive's contents may not be deterministic. + return (*a)->id() - (*b)->id(); + } +} + +void ArchiveBuilder::sort_metadata_objs() { + _rw_src_objs.objs()->sort(compare_src_objs); + _ro_src_objs.objs()->sort(compare_src_objs); +} + void ArchiveBuilder::dump_rw_metadata() { ResourceMark rm; log_info(cds)("Allocating RW objects ... "); diff --git a/src/hotspot/share/cds/archiveBuilder.hpp b/src/hotspot/share/cds/archiveBuilder.hpp index e6ac2e7ac4e..dab369265b0 100644 --- a/src/hotspot/share/cds/archiveBuilder.hpp +++ b/src/hotspot/share/cds/archiveBuilder.hpp @@ -126,15 +126,18 @@ private: uintx _ptrmap_start; // The bit-offset of the start of this object (inclusive) uintx _ptrmap_end; // The bit-offset of the end of this object (exclusive) bool _read_only; + bool _has_embedded_pointer; FollowMode _follow_mode; int _size_in_bytes; + int _id; // Each object has a unique serial ID, starting from zero. The ID is assigned + // when the object is added into _source_objs. MetaspaceObj::Type _msotype; address _source_addr; // The source object to be copied. address _buffered_addr; // The copy of this object insider the buffer. public: SourceObjInfo(MetaspaceClosure::Ref* ref, bool read_only, FollowMode follow_mode) : - _ptrmap_start(0), _ptrmap_end(0), _read_only(read_only), _follow_mode(follow_mode), - _size_in_bytes(ref->size() * BytesPerWord), _msotype(ref->msotype()), + _ptrmap_start(0), _ptrmap_end(0), _read_only(read_only), _has_embedded_pointer(false), _follow_mode(follow_mode), + _size_in_bytes(ref->size() * BytesPerWord), _id(0), _msotype(ref->msotype()), _source_addr(ref->obj()) { if (follow_mode == point_to_it) { _buffered_addr = ref->obj(); @@ -164,7 +167,11 @@ private: uintx ptrmap_start() const { return _ptrmap_start; } // inclusive uintx ptrmap_end() const { return _ptrmap_end; } // exclusive bool read_only() const { return _read_only; } + bool has_embedded_pointer() const { return _has_embedded_pointer; } + void set_has_embedded_pointer() { _has_embedded_pointer = true; } int size_in_bytes() const { return _size_in_bytes; } + int id() const { return _id; } + void set_id(int i) { _id = i; } address source_addr() const { return _source_addr; } address buffered_addr() const { if (_follow_mode != set_to_null) { @@ -384,6 +391,8 @@ public: char* ro_strdup(const char* s); + static int compare_src_objs(SourceObjInfo** a, SourceObjInfo** b); + void sort_metadata_objs(); void dump_rw_metadata(); void dump_ro_metadata(); void relocate_metaspaceobj_embedded_pointers(); diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 707a1de6fd1..2182865ebaa 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -293,6 +293,8 @@ void FileMapHeader::print(outputStream* st) { st->print_cr("- heap_roots_offset: " SIZE_FORMAT, _heap_roots_offset); st->print_cr("- _heap_oopmap_start_pos: " SIZE_FORMAT, _heap_oopmap_start_pos); st->print_cr("- _heap_ptrmap_start_pos: " SIZE_FORMAT, _heap_ptrmap_start_pos); + st->print_cr("- _rw_ptrmap_start_pos: " SIZE_FORMAT, _rw_ptrmap_start_pos); + st->print_cr("- _ro_ptrmap_start_pos: " SIZE_FORMAT, _ro_ptrmap_start_pos); st->print_cr("- allow_archiving_with_java_agent:%d", _allow_archiving_with_java_agent); st->print_cr("- use_optimized_module_handling: %d", _use_optimized_module_handling); st->print_cr("- has_full_module_graph %d", _has_full_module_graph); @@ -1580,7 +1582,7 @@ static size_t write_bitmap(const CHeapBitMap* map, char* output, size_t offset) // lots of leading zeros. size_t FileMapInfo::remove_bitmap_leading_zeros(CHeapBitMap* map) { size_t old_zeros = map->find_first_set_bit(0); - size_t old_size = map->size_in_bytes(); + size_t old_size = map->size(); // Slice and resize bitmap map->truncate(old_zeros, map->size()); @@ -1589,13 +1591,16 @@ size_t FileMapInfo::remove_bitmap_leading_zeros(CHeapBitMap* map) { size_t new_zeros = map->find_first_set_bit(0); assert(new_zeros == 0, "Should have removed leading zeros"); ) - - assert(map->size_in_bytes() < old_size, "Map size should have decreased"); + assert(map->size() <= old_size, "sanity"); return old_zeros; } -char* FileMapInfo::write_bitmap_region(const CHeapBitMap* rw_ptrmap, const CHeapBitMap* ro_ptrmap, ArchiveHeapInfo* heap_info, +char* FileMapInfo::write_bitmap_region(CHeapBitMap* rw_ptrmap, CHeapBitMap* ro_ptrmap, ArchiveHeapInfo* heap_info, size_t &size_in_bytes) { + size_t removed_rw_zeros = remove_bitmap_leading_zeros(rw_ptrmap); + size_t removed_ro_zeros = remove_bitmap_leading_zeros(ro_ptrmap); + header()->set_rw_ptrmap_start_pos(removed_rw_zeros); + header()->set_ro_ptrmap_start_pos(removed_ro_zeros); size_in_bytes = rw_ptrmap->size_in_bytes() + ro_ptrmap->size_in_bytes(); if (heap_info->is_used()) { @@ -1942,9 +1947,9 @@ bool FileMapInfo::relocate_pointers_in_core_regions(intx addr_delta) { address valid_new_base = (address)header()->mapped_base_address(); address valid_new_end = (address)mapped_end(); - SharedDataRelocator rw_patcher((address*)rw_patch_base, (address*)rw_patch_end, valid_old_base, valid_old_end, + SharedDataRelocator rw_patcher((address*)rw_patch_base + header()->rw_ptrmap_start_pos(), (address*)rw_patch_end, valid_old_base, valid_old_end, valid_new_base, valid_new_end, addr_delta); - SharedDataRelocator ro_patcher((address*)ro_patch_base, (address*)ro_patch_end, valid_old_base, valid_old_end, + SharedDataRelocator ro_patcher((address*)ro_patch_base + header()->ro_ptrmap_start_pos(), (address*)ro_patch_end, valid_old_base, valid_old_end, valid_new_base, valid_new_end, addr_delta); rw_ptrmap.iterate(&rw_patcher); ro_ptrmap.iterate(&ro_patcher); diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index a7f1c23d00a..54881b8d237 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -229,6 +229,8 @@ private: // of the archived heap objects, in bytes. size_t _heap_oopmap_start_pos; // The first bit in the oopmap corresponds to this position in the heap. size_t _heap_ptrmap_start_pos; // The first bit in the ptrmap corresponds to this position in the heap. + size_t _rw_ptrmap_start_pos; // The first bit in the ptrmap corresponds to this position in the rw region + size_t _ro_ptrmap_start_pos; // The first bit in the ptrmap corresponds to this position in the ro region char* from_mapped_offset(size_t offset) const { return mapped_base_address() + offset; } @@ -269,8 +271,10 @@ public: bool compressed_oops() const { return _compressed_oops; } bool compressed_class_pointers() const { return _compressed_class_ptrs; } size_t heap_roots_offset() const { return _heap_roots_offset; } - size_t heap_oopmap_start_pos() const { return _heap_oopmap_start_pos;} - size_t heap_ptrmap_start_pos() const { return _heap_ptrmap_start_pos;} + size_t heap_oopmap_start_pos() const { return _heap_oopmap_start_pos; } + size_t heap_ptrmap_start_pos() const { return _heap_ptrmap_start_pos; } + size_t rw_ptrmap_start_pos() const { return _rw_ptrmap_start_pos; } + size_t ro_ptrmap_start_pos() const { return _ro_ptrmap_start_pos; } // FIXME: These should really return int jshort max_used_path_index() const { return _max_used_path_index; } jshort app_module_paths_start_index() const { return _app_module_paths_start_index; } @@ -284,6 +288,8 @@ public: void set_heap_roots_offset(size_t n) { _heap_roots_offset = n; } void set_heap_oopmap_start_pos(size_t n) { _heap_oopmap_start_pos = n; } void set_heap_ptrmap_start_pos(size_t n) { _heap_ptrmap_start_pos = n; } + void set_rw_ptrmap_start_pos(size_t n) { _rw_ptrmap_start_pos = n; } + void set_ro_ptrmap_start_pos(size_t n) { _ro_ptrmap_start_pos = n; } void copy_base_archive_name(const char* name); void set_shared_path_table(SharedPathTable table) { @@ -440,7 +446,7 @@ public: void write_region(int region, char* base, size_t size, bool read_only, bool allow_exec); size_t remove_bitmap_leading_zeros(CHeapBitMap* map); - char* write_bitmap_region(const CHeapBitMap* rw_ptrmap, const CHeapBitMap* ro_ptrmap, ArchiveHeapInfo* heap_info, + char* write_bitmap_region(CHeapBitMap* rw_ptrmap, CHeapBitMap* ro_ptrmap, ArchiveHeapInfo* heap_info, size_t &size_in_bytes); size_t write_heap_region(ArchiveHeapInfo* heap_info); void write_bytes(const void* buffer, size_t count); diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index b13ef2101a9..c7d14f83d03 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -513,6 +513,7 @@ void VM_PopulateDumpSharedSpace::doit() { char* cloned_vtables = CppVtables::dumptime_init(&builder); + builder.sort_metadata_objs(); builder.dump_rw_metadata(); builder.dump_ro_metadata(); builder.relocate_metaspaceobj_embedded_pointers();