8377096: Refactor AOTMapLogger::OopDataIterator implementations

Reviewed-by: eosterlund, kvn
This commit is contained in:
Ioi Lam 2026-02-10 17:07:56 +00:00
parent 21d4c6c68f
commit 7bc2475962
21 changed files with 539 additions and 494 deletions

View File

@ -88,7 +88,7 @@ void AOTMapLogger::ergo_initialize() {
}
void AOTMapLogger::dumptime_log(ArchiveBuilder* builder, FileMapInfo* mapinfo,
ArchiveMappedHeapInfo* mapped_heap_info, ArchiveStreamedHeapInfo* streamed_heap_info,
AOTMappedHeapInfo* mapped_heap_info, AOTStreamedHeapInfo* streamed_heap_info,
char* bitmap, size_t bitmap_size_in_bytes) {
_is_runtime_logging = false;
_buffer_to_requested_delta = ArchiveBuilder::current()->buffer_to_requested_delta();
@ -823,7 +823,7 @@ public:
}
}; // AOTMapLogger::ArchivedFieldPrinter
void AOTMapLogger::dumptime_log_mapped_heap_region(ArchiveMappedHeapInfo* heap_info) {
void AOTMapLogger::dumptime_log_mapped_heap_region(AOTMappedHeapInfo* heap_info) {
MemRegion r = heap_info->buffer_region();
address buffer_start = address(r.start()); // start of the current oop inside the buffer
address buffer_end = address(r.end());
@ -835,7 +835,7 @@ void AOTMapLogger::dumptime_log_mapped_heap_region(ArchiveMappedHeapInfo* heap_i
log_archived_objects(AOTMappedHeapWriter::oop_iterator(heap_info));
}
void AOTMapLogger::dumptime_log_streamed_heap_region(ArchiveStreamedHeapInfo* heap_info) {
void AOTMapLogger::dumptime_log_streamed_heap_region(AOTStreamedHeapInfo* heap_info) {
MemRegion r = heap_info->buffer_region();
address buffer_start = address(r.start()); // start of the current oop inside the buffer
address buffer_end = address(r.end());

View File

@ -33,8 +33,8 @@
#include "utilities/globalDefinitions.hpp"
#include "utilities/growableArray.hpp"
class ArchiveMappedHeapInfo;
class ArchiveStreamedHeapInfo;
class AOTMappedHeapInfo;
class AOTStreamedHeapInfo;
class CompileTrainingData;
class DumpRegion;
class FileMapInfo;
@ -157,8 +157,8 @@ private:
#if INCLUDE_CDS_JAVA_HEAP
static void dumptime_log_mapped_heap_region(ArchiveMappedHeapInfo* mapped_heap_info);
static void dumptime_log_streamed_heap_region(ArchiveStreamedHeapInfo* streamed_heap_info);
static void dumptime_log_mapped_heap_region(AOTMappedHeapInfo* mapped_heap_info);
static void dumptime_log_streamed_heap_region(AOTStreamedHeapInfo* streamed_heap_info);
static void runtime_log_heap_region(FileMapInfo* mapinfo);
static void print_oop_info_cr(outputStream* st, FakeOop fake_oop, bool print_location = true);
@ -173,7 +173,7 @@ public:
static bool is_logging_at_bootstrap() { return _is_logging_at_bootstrap; }
static void dumptime_log(ArchiveBuilder* builder, FileMapInfo* mapinfo,
ArchiveMappedHeapInfo* mapped_heap_info, ArchiveStreamedHeapInfo* streamed_heap_info,
AOTMappedHeapInfo* mapped_heap_info, AOTStreamedHeapInfo* streamed_heap_info,
char* bitmap, size_t bitmap_size_in_bytes);
static void runtime_log(FileMapInfo* static_mapinfo, FileMapInfo* dynamic_mapinfo);
};

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "cds/aotMappedHeap.hpp"
// Anything that goes in the header must be thoroughly purged from uninitialized memory
// as it will be written to disk. Therefore, the constructors memset the memory to 0.
// This is not the prettiest thing, but we need to know every byte is initialized,
// including potential padding between fields.
AOTMappedHeapHeader::AOTMappedHeapHeader(size_t ptrmap_start_pos,
size_t oopmap_start_pos,
HeapRootSegments root_segments) {
memset((char*)this, 0, sizeof(*this));
_ptrmap_start_pos = ptrmap_start_pos;
_oopmap_start_pos = oopmap_start_pos;
_root_segments = root_segments;
}
AOTMappedHeapHeader::AOTMappedHeapHeader() {
memset((char*)this, 0, sizeof(*this));
}
AOTMappedHeapHeader AOTMappedHeapInfo::create_header() {
return AOTMappedHeapHeader{_ptrmap_start_pos,
_oopmap_start_pos,
_root_segments};
}

View File

@ -0,0 +1,168 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_CDS_AOTMAPPEDHEAP_HPP
#define SHARE_CDS_AOTMAPPEDHEAP_HPP
#include "cds/aotMapLogger.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
class AOTMappedHeapHeader {
size_t _ptrmap_start_pos; // The first bit in the ptrmap corresponds to this position in the heap.
size_t _oopmap_start_pos; // The first bit in the oopmap corresponds to this position in the heap.
HeapRootSegments _root_segments; // Heap root segments info
public:
AOTMappedHeapHeader();
AOTMappedHeapHeader(size_t ptrmap_start_pos,
size_t oopmap_start_pos,
HeapRootSegments root_segments);
size_t ptrmap_start_pos() const { return _ptrmap_start_pos; }
size_t oopmap_start_pos() const { return _oopmap_start_pos; }
HeapRootSegments root_segments() const { return _root_segments; }
// This class is trivially copyable and assignable.
AOTMappedHeapHeader(const AOTMappedHeapHeader&) = default;
AOTMappedHeapHeader& operator=(const AOTMappedHeapHeader&) = default;
};
class AOTMappedHeapInfo {
MemRegion _buffer_region; // Contains the archived objects to be written into the CDS archive.
CHeapBitMap _oopmap;
CHeapBitMap _ptrmap;
HeapRootSegments _root_segments;
size_t _oopmap_start_pos; // How many zeros were removed from the beginning of the bit map?
size_t _ptrmap_start_pos; // How many zeros were removed from the beginning of the bit map?
public:
AOTMappedHeapInfo() :
_buffer_region(),
_oopmap(128, mtClassShared),
_ptrmap(128, mtClassShared),
_root_segments(),
_oopmap_start_pos(),
_ptrmap_start_pos() {}
bool is_used() { return !_buffer_region.is_empty(); }
MemRegion buffer_region() { return _buffer_region; }
void set_buffer_region(MemRegion r) { _buffer_region = r; }
char* buffer_start() { return (char*)_buffer_region.start(); }
size_t buffer_byte_size() { return _buffer_region.byte_size(); }
CHeapBitMap* oopmap() { return &_oopmap; }
CHeapBitMap* ptrmap() { return &_ptrmap; }
void set_oopmap_start_pos(size_t start_pos) { _oopmap_start_pos = start_pos; }
void set_ptrmap_start_pos(size_t start_pos) { _ptrmap_start_pos = start_pos; }
void set_root_segments(HeapRootSegments segments) { _root_segments = segments; };
HeapRootSegments root_segments() { return _root_segments; }
AOTMappedHeapHeader create_header();
};
#if INCLUDE_CDS_JAVA_HEAP
class AOTMappedHeapOopIterator : public AOTMapLogger::OopDataIterator {
protected:
address _current;
address _next;
address _buffer_start;
address _buffer_end;
uint64_t _buffer_start_narrow_oop;
intptr_t _buffer_to_requested_delta;
int _requested_shift;
size_t _num_root_segments;
size_t _num_obj_arrays_logged;
public:
AOTMappedHeapOopIterator(address buffer_start,
address buffer_end,
address requested_base,
address requested_start,
int requested_shift,
size_t num_root_segments)
: _current(nullptr),
_next(buffer_start),
_buffer_start(buffer_start),
_buffer_end(buffer_end),
_requested_shift(requested_shift),
_num_root_segments(num_root_segments),
_num_obj_arrays_logged(0) {
_buffer_to_requested_delta = requested_start - buffer_start;
_buffer_start_narrow_oop = 0xdeadbeed;
if (UseCompressedOops) {
_buffer_start_narrow_oop = (uint64_t)(pointer_delta(requested_start, requested_base, 1)) >> requested_shift;
assert(_buffer_start_narrow_oop < 0xffffffff, "sanity");
}
}
virtual AOTMapLogger::OopData capture(address buffered_addr) = 0;
bool has_next() override {
return _next < _buffer_end;
}
AOTMapLogger::OopData next() override {
_current = _next;
AOTMapLogger::OopData result = capture(_current);
if (result._klass->is_objArray_klass()) {
result._is_root_segment = _num_obj_arrays_logged++ < _num_root_segments;
}
_next = _current + result._size * BytesPerWord;
return result;
}
AOTMapLogger::OopData obj_at(narrowOop* addr) override {
uint64_t n = (uint64_t)(*addr);
if (n == 0) {
return null_data();
} else {
precond(n >= _buffer_start_narrow_oop);
address buffer_addr = _buffer_start + ((n - _buffer_start_narrow_oop) << _requested_shift);
return capture(buffer_addr);
}
}
AOTMapLogger::OopData obj_at(oop* addr) override {
address requested_value = cast_from_oop<address>(*addr);
if (requested_value == nullptr) {
return null_data();
} else {
address buffer_addr = requested_value - _buffer_to_requested_delta;
return capture(buffer_addr);
}
}
GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>* roots() override {
return new GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>();
}
};
#endif // INCLUDE_CDS_JAVA_HEAP
#endif // SHARE_CDS_AOTMAPPEDHEAP_HPP

View File

@ -23,6 +23,7 @@
*/
#include "cds/aotLogging.hpp"
#include "cds/aotMappedHeap.hpp"
#include "cds/aotMappedHeapLoader.inline.hpp"
#include "cds/aotMappedHeapWriter.hpp"
#include "cds/aotMetaspace.hpp"
@ -221,7 +222,7 @@ void AOTMappedHeapLoader::patch_embedded_pointers(FileMapInfo* info,
// the heap object may be loaded at a different address at run time. This structure is used
// to translate the dump time addresses for all objects in FileMapInfo::space_at(region_index)
// to their runtime addresses.
struct LoadedArchiveHeapRegion {
struct AOTMappedHeapRegion {
int _region_index; // index for FileMapInfo::space_at(index)
size_t _region_size; // number of bytes in this region
uintptr_t _dumptime_base; // The dump-time (decoded) address of the first object in this region
@ -232,7 +233,7 @@ struct LoadedArchiveHeapRegion {
}
};
void AOTMappedHeapLoader::init_loaded_heap_relocation(LoadedArchiveHeapRegion* loaded_region) {
void AOTMappedHeapLoader::init_loaded_heap_relocation(AOTMappedHeapRegion* loaded_region) {
_dumptime_base = loaded_region->_dumptime_base;
_dumptime_top = loaded_region->top();
_runtime_offset = loaded_region->_runtime_offset;
@ -249,7 +250,7 @@ class AOTMappedHeapLoader::PatchLoadedRegionPointers: public BitMapClosure {
uintptr_t _top;
public:
PatchLoadedRegionPointers(narrowOop* start, LoadedArchiveHeapRegion* loaded_region)
PatchLoadedRegionPointers(narrowOop* start, AOTMappedHeapRegion* loaded_region)
: _start(start),
_offset(loaded_region->_runtime_offset),
_base(loaded_region->_dumptime_base),
@ -270,7 +271,7 @@ class AOTMappedHeapLoader::PatchLoadedRegionPointers: public BitMapClosure {
}
};
bool AOTMappedHeapLoader::init_loaded_region(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_region,
bool AOTMappedHeapLoader::init_loaded_region(FileMapInfo* mapinfo, AOTMappedHeapRegion* loaded_region,
MemRegion& archive_space) {
size_t total_bytes = 0;
FileMapRegion* r = mapinfo->region_at(AOTMetaspace::hp);
@ -301,7 +302,7 @@ bool AOTMappedHeapLoader::init_loaded_region(FileMapInfo* mapinfo, LoadedArchive
return true;
}
bool AOTMappedHeapLoader::load_heap_region_impl(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_region,
bool AOTMappedHeapLoader::load_heap_region_impl(FileMapInfo* mapinfo, AOTMappedHeapRegion* loaded_region,
uintptr_t load_address) {
uintptr_t bitmap_base = (uintptr_t)mapinfo->map_bitmap_region();
if (bitmap_base == 0) {
@ -340,7 +341,7 @@ bool AOTMappedHeapLoader::load_heap_region(FileMapInfo* mapinfo) {
assert(can_load(), "loaded heap for must be supported");
init_narrow_oop_decoding(mapinfo->narrow_oop_base(), mapinfo->narrow_oop_shift());
LoadedArchiveHeapRegion loaded_region;
AOTMappedHeapRegion loaded_region;
memset(&loaded_region, 0, sizeof(loaded_region));
MemRegion archive_space;
@ -733,40 +734,22 @@ void AOTMappedHeapLoader::dealloc_heap_region(FileMapInfo* info) {
}
AOTMapLogger::OopDataIterator* AOTMappedHeapLoader::oop_iterator(FileMapInfo* info, address buffer_start, address buffer_end) {
class MappedLoaderOopIterator : public AOTMapLogger::OopDataIterator {
private:
address _current;
address _next;
address _buffer_start;
address _buffer_end;
uint64_t _buffer_start_narrow_oop;
intptr_t _buffer_to_requested_delta;
int _requested_shift;
size_t _num_root_segments;
size_t _num_obj_arrays_logged;
class MappedLoaderOopIterator : public AOTMappedHeapOopIterator {
public:
MappedLoaderOopIterator(address buffer_start,
address buffer_end,
uint64_t buffer_start_narrow_oop,
intptr_t buffer_to_requested_delta,
address requested_base,
address requested_start,
int requested_shift,
size_t num_root_segments)
: _current(nullptr),
_next(buffer_start),
_buffer_start(buffer_start),
_buffer_end(buffer_end),
_buffer_start_narrow_oop(buffer_start_narrow_oop),
_buffer_to_requested_delta(buffer_to_requested_delta),
_requested_shift(requested_shift),
_num_root_segments(num_root_segments),
_num_obj_arrays_logged(0) {
}
size_t num_root_segments) :
AOTMappedHeapOopIterator(buffer_start,
buffer_end,
requested_base,
requested_start,
requested_shift,
num_root_segments) {}
AOTMapLogger::OopData capture(address buffered_addr) {
AOTMapLogger::OopData capture(address buffered_addr) override {
oopDesc* raw_oop = (oopDesc*)buffered_addr;
size_t size = raw_oop->size();
address requested_addr = buffered_addr + _buffer_to_requested_delta;
@ -784,62 +767,17 @@ AOTMapLogger::OopDataIterator* AOTMappedHeapLoader::oop_iterator(FileMapInfo* in
size,
false };
}
bool has_next() override {
return _next < _buffer_end;
}
AOTMapLogger::OopData next() override {
_current = _next;
AOTMapLogger::OopData result = capture(_current);
if (result._klass->is_objArray_klass()) {
result._is_root_segment = _num_obj_arrays_logged++ < _num_root_segments;
}
_next = _current + result._size * BytesPerWord;
return result;
}
AOTMapLogger::OopData obj_at(narrowOop* addr) override {
uint64_t n = (uint64_t)(*addr);
if (n == 0) {
return null_data();
} else {
precond(n >= _buffer_start_narrow_oop);
address buffer_addr = _buffer_start + ((n - _buffer_start_narrow_oop) << _requested_shift);
return capture(buffer_addr);
}
}
AOTMapLogger::OopData obj_at(oop* addr) override {
address requested_value = cast_from_oop<address>(*addr);
if (requested_value == nullptr) {
return null_data();
} else {
address buffer_addr = requested_value - _buffer_to_requested_delta;
return capture(buffer_addr);
}
}
GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>* roots() override {
return new GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>();
}
};
FileMapRegion* r = info->region_at(AOTMetaspace::hp);
address requested_base = UseCompressedOops ? (address)info->narrow_oop_base() : heap_region_requested_address(info);
address requested_start = requested_base + r->mapping_offset();
int requested_shift = info->narrow_oop_shift();
intptr_t buffer_to_requested_delta = requested_start - buffer_start;
uint64_t buffer_start_narrow_oop = 0xdeadbeed;
if (UseCompressedOops) {
buffer_start_narrow_oop = (uint64_t)(pointer_delta(requested_start, requested_base, 1)) >> requested_shift;
assert(buffer_start_narrow_oop < 0xffffffff, "sanity");
}
return new MappedLoaderOopIterator(buffer_start,
buffer_end,
buffer_start_narrow_oop,
buffer_to_requested_delta,
requested_base,
requested_start,
requested_shift,
info->mapped_heap()->root_segments().count());
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,8 +37,8 @@
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
struct AOTMappedHeapRegion;
class FileMapInfo;
struct LoadedArchiveHeapRegion;
class AOTMappedHeapLoader : AllStatic {
friend class AOTMapLogger;
@ -93,7 +93,7 @@ public:
// function instead.
inline static oop decode_from_archive(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(nullptr);
// More efficient version, but works only when ArchiveHeap is mapped.
// More efficient version, but works only when is_mapped()
inline static oop decode_from_mapped_archive(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(nullptr);
static void patch_compressed_embedded_pointers(BitMapView bm,
@ -113,7 +113,7 @@ private:
static bool _is_loaded;
// Support for loaded archived heap. These are cached values from
// LoadedArchiveHeapRegion's.
// AOTMappedHeapRegion's.
static uintptr_t _dumptime_base;
static uintptr_t _dumptime_top;
static intx _runtime_offset;
@ -141,10 +141,10 @@ private:
static bool _heap_pointers_need_patching;
static void init_narrow_oop_decoding(address base, int shift);
static bool init_loaded_region(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_region,
static bool init_loaded_region(FileMapInfo* mapinfo, AOTMappedHeapRegion* loaded_region,
MemRegion& archive_space);
static bool load_heap_region_impl(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_region, uintptr_t buffer);
static void init_loaded_heap_relocation(LoadedArchiveHeapRegion* reloc_info);
static bool load_heap_region_impl(FileMapInfo* mapinfo, AOTMappedHeapRegion* loaded_region, uintptr_t buffer);
static void init_loaded_heap_relocation(AOTMappedHeapRegion* reloc_info);
static void patch_native_pointers();
static void finish_loaded_heap();
static void verify_loaded_heap();

View File

@ -22,7 +22,7 @@
*
*/
#include "cds/aotMappedHeapLoader.hpp"
#include "cds/aotMappedHeap.hpp"
#include "cds/aotMappedHeapWriter.hpp"
#include "cds/aotReferenceObjSupport.hpp"
#include "cds/cdsConfig.hpp"
@ -151,7 +151,7 @@ void AOTMappedHeapWriter::add_source_obj(oop src_obj) {
}
void AOTMappedHeapWriter::write(GrowableArrayCHeap<oop, mtClassShared>* roots,
ArchiveMappedHeapInfo* heap_info) {
AOTMappedHeapInfo* heap_info) {
assert(CDSConfig::is_dumping_heap(), "sanity");
allocate_buffer();
copy_source_objs_to_buffer(roots);
@ -598,7 +598,7 @@ size_t AOTMappedHeapWriter::copy_one_source_obj_to_buffer(oop src_obj) {
//
// So we just hard code it to NOCOOPS_REQUESTED_BASE.
//
void AOTMappedHeapWriter::set_requested_address_range(ArchiveMappedHeapInfo* info) {
void AOTMappedHeapWriter::set_requested_address_range(AOTMappedHeapInfo* info) {
assert(!info->is_used(), "only set once");
size_t heap_region_byte_size = _buffer_used;
@ -792,7 +792,7 @@ static void log_bitmap_usage(const char* which, BitMap* bitmap, size_t total_bit
// Update all oop fields embedded in the buffered objects
void AOTMappedHeapWriter::relocate_embedded_oops(GrowableArrayCHeap<oop, mtClassShared>* roots,
ArchiveMappedHeapInfo* heap_info) {
AOTMappedHeapInfo* heap_info) {
size_t oopmap_unit = (UseCompressedOops ? sizeof(narrowOop) : sizeof(oop));
size_t heap_region_byte_size = _buffer_used;
heap_info->oopmap()->resize(heap_region_byte_size / oopmap_unit);
@ -862,7 +862,7 @@ void AOTMappedHeapWriter::mark_native_pointers(oop orig_obj) {
});
}
void AOTMappedHeapWriter::compute_ptrmap(ArchiveMappedHeapInfo* heap_info) {
void AOTMappedHeapWriter::compute_ptrmap(AOTMappedHeapInfo* heap_info) {
int num_non_null_ptrs = 0;
Metadata** bottom = (Metadata**) _requested_bottom;
Metadata** top = (Metadata**) _requested_top; // exclusive
@ -909,40 +909,23 @@ void AOTMappedHeapWriter::compute_ptrmap(ArchiveMappedHeapInfo* heap_info) {
num_non_null_ptrs, size_t(heap_info->ptrmap()->size()));
}
AOTMapLogger::OopDataIterator* AOTMappedHeapWriter::oop_iterator(ArchiveMappedHeapInfo* heap_info) {
class MappedWriterOopIterator : public AOTMapLogger::OopDataIterator {
private:
address _current;
address _next;
address _buffer_start;
address _buffer_end;
uint64_t _buffer_start_narrow_oop;
intptr_t _buffer_to_requested_delta;
int _requested_shift;
size_t _num_root_segments;
size_t _num_obj_arrays_logged;
AOTMapLogger::OopDataIterator* AOTMappedHeapWriter::oop_iterator(AOTMappedHeapInfo* heap_info) {
class MappedWriterOopIterator : public AOTMappedHeapOopIterator {
public:
MappedWriterOopIterator(address buffer_start,
address buffer_end,
uint64_t buffer_start_narrow_oop,
intptr_t buffer_to_requested_delta,
address requested_base,
address requested_start,
int requested_shift,
size_t num_root_segments)
: _current(nullptr),
_next(buffer_start),
_buffer_start(buffer_start),
_buffer_end(buffer_end),
_buffer_start_narrow_oop(buffer_start_narrow_oop),
_buffer_to_requested_delta(buffer_to_requested_delta),
_requested_shift(requested_shift),
_num_root_segments(num_root_segments),
_num_obj_arrays_logged(0) {
}
size_t num_root_segments) :
AOTMappedHeapOopIterator(buffer_start,
buffer_end,
requested_base,
requested_start,
requested_shift,
num_root_segments) {}
AOTMapLogger::OopData capture(address buffered_addr) {
AOTMapLogger::OopData capture(address buffered_addr) override {
oopDesc* raw_oop = (oopDesc*)buffered_addr;
size_t size = size_of_buffered_oop(buffered_addr);
address requested_addr = buffered_addr_to_requested_addr(buffered_addr);
@ -960,45 +943,6 @@ AOTMapLogger::OopDataIterator* AOTMappedHeapWriter::oop_iterator(ArchiveMappedHe
size,
false };
}
bool has_next() override {
return _next < _buffer_end;
}
AOTMapLogger::OopData next() override {
_current = _next;
AOTMapLogger::OopData result = capture(_current);
if (result._klass->is_objArray_klass()) {
result._is_root_segment = _num_obj_arrays_logged++ < _num_root_segments;
}
_next = _current + result._size * BytesPerWord;
return result;
}
AOTMapLogger::OopData obj_at(narrowOop* addr) override {
uint64_t n = (uint64_t)(*addr);
if (n == 0) {
return null_data();
} else {
precond(n >= _buffer_start_narrow_oop);
address buffer_addr = _buffer_start + ((n - _buffer_start_narrow_oop) << _requested_shift);
return capture(buffer_addr);
}
}
AOTMapLogger::OopData obj_at(oop* addr) override {
address requested_value = cast_from_oop<address>(*addr);
if (requested_value == nullptr) {
return null_data();
} else {
address buffer_addr = requested_value - _buffer_to_requested_delta;
return capture(buffer_addr);
}
}
GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>* roots() override {
return new GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>();
}
};
MemRegion r = heap_info->buffer_region();
@ -1008,17 +952,11 @@ AOTMapLogger::OopDataIterator* AOTMappedHeapWriter::oop_iterator(ArchiveMappedHe
address requested_base = UseCompressedOops ? AOTMappedHeapWriter::narrow_oop_base() : (address)AOTMappedHeapWriter::NOCOOPS_REQUESTED_BASE;
address requested_start = UseCompressedOops ? AOTMappedHeapWriter::buffered_addr_to_requested_addr(buffer_start) : requested_base;
int requested_shift = AOTMappedHeapWriter::narrow_oop_shift();
intptr_t buffer_to_requested_delta = requested_start - buffer_start;
uint64_t buffer_start_narrow_oop = 0xdeadbeed;
if (UseCompressedOops) {
buffer_start_narrow_oop = (uint64_t)(pointer_delta(requested_start, requested_base, 1)) >> requested_shift;
assert(buffer_start_narrow_oop < 0xffffffff, "sanity");
}
return new MappedWriterOopIterator(buffer_start,
buffer_end,
buffer_start_narrow_oop,
buffer_to_requested_delta,
requested_base,
requested_start,
requested_shift,
heap_info->root_segments().count());
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -196,10 +196,10 @@ private:
static int filler_array_length(size_t fill_bytes);
static HeapWord* init_filler_array_at_buffer_top(int array_length, size_t fill_bytes);
static void set_requested_address_range(ArchiveMappedHeapInfo* info);
static void set_requested_address_range(AOTMappedHeapInfo* info);
static void mark_native_pointers(oop orig_obj);
static void relocate_embedded_oops(GrowableArrayCHeap<oop, mtClassShared>* roots, ArchiveMappedHeapInfo* info);
static void compute_ptrmap(ArchiveMappedHeapInfo *info);
static void relocate_embedded_oops(GrowableArrayCHeap<oop, mtClassShared>* roots, AOTMappedHeapInfo* info);
static void compute_ptrmap(AOTMappedHeapInfo *info);
static bool is_in_requested_range(oop o);
static oop requested_obj_from_buffer_offset(size_t offset);
@ -229,7 +229,7 @@ public:
static bool is_string_too_large_to_archive(oop string);
static bool is_dumped_interned_string(oop o);
static void add_to_dumped_interned_strings(oop string);
static void write(GrowableArrayCHeap<oop, mtClassShared>*, ArchiveMappedHeapInfo* heap_info);
static void write(GrowableArrayCHeap<oop, mtClassShared>*, AOTMappedHeapInfo* heap_info);
static address requested_address(); // requested address of the lowest achived heap object
static size_t get_filler_size_at(address buffered_addr);
@ -240,7 +240,7 @@ public:
static Klass* real_klass_of_buffered_oop(address buffered_addr);
static size_t size_of_buffered_oop(address buffered_addr);
static AOTMapLogger::OopDataIterator* oop_iterator(ArchiveMappedHeapInfo* heap_info);
static AOTMapLogger::OopDataIterator* oop_iterator(AOTMappedHeapInfo* heap_info);
};
#endif // INCLUDE_CDS_JAVA_HEAP
#endif // SHARE_CDS_AOTMAPPEDHEAPWRITER_HPP

View File

@ -661,8 +661,8 @@ void AOTMetaspace::rewrite_bytecodes_and_calculate_fingerprints(Thread* thread,
class VM_PopulateDumpSharedSpace : public VM_Operation {
private:
ArchiveMappedHeapInfo _mapped_heap_info;
ArchiveStreamedHeapInfo _streamed_heap_info;
AOTMappedHeapInfo _mapped_heap_info;
AOTStreamedHeapInfo _streamed_heap_info;
FileMapInfo* _map_info;
StaticArchiveBuilder& _builder;
@ -682,8 +682,8 @@ public:
bool skip_operation() const { return false; }
VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; }
ArchiveMappedHeapInfo* mapped_heap_info() { return &_mapped_heap_info; }
ArchiveStreamedHeapInfo* streamed_heap_info() { return &_streamed_heap_info; }
AOTMappedHeapInfo* mapped_heap_info() { return &_mapped_heap_info; }
AOTStreamedHeapInfo* streamed_heap_info() { return &_streamed_heap_info; }
void doit(); // outline because gdb sucks
bool allow_nested_vm_operations() const { return true; }
}; // class VM_PopulateDumpSharedSpace
@ -1212,8 +1212,8 @@ void AOTMetaspace::dump_static_archive_impl(StaticArchiveBuilder& builder, TRAPS
bool AOTMetaspace::write_static_archive(ArchiveBuilder* builder,
FileMapInfo* map_info,
ArchiveMappedHeapInfo* mapped_heap_info,
ArchiveStreamedHeapInfo* streamed_heap_info) {
AOTMappedHeapInfo* mapped_heap_info,
AOTStreamedHeapInfo* streamed_heap_info) {
// relocate the data so that it can be mapped to AOTMetaspace::requested_base_address()
// without runtime relocation.
builder->relocate_to_requested();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,8 +33,8 @@
#include "utilities/macros.hpp"
class ArchiveBuilder;
class ArchiveMappedHeapInfo;
class ArchiveStreamedHeapInfo;
class AOTMappedHeapInfo;
class AOTStreamedHeapInfo;
class FileMapInfo;
class Method;
class outputStream;
@ -192,8 +192,8 @@ private:
static void open_output_mapinfo();
static bool write_static_archive(ArchiveBuilder* builder,
FileMapInfo* map_info,
ArchiveMappedHeapInfo* mapped_heap_info,
ArchiveStreamedHeapInfo* streamed_heap_info);
AOTMappedHeapInfo* mapped_heap_info,
AOTStreamedHeapInfo* streamed_heap_info);
static FileMapInfo* open_static_archive();
static FileMapInfo* open_dynamic_archive();
// use_requested_addr: If true (default), attempt to map at the address the

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "cds/aotStreamedHeap.hpp"
// Anything that goes in the header must be thoroughly purged from uninitialized memory
// as it will be written to disk. Therefore, the constructors memset the memory to 0.
// This is not the prettiest thing, but we need to know every byte is initialized,
// including potential padding between fields.
AOTStreamedHeapHeader::AOTStreamedHeapHeader(size_t forwarding_offset,
size_t roots_offset,
size_t num_roots,
size_t root_highest_object_index_table_offset,
size_t num_archived_objects) {
memset((char*)this, 0, sizeof(*this));
_forwarding_offset = forwarding_offset;
_roots_offset = roots_offset;
_num_roots = num_roots;
_root_highest_object_index_table_offset = root_highest_object_index_table_offset;
_num_archived_objects = num_archived_objects;
}
AOTStreamedHeapHeader::AOTStreamedHeapHeader() {
memset((char*)this, 0, sizeof(*this));
}
AOTStreamedHeapHeader AOTStreamedHeapInfo::create_header() {
return AOTStreamedHeapHeader{_forwarding_offset,
_roots_offset,
_num_roots,
_root_highest_object_index_table_offset,
_num_archived_objects};
}

View File

@ -0,0 +1,147 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_CDS_AOTSTREAMEDHEAP_HPP
#define SHARE_CDS_AOTSTREAMEDHEAP_HPP
#include "cds/aotMapLogger.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
class AOTStreamedHeapHeader {
size_t _forwarding_offset; // Offset of forwarding information in the heap region.
size_t _roots_offset; // Start position for the roots
size_t _root_highest_object_index_table_offset; // Offset of root dfs depth information
size_t _num_roots; // Number of embedded roots
size_t _num_archived_objects; // The number of archived heap objects
public:
AOTStreamedHeapHeader();
AOTStreamedHeapHeader(size_t forwarding_offset,
size_t roots_offset,
size_t num_roots,
size_t root_highest_object_index_table_offset,
size_t num_archived_objects);
size_t forwarding_offset() const { return _forwarding_offset; }
size_t roots_offset() const { return _roots_offset; }
size_t num_roots() const { return _num_roots; }
size_t root_highest_object_index_table_offset() const { return _root_highest_object_index_table_offset; }
size_t num_archived_objects() const { return _num_archived_objects; }
// This class is trivially copyable and assignable.
AOTStreamedHeapHeader(const AOTStreamedHeapHeader&) = default;
AOTStreamedHeapHeader& operator=(const AOTStreamedHeapHeader&) = default;
};
class AOTStreamedHeapInfo {
MemRegion _buffer_region; // Contains the archived objects to be written into the CDS archive.
CHeapBitMap _oopmap;
size_t _roots_offset; // Offset of the HeapShared::roots() object, from the bottom
// of the archived heap objects, in bytes.
size_t _num_roots;
size_t _forwarding_offset; // Offset of forwarding information from the bottom
size_t _root_highest_object_index_table_offset; // Offset to root dfs depth information
size_t _num_archived_objects; // The number of archived objects written into the CDS archive.
public:
AOTStreamedHeapInfo()
: _buffer_region(),
_oopmap(128, mtClassShared),
_roots_offset(),
_forwarding_offset(),
_root_highest_object_index_table_offset(),
_num_archived_objects() {}
bool is_used() { return !_buffer_region.is_empty(); }
void set_buffer_region(MemRegion r) { _buffer_region = r; }
MemRegion buffer_region() { return _buffer_region; }
char* buffer_start() { return (char*)_buffer_region.start(); }
size_t buffer_byte_size() { return _buffer_region.byte_size(); }
CHeapBitMap* oopmap() { return &_oopmap; }
void set_roots_offset(size_t n) { _roots_offset = n; }
size_t roots_offset() { return _roots_offset; }
void set_num_roots(size_t n) { _num_roots = n; }
size_t num_roots() { return _num_roots; }
void set_forwarding_offset(size_t n) { _forwarding_offset = n; }
void set_root_highest_object_index_table_offset(size_t n) { _root_highest_object_index_table_offset = n; }
void set_num_archived_objects(size_t n) { _num_archived_objects = n; }
size_t num_archived_objects() { return _num_archived_objects; }
AOTStreamedHeapHeader create_header();
};
#if INCLUDE_CDS_JAVA_HEAP
class AOTStreamedHeapOopIterator : public AOTMapLogger::OopDataIterator {
protected:
int _current;
int _next;
address _buffer_start;
int _num_archived_objects;
public:
AOTStreamedHeapOopIterator(address buffer_start,
int num_archived_objects)
: _current(0),
_next(1),
_buffer_start(buffer_start),
_num_archived_objects(num_archived_objects) {}
virtual AOTMapLogger::OopData capture(int dfs_index) = 0;
bool has_next() override {
return _next <= _num_archived_objects;
}
AOTMapLogger::OopData next() override {
_current = _next;
AOTMapLogger::OopData result = capture(_current);
_next = _current + 1;
return result;
}
AOTMapLogger::OopData obj_at(narrowOop* addr) override {
int dfs_index = (int)(*addr);
if (dfs_index == 0) {
return null_data();
} else {
return capture(dfs_index);
}
}
AOTMapLogger::OopData obj_at(oop* addr) override {
int dfs_index = (int)cast_from_oop<uintptr_t>(*addr);
if (dfs_index == 0) {
return null_data();
} else {
return capture(dfs_index);
}
}
};
#endif // INCLUDE_CDS_JAVA_HEAP
#endif // SHARE_CDS_AOTSTREAMEDHEAP_HPP

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1102,25 +1102,13 @@ void AOTStreamedHeapLoader::finish_initialization(FileMapInfo* static_mapinfo) {
}
AOTMapLogger::OopDataIterator* AOTStreamedHeapLoader::oop_iterator(FileMapInfo* info, address buffer_start, address buffer_end) {
class StreamedLoaderOopIterator : public AOTMapLogger::OopDataIterator {
private:
int _current;
int _next;
address _buffer_start;
int _num_archived_objects;
class StreamedLoaderOopIterator : public AOTStreamedHeapOopIterator {
public:
StreamedLoaderOopIterator(address buffer_start,
int num_archived_objects)
: _current(0),
_next(1),
_buffer_start(buffer_start),
_num_archived_objects(num_archived_objects) {
}
: AOTStreamedHeapOopIterator(buffer_start, num_archived_objects) {}
AOTMapLogger::OopData capture(int dfs_index) {
AOTMapLogger::OopData capture(int dfs_index) override {
size_t buffered_offset = buffer_offset_for_object_index(dfs_index);
address buffered_addr = _buffer_start + buffered_offset;
oopDesc* raw_oop = (oopDesc*)buffered_addr;
@ -1142,35 +1130,6 @@ AOTMapLogger::OopDataIterator* AOTStreamedHeapLoader::oop_iterator(FileMapInfo*
false };
}
bool has_next() override {
return _next <= _num_archived_objects;
}
AOTMapLogger::OopData next() override {
_current = _next;
AOTMapLogger::OopData result = capture(_current);
_next = _current + 1;
return result;
}
AOTMapLogger::OopData obj_at(narrowOop* addr) override {
int dfs_index = (int)(*addr);
if (dfs_index == 0) {
return null_data();
} else {
return capture(dfs_index);
}
}
AOTMapLogger::OopData obj_at(oop* addr) override {
int dfs_index = (int)cast_from_oop<uintptr_t>(*addr);
if (dfs_index == 0) {
return null_data();
} else {
return capture(dfs_index);
}
}
GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>* roots() override {
GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>* result = new GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -163,7 +163,7 @@ void AOTStreamedHeapWriter::order_source_objs(GrowableArrayCHeap<oop, mtClassSha
}
void AOTStreamedHeapWriter::write(GrowableArrayCHeap<oop, mtClassShared>* roots,
ArchiveStreamedHeapInfo* heap_info) {
AOTStreamedHeapInfo* heap_info) {
assert(CDSConfig::is_dumping_heap(), "sanity");
allocate_buffer();
order_source_objs(roots);
@ -453,7 +453,7 @@ static void log_bitmap_usage(const char* which, BitMap* bitmap, size_t total_bit
}
// Update all oop fields embedded in the buffered objects
void AOTStreamedHeapWriter::map_embedded_oops(ArchiveStreamedHeapInfo* heap_info) {
void AOTStreamedHeapWriter::map_embedded_oops(AOTStreamedHeapInfo* heap_info) {
size_t oopmap_unit = (UseCompressedOops ? sizeof(narrowOop) : sizeof(oop));
size_t heap_region_byte_size = _buffer_used;
heap_info->oopmap()->resize(heap_region_byte_size / oopmap_unit);
@ -497,7 +497,7 @@ oop AOTStreamedHeapWriter::buffered_addr_to_source_obj(address buffered_addr) {
return buffered_offset_to_source_obj(buffered_address_to_offset(buffered_addr));
}
void AOTStreamedHeapWriter::populate_archive_heap_info(ArchiveStreamedHeapInfo* info) {
void AOTStreamedHeapWriter::populate_archive_heap_info(AOTStreamedHeapInfo* info) {
assert(!info->is_used(), "only set once");
size_t heap_region_byte_size = _buffer_used;
@ -512,15 +512,9 @@ void AOTStreamedHeapWriter::populate_archive_heap_info(ArchiveStreamedHeapInfo*
info->set_num_archived_objects((size_t)_source_objs->length());
}
AOTMapLogger::OopDataIterator* AOTStreamedHeapWriter::oop_iterator(ArchiveStreamedHeapInfo* heap_info) {
class StreamedWriterOopIterator : public AOTMapLogger::OopDataIterator {
AOTMapLogger::OopDataIterator* AOTStreamedHeapWriter::oop_iterator(AOTStreamedHeapInfo* heap_info) {
class StreamedWriterOopIterator : public AOTStreamedHeapOopIterator {
private:
int _current;
int _next;
address _buffer_start;
int _num_archived_objects;
int _num_archived_roots;
int* _roots;
@ -529,15 +523,11 @@ AOTMapLogger::OopDataIterator* AOTStreamedHeapWriter::oop_iterator(ArchiveStream
int num_archived_objects,
int num_archived_roots,
int* roots)
: _current(0),
_next(1),
_buffer_start(buffer_start),
_num_archived_objects(num_archived_objects),
: AOTStreamedHeapOopIterator(buffer_start, num_archived_objects),
_num_archived_roots(num_archived_roots),
_roots(roots) {
}
_roots(roots) {}
AOTMapLogger::OopData capture(int dfs_index) {
AOTMapLogger::OopData capture(int dfs_index) override {
size_t buffered_offset = _dfs_to_archive_object_table[dfs_index];
address buffered_addr = _buffer_start + buffered_offset;
oop src_obj = AOTStreamedHeapWriter::buffered_offset_to_source_obj(buffered_offset);
@ -561,35 +551,6 @@ AOTMapLogger::OopDataIterator* AOTStreamedHeapWriter::oop_iterator(ArchiveStream
false };
}
bool has_next() override {
return _next <= _num_archived_objects;
}
AOTMapLogger::OopData next() override {
_current = _next;
AOTMapLogger::OopData result = capture(_current);
_next = _current + 1;
return result;
}
AOTMapLogger::OopData obj_at(narrowOop* addr) override {
int dfs_index = (int)(*addr);
if (dfs_index == 0) {
return null_data();
} else {
return capture(dfs_index);
}
}
AOTMapLogger::OopData obj_at(oop* addr) override {
int dfs_index = (int)cast_from_oop<uintptr_t>(*addr);
if (dfs_index == 0) {
return null_data();
} else {
return capture(dfs_index);
}
}
GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>* roots() override {
GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>* result = new GrowableArrayCHeap<AOTMapLogger::OopData, mtClass>();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -117,7 +117,7 @@ class AOTStreamedHeapWriter : AllStatic {
static void copy_forwarding_to_buffer();
static void copy_roots_max_dfs_to_buffer(int roots_length);
static void map_embedded_oops(ArchiveStreamedHeapInfo* info);
static void map_embedded_oops(AOTStreamedHeapInfo* info);
static bool is_in_requested_range(oop o);
static oop requested_obj_from_buffer_offset(size_t offset);
@ -131,14 +131,14 @@ class AOTStreamedHeapWriter : AllStatic {
static void update_header_for_buffered_addr(address buffered_addr, oop src_obj, Klass* src_klass);
static void populate_archive_heap_info(ArchiveStreamedHeapInfo* info);
static void populate_archive_heap_info(AOTStreamedHeapInfo* info);
public:
static void init() NOT_CDS_JAVA_HEAP_RETURN;
static void delete_tables_with_raw_oops();
static void add_source_obj(oop src_obj);
static void write(GrowableArrayCHeap<oop, mtClassShared>*, ArchiveStreamedHeapInfo* heap_info);
static void write(GrowableArrayCHeap<oop, mtClassShared>*, AOTStreamedHeapInfo* heap_info);
static address buffered_heap_roots_addr() {
return offset_to_buffered_address<address>(_roots_offset);
}
@ -156,7 +156,7 @@ public:
static oop buffered_offset_to_source_obj(size_t buffered_offset);
static oop buffered_addr_to_source_obj(address buffered_addr);
static AOTMapLogger::OopDataIterator* oop_iterator(ArchiveStreamedHeapInfo* heap_info);
static AOTMapLogger::OopDataIterator* oop_iterator(AOTStreamedHeapInfo* heap_info);
};
#endif // INCLUDE_CDS_JAVA_HEAP
#endif // SHARE_CDS_AOTSTREAMEDHEAPWRITER_HPP

View File

@ -1154,7 +1154,7 @@ void ArchiveBuilder::print_stats() {
_alloc_stats.print_stats(int(_ro_region.used()), int(_rw_region.used()));
}
void ArchiveBuilder::write_archive(FileMapInfo* mapinfo, ArchiveMappedHeapInfo* mapped_heap_info, ArchiveStreamedHeapInfo* streamed_heap_info) {
void ArchiveBuilder::write_archive(FileMapInfo* mapinfo, AOTMappedHeapInfo* mapped_heap_info, AOTStreamedHeapInfo* streamed_heap_info) {
// Make sure NUM_CDS_REGIONS (exported in cds.h) agrees with
// AOTMetaspace::n_regions (internal to hotspot).
assert(NUM_CDS_REGIONS == AOTMetaspace::n_regions, "sanity");
@ -1213,8 +1213,8 @@ void ArchiveBuilder::count_relocated_pointer(bool tagged, bool nulled) {
}
void ArchiveBuilder::print_region_stats(FileMapInfo *mapinfo,
ArchiveMappedHeapInfo* mapped_heap_info,
ArchiveStreamedHeapInfo* streamed_heap_info) {
AOTMappedHeapInfo* mapped_heap_info,
AOTStreamedHeapInfo* streamed_heap_info) {
// Print statistics of all the regions
const size_t bitmap_used = mapinfo->region_at(AOTMetaspace::bm)->used();
const size_t bitmap_reserved = mapinfo->region_at(AOTMetaspace::bm)->used_aligned();

View File

@ -39,8 +39,8 @@
#include "utilities/hashTable.hpp"
#include "utilities/resizableHashTable.hpp"
class ArchiveMappedHeapInfo;
class ArchiveStreamedHeapInfo;
class AOTMappedHeapInfo;
class AOTStreamedHeapInfo;
class CHeapBitMap;
class FileMapInfo;
class Klass;
@ -247,8 +247,8 @@ private:
} _relocated_ptr_info;
void print_region_stats(FileMapInfo *map_info,
ArchiveMappedHeapInfo* mapped_heap_info,
ArchiveStreamedHeapInfo* streamed_heap_info);
AOTMappedHeapInfo* mapped_heap_info,
AOTStreamedHeapInfo* streamed_heap_info);
void print_bitmap_region_stats(size_t size, size_t total_size);
void print_heap_region_stats(char* start, size_t size, size_t total_size);
@ -438,8 +438,8 @@ public:
void make_training_data_shareable();
void relocate_to_requested();
void write_archive(FileMapInfo* mapinfo,
ArchiveMappedHeapInfo* mapped_heap_info,
ArchiveStreamedHeapInfo* streamed_heap_info);
AOTMappedHeapInfo* mapped_heap_info,
AOTStreamedHeapInfo* streamed_heap_info);
void write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region,
bool read_only, bool allow_exec);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -974,8 +974,8 @@ size_t FileMapInfo::remove_bitmap_zeros(CHeapBitMap* map) {
char* FileMapInfo::write_bitmap_region(CHeapBitMap* rw_ptrmap,
CHeapBitMap* ro_ptrmap,
ArchiveMappedHeapInfo* mapped_heap_info,
ArchiveStreamedHeapInfo* streamed_heap_info,
AOTMappedHeapInfo* mapped_heap_info,
AOTStreamedHeapInfo* streamed_heap_info,
size_t &size_in_bytes) {
size_t removed_rw_leading_zeros = remove_bitmap_zeros(rw_ptrmap);
size_t removed_ro_leading_zeros = remove_bitmap_zeros(ro_ptrmap);
@ -1035,7 +1035,7 @@ char* FileMapInfo::write_bitmap_region(CHeapBitMap* rw_ptrmap,
}
#if INCLUDE_CDS_JAVA_HEAP
size_t FileMapInfo::write_mapped_heap_region(ArchiveMappedHeapInfo* heap_info) {
size_t FileMapInfo::write_mapped_heap_region(AOTMappedHeapInfo* heap_info) {
char* buffer_start = heap_info->buffer_start();
size_t buffer_size = heap_info->buffer_byte_size();
write_region(AOTMetaspace::hp, buffer_start, buffer_size, false, false);
@ -1043,7 +1043,7 @@ size_t FileMapInfo::write_mapped_heap_region(ArchiveMappedHeapInfo* heap_info) {
return buffer_size;
}
size_t FileMapInfo::write_streamed_heap_region(ArchiveStreamedHeapInfo* heap_info) {
size_t FileMapInfo::write_streamed_heap_region(AOTStreamedHeapInfo* heap_info) {
char* buffer_start = heap_info->buffer_start();
size_t buffer_size = heap_info->buffer_byte_size();
write_region(AOTMetaspace::hp, buffer_start, buffer_size, true, false);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,9 @@
#ifndef SHARE_CDS_FILEMAP_HPP
#define SHARE_CDS_FILEMAP_HPP
#include "cds/aotMappedHeap.hpp"
#include "cds/aotMetaspace.hpp"
#include "cds/aotStreamedHeap.hpp"
#include "cds/archiveUtils.hpp"
#include "cds/heapShared.hpp"
#include "include/cds.h"
@ -144,8 +146,8 @@ private:
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
ArchiveMappedHeapHeader _mapped_heap_header;
ArchiveStreamedHeapHeader _streamed_heap_header;
AOTMappedHeapHeader _mapped_heap_header;
AOTStreamedHeapHeader _streamed_heap_header;
// The following are parameters that affect MethodData layout.
u1 _compiler_type;
@ -209,11 +211,11 @@ public:
size_t ro_ptrmap_start_pos() const { return _ro_ptrmap_start_pos; }
// Heap archiving
const ArchiveMappedHeapHeader* mapped_heap() const { return &_mapped_heap_header; }
const ArchiveStreamedHeapHeader* streamed_heap() const { return &_streamed_heap_header; }
const AOTMappedHeapHeader* mapped_heap() const { return &_mapped_heap_header; }
const AOTStreamedHeapHeader* streamed_heap() const { return &_streamed_heap_header; }
void set_streamed_heap_header(ArchiveStreamedHeapHeader header) { _streamed_heap_header = header; }
void set_mapped_heap_header(ArchiveMappedHeapHeader header) { _mapped_heap_header = header; }
void set_streamed_heap_header(AOTStreamedHeapHeader header) { _streamed_heap_header = header; }
void set_mapped_heap_header(AOTMappedHeapHeader header) { _mapped_heap_header = header; }
void set_has_platform_or_app_classes(bool v) { _has_platform_or_app_classes = v; }
void set_cloned_vtables(char* p) { set_as_offset(p, &_cloned_vtables_offset); }
@ -309,8 +311,8 @@ public:
uintx max_heap_size() const { return header()->max_heap_size(); }
size_t core_region_alignment() const { return header()->core_region_alignment(); }
const ArchiveMappedHeapHeader* mapped_heap() const { return header()->mapped_heap(); }
const ArchiveStreamedHeapHeader* streamed_heap() const { return header()->streamed_heap(); }
const AOTMappedHeapHeader* mapped_heap() const { return header()->mapped_heap(); }
const AOTStreamedHeapHeader* streamed_heap() const { return header()->streamed_heap(); }
bool object_streaming_mode() const { return header()->object_streaming_mode(); }
CompressedOops::Mode narrow_oop_mode() const { return header()->narrow_oop_mode(); }
@ -372,11 +374,11 @@ public:
size_t remove_bitmap_zeros(CHeapBitMap* map);
char* write_bitmap_region(CHeapBitMap* rw_ptrmap,
CHeapBitMap* ro_ptrmap,
ArchiveMappedHeapInfo* mapped_heap_info,
ArchiveStreamedHeapInfo* streamed_heap_info,
AOTMappedHeapInfo* mapped_heap_info,
AOTStreamedHeapInfo* streamed_heap_info,
size_t &size_in_bytes);
size_t write_mapped_heap_region(ArchiveMappedHeapInfo* heap_info) NOT_CDS_JAVA_HEAP_RETURN_(0);
size_t write_streamed_heap_region(ArchiveStreamedHeapInfo* heap_info) NOT_CDS_JAVA_HEAP_RETURN_(0);
size_t write_mapped_heap_region(AOTMappedHeapInfo* heap_info) NOT_CDS_JAVA_HEAP_RETURN_(0);
size_t write_streamed_heap_region(AOTStreamedHeapInfo* heap_info) NOT_CDS_JAVA_HEAP_RETURN_(0);
void write_bytes(const void* buffer, size_t count);
void write_bytes_aligned(const void* buffer, size_t count);
size_t read_bytes(void* buffer, size_t count);

View File

@ -95,55 +95,6 @@ struct ArchivableStaticFieldInfo {
}
};
// Anything that goes in the header must be thoroughly purged from uninitialized memory
// as it will be written to disk. Therefore, the constructors memset the memory to 0.
// This is not the prettiest thing, but we need to know every byte is initialized,
// including potential padding between fields.
ArchiveMappedHeapHeader::ArchiveMappedHeapHeader(size_t ptrmap_start_pos,
size_t oopmap_start_pos,
HeapRootSegments root_segments) {
memset((char*)this, 0, sizeof(*this));
_ptrmap_start_pos = ptrmap_start_pos;
_oopmap_start_pos = oopmap_start_pos;
_root_segments = root_segments;
}
ArchiveMappedHeapHeader::ArchiveMappedHeapHeader() {
memset((char*)this, 0, sizeof(*this));
}
ArchiveMappedHeapHeader ArchiveMappedHeapInfo::create_header() {
return ArchiveMappedHeapHeader{_ptrmap_start_pos,
_oopmap_start_pos,
_root_segments};
}
ArchiveStreamedHeapHeader::ArchiveStreamedHeapHeader(size_t forwarding_offset,
size_t roots_offset,
size_t num_roots,
size_t root_highest_object_index_table_offset,
size_t num_archived_objects) {
memset((char*)this, 0, sizeof(*this));
_forwarding_offset = forwarding_offset;
_roots_offset = roots_offset;
_num_roots = num_roots;
_root_highest_object_index_table_offset = root_highest_object_index_table_offset;
_num_archived_objects = num_archived_objects;
}
ArchiveStreamedHeapHeader::ArchiveStreamedHeapHeader() {
memset((char*)this, 0, sizeof(*this));
}
ArchiveStreamedHeapHeader ArchiveStreamedHeapInfo::create_header() {
return ArchiveStreamedHeapHeader{_forwarding_offset,
_roots_offset,
_num_roots,
_root_highest_object_index_table_offset,
_num_archived_objects};
}
HeapArchiveMode HeapShared::_heap_load_mode = HeapArchiveMode::_uninitialized;
HeapArchiveMode HeapShared::_heap_write_mode = HeapArchiveMode::_uninitialized;
@ -892,7 +843,7 @@ void HeapShared::end_scanning_for_oops() {
delete_seen_objects_table();
}
void HeapShared::write_heap(ArchiveMappedHeapInfo* mapped_heap_info, ArchiveStreamedHeapInfo* streamed_heap_info) {
void HeapShared::write_heap(AOTMappedHeapInfo* mapped_heap_info, AOTStreamedHeapInfo* streamed_heap_info) {
{
NoSafepointVerifier nsv;
CDSHeapVerifier::verify();

View File

@ -142,129 +142,6 @@ enum class HeapArchiveMode {
_streaming
};
class ArchiveMappedHeapHeader {
size_t _ptrmap_start_pos; // The first bit in the ptrmap corresponds to this position in the heap.
size_t _oopmap_start_pos; // The first bit in the oopmap corresponds to this position in the heap.
HeapRootSegments _root_segments; // Heap root segments info
public:
ArchiveMappedHeapHeader();
ArchiveMappedHeapHeader(size_t ptrmap_start_pos,
size_t oopmap_start_pos,
HeapRootSegments root_segments);
size_t ptrmap_start_pos() const { return _ptrmap_start_pos; }
size_t oopmap_start_pos() const { return _oopmap_start_pos; }
HeapRootSegments root_segments() const { return _root_segments; }
// This class is trivially copyable and assignable.
ArchiveMappedHeapHeader(const ArchiveMappedHeapHeader&) = default;
ArchiveMappedHeapHeader& operator=(const ArchiveMappedHeapHeader&) = default;
};
class ArchiveStreamedHeapHeader {
size_t _forwarding_offset; // Offset of forwarding information in the heap region.
size_t _roots_offset; // Start position for the roots
size_t _root_highest_object_index_table_offset; // Offset of root dfs depth information
size_t _num_roots; // Number of embedded roots
size_t _num_archived_objects; // The number of archived heap objects
public:
ArchiveStreamedHeapHeader();
ArchiveStreamedHeapHeader(size_t forwarding_offset,
size_t roots_offset,
size_t num_roots,
size_t root_highest_object_index_table_offset,
size_t num_archived_objects);
size_t forwarding_offset() const { return _forwarding_offset; }
size_t roots_offset() const { return _roots_offset; }
size_t num_roots() const { return _num_roots; }
size_t root_highest_object_index_table_offset() const { return _root_highest_object_index_table_offset; }
size_t num_archived_objects() const { return _num_archived_objects; }
// This class is trivially copyable and assignable.
ArchiveStreamedHeapHeader(const ArchiveStreamedHeapHeader&) = default;
ArchiveStreamedHeapHeader& operator=(const ArchiveStreamedHeapHeader&) = default;
};
class ArchiveMappedHeapInfo {
MemRegion _buffer_region; // Contains the archived objects to be written into the CDS archive.
CHeapBitMap _oopmap;
CHeapBitMap _ptrmap;
HeapRootSegments _root_segments;
size_t _oopmap_start_pos; // How many zeros were removed from the beginning of the bit map?
size_t _ptrmap_start_pos; // How many zeros were removed from the beginning of the bit map?
public:
ArchiveMappedHeapInfo() :
_buffer_region(),
_oopmap(128, mtClassShared),
_ptrmap(128, mtClassShared),
_root_segments(),
_oopmap_start_pos(),
_ptrmap_start_pos() {}
bool is_used() { return !_buffer_region.is_empty(); }
MemRegion buffer_region() { return _buffer_region; }
void set_buffer_region(MemRegion r) { _buffer_region = r; }
char* buffer_start() { return (char*)_buffer_region.start(); }
size_t buffer_byte_size() { return _buffer_region.byte_size(); }
CHeapBitMap* oopmap() { return &_oopmap; }
CHeapBitMap* ptrmap() { return &_ptrmap; }
void set_oopmap_start_pos(size_t start_pos) { _oopmap_start_pos = start_pos; }
void set_ptrmap_start_pos(size_t start_pos) { _ptrmap_start_pos = start_pos; }
void set_root_segments(HeapRootSegments segments) { _root_segments = segments; };
HeapRootSegments root_segments() { return _root_segments; }
ArchiveMappedHeapHeader create_header();
};
class ArchiveStreamedHeapInfo {
MemRegion _buffer_region; // Contains the archived objects to be written into the CDS archive.
CHeapBitMap _oopmap;
size_t _roots_offset; // Offset of the HeapShared::roots() object, from the bottom
// of the archived heap objects, in bytes.
size_t _num_roots;
size_t _forwarding_offset; // Offset of forwarding information from the bottom
size_t _root_highest_object_index_table_offset; // Offset to root dfs depth information
size_t _num_archived_objects; // The number of archived objects written into the CDS archive.
public:
ArchiveStreamedHeapInfo()
: _buffer_region(),
_oopmap(128, mtClassShared),
_roots_offset(),
_forwarding_offset(),
_root_highest_object_index_table_offset(),
_num_archived_objects() {}
bool is_used() { return !_buffer_region.is_empty(); }
void set_buffer_region(MemRegion r) { _buffer_region = r; }
MemRegion buffer_region() { return _buffer_region; }
char* buffer_start() { return (char*)_buffer_region.start(); }
size_t buffer_byte_size() { return _buffer_region.byte_size(); }
CHeapBitMap* oopmap() { return &_oopmap; }
void set_roots_offset(size_t n) { _roots_offset = n; }
size_t roots_offset() { return _roots_offset; }
void set_num_roots(size_t n) { _num_roots = n; }
size_t num_roots() { return _num_roots; }
void set_forwarding_offset(size_t n) { _forwarding_offset = n; }
void set_root_highest_object_index_table_offset(size_t n) { _root_highest_object_index_table_offset = n; }
void set_num_archived_objects(size_t n) { _num_archived_objects = n; }
size_t num_archived_objects() { return _num_archived_objects; }
ArchiveStreamedHeapHeader create_header();
};
class HeapShared: AllStatic {
friend class VerifySharedOopClosure;
@ -575,7 +452,7 @@ private:
public:
static void finish_materialize_objects() NOT_CDS_JAVA_HEAP_RETURN;
static void write_heap(ArchiveMappedHeapInfo* mapped_heap_info, ArchiveStreamedHeapInfo* streamed_heap_info) NOT_CDS_JAVA_HEAP_RETURN;
static void write_heap(AOTMappedHeapInfo* mapped_heap_info, AOTStreamedHeapInfo* streamed_heap_info) NOT_CDS_JAVA_HEAP_RETURN;
static objArrayOop scratch_resolved_references(ConstantPool* src);
static void add_scratch_resolved_references(ConstantPool* src, objArrayOop dest) NOT_CDS_JAVA_HEAP_RETURN;
static void init_dumping() NOT_CDS_JAVA_HEAP_RETURN;