From 0867f9b1b4bfa090cce1403cdbcce56a2e91127c Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Wed, 11 Feb 2026 23:00:50 +0000 Subject: [PATCH] 8377307: Refactor code for AOT cache pointer compression Reviewed-by: jsjolen, xuelei, asmehra --- .../share/cds/aotCompressedPointers.cpp | 30 ++++ .../share/cds/aotCompressedPointers.hpp | 142 ++++++++++++++++++ src/hotspot/share/cds/aotMetaspace.cpp | 6 +- src/hotspot/share/cds/archiveBuilder.cpp | 20 +-- src/hotspot/share/cds/archiveBuilder.hpp | 43 +----- src/hotspot/share/cds/archiveUtils.cpp | 14 +- src/hotspot/share/cds/archiveUtils.hpp | 56 +------ src/hotspot/share/cds/dynamicArchive.cpp | 9 +- src/hotspot/share/cds/filemap.cpp | 12 +- src/hotspot/share/cds/filemap.hpp | 35 ++--- src/hotspot/share/cds/heapShared.cpp | 4 +- src/hotspot/share/cds/lambdaFormInvokers.cpp | 13 +- src/hotspot/share/cds/lambdaFormInvokers.hpp | 7 +- .../share/cds/lambdaProxyClassDictionary.cpp | 28 ++-- .../share/cds/lambdaProxyClassDictionary.hpp | 57 ++++--- src/hotspot/share/cds/runTimeClassInfo.cpp | 19 +-- src/hotspot/share/cds/runTimeClassInfo.hpp | 27 ++-- .../share/classfile/compactHashtable.hpp | 12 +- src/hotspot/share/classfile/symbolTable.cpp | 3 +- .../classfile/systemDictionaryShared.cpp | 9 +- src/hotspot/share/include/cds.h | 4 +- src/hotspot/share/oops/trainingData.cpp | 6 +- src/hotspot/share/runtime/sharedRuntime.cpp | 7 +- src/hotspot/share/runtime/sharedRuntime.hpp | 2 +- src/hotspot/share/runtime/vmStructs.cpp | 4 +- .../sun/jvm/hotspot/memory/FileMapInfo.java | 8 +- 26 files changed, 343 insertions(+), 234 deletions(-) create mode 100644 src/hotspot/share/cds/aotCompressedPointers.cpp create mode 100644 src/hotspot/share/cds/aotCompressedPointers.hpp diff --git a/src/hotspot/share/cds/aotCompressedPointers.cpp b/src/hotspot/share/cds/aotCompressedPointers.cpp new file mode 100644 index 00000000000..c3efa7a7185 --- /dev/null +++ b/src/hotspot/share/cds/aotCompressedPointers.cpp @@ -0,0 +1,30 @@ +/* + * 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/aotCompressedPointers.hpp" +#include "cds/archiveBuilder.hpp" + +size_t AOTCompressedPointers::compute_byte_offset(address p) { + return ArchiveBuilder::current()->any_to_offset(p); +} diff --git a/src/hotspot/share/cds/aotCompressedPointers.hpp b/src/hotspot/share/cds/aotCompressedPointers.hpp new file mode 100644 index 00000000000..ead48ef9948 --- /dev/null +++ b/src/hotspot/share/cds/aotCompressedPointers.hpp @@ -0,0 +1,142 @@ +/* + * 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_AOTCOMPRESSEDPOINTERS_HPP +#define SHARE_CDS_AOTCOMPRESSEDPOINTERS_HPP + +#include "cds/cds_globals.hpp" +#include "memory/allStatic.hpp" +#include "memory/metaspace.hpp" +#include "metaprogramming/enableIf.hpp" +#include "utilities/align.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +class AOTCompressedPointers: public AllStatic { +public: + // For space saving, we can encode the location of metadata objects in the "rw" and "ro" + // regions using a 32-bit offset from the bottom of the mapped AOT metaspace. + // Currently we allow only up to 2GB total size in the rw and ro regions (which are + // contiguous to each other). + enum class narrowPtr : u4; + static constexpr size_t MaxMetadataOffsetBytes = 0x7FFFFFFF; + + // In the future, this could return a different numerical value than + // narrowp if the encoding contains shifts. + inline static size_t get_byte_offset(narrowPtr narrowp) { + return checked_cast(narrowp); + } + + inline static narrowPtr null() { + return static_cast(0); + } + + // Encoding ------ + + // ptr can point to one of the following + // - an object in the ArchiveBuilder's buffer. + // - an object in the currently mapped AOT cache rw/ro regions. + // - an object that has been copied into the ArchiveBuilder's buffer. + template + static narrowPtr encode_not_null(T ptr) { + address p = reinterpret_cast
(ptr); + return encode_byte_offset(compute_byte_offset(p)); + } + + template + static narrowPtr encode(T ptr) { // may be null + if (ptr == nullptr) { + return null(); + } else { + return encode_not_null(ptr); + } + } + + // ptr must be in the currently mapped AOT cache rw/ro regions. + template + static narrowPtr encode_address_in_cache(T ptr) { + assert(Metaspace::in_aot_cache(ptr), "must be"); + address p = reinterpret_cast
(ptr); + address base = reinterpret_cast
(SharedBaseAddress); + return encode_byte_offset(pointer_delta(p, base, 1)); + } + + template + static narrowPtr encode_address_in_cache_or_null(T ptr) { + if (ptr == nullptr) { + return null(); + } else { + return encode_address_in_cache(ptr); + } + } + + // Decoding ----- + + // If base_address is null, decode an address within the mapped aot cache range. + template + static T decode_not_null(narrowPtr narrowp, address base_address = nullptr) { + assert(narrowp != null(), "sanity"); + if (base_address == nullptr) { + T p = reinterpret_cast(reinterpret_cast
(SharedBaseAddress) + get_byte_offset(narrowp)); + assert(Metaspace::in_aot_cache(p), "must be"); + return p; + } else { + // This is usually called before the cache is fully mapped. + return reinterpret_cast(base_address + get_byte_offset(narrowp)); + } + } + + template + static T decode(narrowPtr narrowp, address base_address = nullptr) { // may be null + if (narrowp == null()) { + return nullptr; + } else { + return decode_not_null(narrowp, base_address); + } + } + +private: + static size_t compute_byte_offset(address p); + + static narrowPtr encode_byte_offset(size_t offset) { + assert(offset != 0, "offset 0 is in protection zone"); + precond(offset <= MaxMetadataOffsetBytes); + return checked_cast(offset); + } +}; + +// Type casts -- declared as global functions to save a few keystrokes + +// A simple type cast. No change in numerical value. +inline AOTCompressedPointers::narrowPtr cast_from_u4(u4 narrowp) { + return checked_cast(narrowp); +} + +// A simple type cast. No change in numerical value. +// !!!DO NOT CALL THIS if you want a byte offset!!! +inline u4 cast_to_u4(AOTCompressedPointers::narrowPtr narrowp) { + return checked_cast(narrowp); +} + +#endif // SHARE_CDS_AOTCOMPRESSEDPOINTERS_HPP diff --git a/src/hotspot/share/cds/aotMetaspace.cpp b/src/hotspot/share/cds/aotMetaspace.cpp index 8bb8387f1ab..544eaa07a4d 100644 --- a/src/hotspot/share/cds/aotMetaspace.cpp +++ b/src/hotspot/share/cds/aotMetaspace.cpp @@ -2106,7 +2106,7 @@ MapArchiveResult AOTMetaspace::map_archive(FileMapInfo* mapinfo, char* mapped_ba // Currently, only static archive uses early serialized data. char* buffer = mapinfo->early_serialized_data(); intptr_t* array = (intptr_t*)buffer; - ReadClosure rc(&array, (intptr_t)mapped_base_address); + ReadClosure rc(&array, (address)mapped_base_address); early_serialize(&rc); } @@ -2152,7 +2152,7 @@ void AOTMetaspace::initialize_shared_spaces() { // shared string/symbol tables. char* buffer = static_mapinfo->serialized_data(); intptr_t* array = (intptr_t*)buffer; - ReadClosure rc(&array, (intptr_t)SharedBaseAddress); + ReadClosure rc(&array, (address)SharedBaseAddress); serialize(&rc); // Finish initializing the heap dump mode used in the archive @@ -2164,7 +2164,7 @@ void AOTMetaspace::initialize_shared_spaces() { if (dynamic_mapinfo != nullptr) { intptr_t* buffer = (intptr_t*)dynamic_mapinfo->serialized_data(); - ReadClosure rc(&buffer, (intptr_t)SharedBaseAddress); + ReadClosure rc(&buffer, (address)SharedBaseAddress); DynamicArchive::serialize(&rc); } diff --git a/src/hotspot/share/cds/archiveBuilder.cpp b/src/hotspot/share/cds/archiveBuilder.cpp index e65bd3985ac..cb9459172b3 100644 --- a/src/hotspot/share/cds/archiveBuilder.cpp +++ b/src/hotspot/share/cds/archiveBuilder.cpp @@ -24,6 +24,7 @@ #include "cds/aotArtifactFinder.hpp" #include "cds/aotClassLinker.hpp" +#include "cds/aotCompressedPointers.hpp" #include "cds/aotLogging.hpp" #include "cds/aotMapLogger.hpp" #include "cds/aotMetaspace.hpp" @@ -175,10 +176,10 @@ ArchiveBuilder::ArchiveBuilder() : _mapped_static_archive_bottom(nullptr), _mapped_static_archive_top(nullptr), _buffer_to_requested_delta(0), - _pz_region("pz", MAX_SHARED_DELTA), // protection zone -- used only during dumping; does NOT exist in cds archive. - _rw_region("rw", MAX_SHARED_DELTA), - _ro_region("ro", MAX_SHARED_DELTA), - _ac_region("ac", MAX_SHARED_DELTA), + _pz_region("pz"), // protection zone -- used only during dumping; does NOT exist in cds archive. + _rw_region("rw"), + _ro_region("ro"), + _ac_region("ac"), _ptrmap(mtClassShared), _rw_ptrmap(mtClassShared), _ro_ptrmap(mtClassShared), @@ -990,16 +991,15 @@ void ArchiveBuilder::make_training_data_shareable() { _src_obj_table.iterate_all(clean_td); } -uintx ArchiveBuilder::buffer_to_offset(address p) const { +size_t ArchiveBuilder::buffer_to_offset(address p) const { address requested_p = to_requested(p); - assert(requested_p >= _requested_static_archive_bottom, "must be"); - return requested_p - _requested_static_archive_bottom; + return pointer_delta(requested_p, _requested_static_archive_bottom, 1); } -uintx ArchiveBuilder::any_to_offset(address p) const { +size_t ArchiveBuilder::any_to_offset(address p) const { if (is_in_mapped_static_archive(p)) { assert(CDSConfig::is_dumping_dynamic_archive(), "must be"); - return p - _mapped_static_archive_bottom; + return pointer_delta(p, _mapped_static_archive_bottom, 1); } if (!is_in_buffer_space(p)) { // p must be a "source" address @@ -1008,7 +1008,7 @@ uintx ArchiveBuilder::any_to_offset(address p) const { return buffer_to_offset(p); } -address ArchiveBuilder::offset_to_buffered_address(u4 offset) const { +address ArchiveBuilder::offset_to_buffered_address(size_t offset) const { address requested_addr = _requested_static_archive_bottom + offset; address buffered_addr = requested_addr - _buffer_to_requested_delta; assert(is_in_buffer_space(buffered_addr), "bad offset"); diff --git a/src/hotspot/share/cds/archiveBuilder.hpp b/src/hotspot/share/cds/archiveBuilder.hpp index 2284dbf70f8..b3667ea11b4 100644 --- a/src/hotspot/share/cds/archiveBuilder.hpp +++ b/src/hotspot/share/cds/archiveBuilder.hpp @@ -329,49 +329,22 @@ public: return current()->buffer_to_requested_delta(); } - inline static u4 to_offset_u4(uintx offset) { - guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset " INTPTR_FORMAT, offset); - return (u4)offset; - } - public: - static const uintx MAX_SHARED_DELTA = ArchiveUtils::MAX_SHARED_DELTA;; - // The address p points to an object inside the output buffer. When the archive is mapped // at the requested address, what's the offset of this object from _requested_static_archive_bottom? - uintx buffer_to_offset(address p) const; + size_t buffer_to_offset(address p) const; - // Same as buffer_to_offset, except that the address p points to either (a) an object - // inside the output buffer, or (b), an object in the currently mapped static archive. - uintx any_to_offset(address p) const; + // Same as buffer_to_offset, except that the address p points to one of the following: + // - an object in the ArchiveBuilder's buffer. + // - an object in the currently mapped AOT cache rw/ro regions. + // - an object that has been copied into the ArchiveBuilder's buffer. + size_t any_to_offset(address p) const; // The reverse of buffer_to_offset() - address offset_to_buffered_address(u4 offset) const; + address offset_to_buffered_address(size_t offset) const; template - u4 buffer_to_offset_u4(T p) const { - uintx offset = buffer_to_offset((address)p); - return to_offset_u4(offset); - } - - template - u4 any_to_offset_u4(T p) const { - assert(p != nullptr, "must not be null"); - uintx offset = any_to_offset((address)p); - return to_offset_u4(offset); - } - - template - u4 any_or_null_to_offset_u4(T p) const { - if (p == nullptr) { - return 0; - } else { - return any_to_offset_u4(p); - } - } - - template - T offset_to_buffered(u4 offset) const { + T offset_to_buffered(size_t offset) const { return (T)offset_to_buffered_address(offset); } diff --git a/src/hotspot/share/cds/archiveUtils.cpp b/src/hotspot/share/cds/archiveUtils.cpp index 842668509cf..c13b447bb87 100644 --- a/src/hotspot/share/cds/archiveUtils.cpp +++ b/src/hotspot/share/cds/archiveUtils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -22,6 +22,7 @@ * */ +#include "cds/aotCompressedPointers.hpp" #include "cds/aotLogging.hpp" #include "cds/aotMetaspace.hpp" #include "cds/archiveBuilder.hpp" @@ -201,13 +202,13 @@ char* DumpRegion::expand_top_to(char* newtop) { commit_to(newtop); _top = newtop; - if (_max_delta > 0) { + if (ArchiveBuilder::is_active() && ArchiveBuilder::current()->is_in_buffer_space(_base)) { uintx delta = ArchiveBuilder::current()->buffer_to_offset((address)(newtop-1)); - if (delta > _max_delta) { + if (delta > AOTCompressedPointers::MaxMetadataOffsetBytes) { // This is just a sanity check and should not appear in any real world usage. This // happens only if you allocate more than 2GB of shared objects and would require // millions of shared classes. - aot_log_error(aot)("Out of memory in the CDS archive: Please reduce the number of shared classes."); + aot_log_error(aot)("Out of memory in the %s: Please reduce the number of shared classes.", CDSConfig::type_of_archive_being_written()); AOTMetaspace::unrecoverable_writing_error(); } } @@ -331,9 +332,8 @@ void WriteClosure::do_ptr(void** p) { void ReadClosure::do_ptr(void** p) { assert(*p == nullptr, "initializing previous initialized pointer."); - intptr_t obj = nextPtr(); - assert(obj >= 0, "sanity."); - *p = (obj != 0) ? (void*)(_base_address + obj) : (void*)obj; + u4 narrowp = checked_cast(nextPtr()); + *p = AOTCompressedPointers::decode(cast_from_u4(narrowp), _base_address); } void ReadClosure::do_u4(u4* p) { diff --git a/src/hotspot/share/cds/archiveUtils.hpp b/src/hotspot/share/cds/archiveUtils.hpp index 79d894f0144..e5d1efa5eab 100644 --- a/src/hotspot/share/cds/archiveUtils.hpp +++ b/src/hotspot/share/cds/archiveUtils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -153,7 +153,6 @@ private: char* _base; char* _top; char* _end; - uintx _max_delta; bool _is_packed; ReservedSpace* _rs; VirtualSpace* _vs; @@ -161,9 +160,9 @@ private: void commit_to(char* newtop); public: - DumpRegion(const char* name, uintx max_delta = 0) + DumpRegion(const char* name) : _name(name), _base(nullptr), _top(nullptr), _end(nullptr), - _max_delta(max_delta), _is_packed(false), + _is_packed(false), _rs(nullptr), _vs(nullptr) {} char* expand_top_to(char* newtop); @@ -237,13 +236,13 @@ public: class ReadClosure : public SerializeClosure { private: intptr_t** _ptr_array; - intptr_t _base_address; + address _base_address; inline intptr_t nextPtr() { return *(*_ptr_array)++; } public: - ReadClosure(intptr_t** ptr_array, intptr_t base_address) : + ReadClosure(intptr_t** ptr_array, address base_address) : _ptr_array(ptr_array), _base_address(base_address) {} void do_ptr(void** p); @@ -260,7 +259,6 @@ class ArchiveUtils { template static Array* archive_ptr_array(GrowableArray* tmp_array); public: - static const uintx MAX_SHARED_DELTA = 0x7FFFFFFF; static void log_to_classlist(BootstrapInfo* bootstrap_specifier, TRAPS) NOT_CDS_RETURN; static bool has_aot_initialized_mirror(InstanceKlass* src_ik); @@ -273,50 +271,6 @@ public: static Array* archive_array(GrowableArray* tmp_array) { return archive_ptr_array(tmp_array); } - - // The following functions translate between a u4 offset and an address in the - // the range of the mapped CDS archive (e.g., Metaspace::in_aot_cache()). - // Since the first 16 bytes in this range are dummy data (see ArchiveBuilder::reserve_buffer()), - // we know that offset 0 never represents a valid object. As a result, an offset of 0 - // is used to encode a nullptr. - // - // Use the "archived_address_or_null" variants if a nullptr may be encoded. - - // offset must represent an object of type T in the mapped shared space. Return - // a direct pointer to this object. - template T static offset_to_archived_address(u4 offset) { - assert(offset != 0, "sanity"); - T p = (T)(SharedBaseAddress + offset); - assert(Metaspace::in_aot_cache(p), "must be"); - return p; - } - - template T static offset_to_archived_address_or_null(u4 offset) { - if (offset == 0) { - return nullptr; - } else { - return offset_to_archived_address(offset); - } - } - - // p must be an archived object. Get its offset from SharedBaseAddress - template static u4 archived_address_to_offset(T p) { - uintx pn = (uintx)p; - uintx base = (uintx)SharedBaseAddress; - assert(Metaspace::in_aot_cache(p), "must be"); - assert(pn > base, "sanity"); // No valid object is stored at 0 offset from SharedBaseAddress - uintx offset = pn - base; - assert(offset <= MAX_SHARED_DELTA, "range check"); - return static_cast(offset); - } - - template static u4 archived_address_or_null_to_offset(T p) { - if (p == nullptr) { - return 0; - } else { - return archived_address_to_offset(p); - } - } }; class HeapRootSegments { diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index d39cf3775e4..cd6890555d3 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -25,6 +25,7 @@ #include "cds/aotArtifactFinder.hpp" #include "cds/aotClassLinker.hpp" #include "cds/aotClassLocation.hpp" +#include "cds/aotCompressedPointers.hpp" #include "cds/aotLogging.hpp" #include "cds/aotMetaspace.hpp" #include "cds/archiveBuilder.hpp" @@ -75,13 +76,13 @@ public: return 0; } - u4 a_offset = ArchiveBuilder::current()->any_to_offset_u4(a_name); - u4 b_offset = ArchiveBuilder::current()->any_to_offset_u4(b_name); + u4 a_narrowp = cast_to_u4(AOTCompressedPointers::encode_not_null(a_name)); + u4 b_narrowp = cast_to_u4(AOTCompressedPointers::encode_not_null(b_name)); - if (a_offset < b_offset) { + if (a_narrowp < b_narrowp) { return -1; } else { - assert(a_offset > b_offset, "must be"); + assert(a_narrowp > b_narrowp, "must be"); return 1; } } diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 7cd736885ad..a779fcddfcf 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -298,11 +298,11 @@ void FileMapHeader::print(outputStream* st) { st->print_cr("- compressed_class_ptrs: %d", _compressed_class_ptrs); st->print_cr("- narrow_klass_pointer_bits: %d", _narrow_klass_pointer_bits); st->print_cr("- narrow_klass_shift: %d", _narrow_klass_shift); - st->print_cr("- cloned_vtables_offset: 0x%zx", _cloned_vtables_offset); - st->print_cr("- early_serialized_data_offset: 0x%zx", _early_serialized_data_offset); - st->print_cr("- serialized_data_offset: 0x%zx", _serialized_data_offset); + st->print_cr("- cloned_vtables: %u", cast_to_u4(_cloned_vtables)); + st->print_cr("- early_serialized_data: %u", cast_to_u4(_early_serialized_data)); + st->print_cr("- serialized_data: %u", cast_to_u4(_serialized_data)); st->print_cr("- jvm_ident: %s", _jvm_ident); - st->print_cr("- class_location_config_offset: 0x%zx", _class_location_config_offset); + st->print_cr("- class_location_config: %d", cast_to_u4(_class_location_config)); st->print_cr("- verify_local: %d", _verify_local); st->print_cr("- verify_remote: %d", _verify_remote); st->print_cr("- has_platform_or_app_classes: %d", _has_platform_or_app_classes); @@ -1767,10 +1767,6 @@ void FileMapInfo::print(outputStream* st) const { } } -void FileMapHeader::set_as_offset(char* p, size_t *offset) { - *offset = ArchiveBuilder::current()->any_to_offset((address)p); -} - int FileMapHeader::compute_crc() { char* start = (char*)this; // start computing from the field after _header_size to end of base archive name. diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index ec7b58a6d19..56b88df378a 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_CDS_FILEMAP_HPP #define SHARE_CDS_FILEMAP_HPP +#include "cds/aotCompressedPointers.hpp" #include "cds/aotMappedHeap.hpp" #include "cds/aotMetaspace.hpp" #include "cds/aotStreamedHeap.hpp" @@ -104,7 +105,7 @@ public: class FileMapHeader: private CDSFileMapHeaderBase { friend class CDSConstants; friend class VMStructs; - + using narrowPtr = AOTCompressedPointers::narrowPtr; private: // The following fields record the states of the VM during dump time. // They are compared with the runtime states to see if the archive @@ -122,16 +123,16 @@ private: bool _compressed_class_ptrs; // save the flag UseCompressedClassPointers int _narrow_klass_pointer_bits; // save number of bits in narrowKlass int _narrow_klass_shift; // save shift width used to pre-compute narrowKlass IDs in archived heap objects - size_t _cloned_vtables_offset; // The address of the first cloned vtable - size_t _early_serialized_data_offset; // Data accessed using {ReadClosure,WriteClosure}::serialize() - size_t _serialized_data_offset; // Data accessed using {ReadClosure,WriteClosure}::serialize() + narrowPtr _cloned_vtables; // The address of the first cloned vtable + narrowPtr _early_serialized_data; // Data accessed using {ReadClosure,WriteClosure}::serialize() + narrowPtr _serialized_data; // Data accessed using {ReadClosure,WriteClosure}::serialize() // The following fields are all sanity checks for whether this archive // will function correctly with this JVM and the bootclasspath it's // invoked with. char _jvm_ident[JVM_IDENT_MAX]; // identifier string of the jvm that created this dump - size_t _class_location_config_offset; + narrowPtr _class_location_config; bool _verify_local; // BytecodeVerificationLocal setting bool _verify_remote; // BytecodeVerificationRemote setting @@ -160,12 +161,8 @@ private: bool _type_profile_casts; int _spec_trap_limit_extra_entries; - template T from_mapped_offset(size_t offset) const { - return (T)(mapped_base_address() + offset); - } - void set_as_offset(char* p, size_t *offset); - template void set_as_offset(T p, size_t *offset) { - set_as_offset((char*)p, offset); + template T decode(narrowPtr narrowp) const { + return AOTCompressedPointers::decode_not_null(narrowp, reinterpret_cast
(mapped_base_address())); } public: @@ -193,9 +190,9 @@ public: bool compact_headers() const { return _compact_headers; } uintx max_heap_size() const { return _max_heap_size; } CompressedOops::Mode narrow_oop_mode() const { return _narrow_oop_mode; } - char* cloned_vtables() const { return from_mapped_offset(_cloned_vtables_offset); } - char* early_serialized_data() const { return from_mapped_offset(_early_serialized_data_offset); } - char* serialized_data() const { return from_mapped_offset(_serialized_data_offset); } + char* cloned_vtables() const { return decode(_cloned_vtables); } + char* early_serialized_data() const { return decode(_early_serialized_data); } + char* serialized_data() const { return decode(_serialized_data); } bool object_streaming_mode() const { return _object_streaming_mode; } const char* jvm_ident() const { return _jvm_ident; } char* requested_base_address() const { return _requested_base_address; } @@ -218,9 +215,9 @@ public: 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); } - void set_early_serialized_data(char* p) { set_as_offset(p, &_early_serialized_data_offset); } - void set_serialized_data(char* p) { set_as_offset(p, &_serialized_data_offset); } + void set_cloned_vtables(char* p) { _cloned_vtables = AOTCompressedPointers::encode_not_null(p); } + void set_early_serialized_data(char* p) { _early_serialized_data = AOTCompressedPointers::encode_not_null(p); } + void set_serialized_data(char* p) { _serialized_data = AOTCompressedPointers::encode_not_null(p); } void set_mapped_base_address(char* p) { _mapped_base_address = p; } 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; } @@ -228,11 +225,11 @@ public: void copy_base_archive_name(const char* name); void set_class_location_config(AOTClassLocationConfig* table) { - set_as_offset(table, &_class_location_config_offset); + _class_location_config = AOTCompressedPointers::encode_not_null(table); } AOTClassLocationConfig* class_location_config() { - return from_mapped_offset(_class_location_config_offset); + return decode(_class_location_config); } void set_requested_base(char* b) { diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index 69a098c67b3..c01e6ded25a 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -25,6 +25,7 @@ #include "cds/aotArtifactFinder.hpp" #include "cds/aotClassInitializer.hpp" #include "cds/aotClassLocation.hpp" +#include "cds/aotCompressedPointers.hpp" #include "cds/aotLogging.hpp" #include "cds/aotMappedHeapLoader.hpp" #include "cds/aotMappedHeapWriter.hpp" @@ -1148,8 +1149,7 @@ public: ArchivedKlassSubGraphInfoRecord* record = HeapShared::archive_subgraph_info(&info); Klass* buffered_k = ArchiveBuilder::get_buffered_klass(klass); unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary((address)buffered_k); - u4 delta = ArchiveBuilder::current()->any_to_offset_u4(record); - _writer->add(hash, delta); + _writer->add(hash, AOTCompressedPointers::encode_not_null(record)); } return true; // keep on iterating } diff --git a/src/hotspot/share/cds/lambdaFormInvokers.cpp b/src/hotspot/share/cds/lambdaFormInvokers.cpp index 19dae28c5b5..3ff5705b79d 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.cpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -23,6 +23,7 @@ */ #include "cds/aotClassFilter.hpp" +#include "cds/aotCompressedPointers.hpp" #include "cds/aotMetaspace.hpp" #include "cds/archiveBuilder.hpp" #include "cds/cdsConfig.hpp" @@ -52,7 +53,7 @@ #include "runtime/mutexLocker.hpp" GrowableArrayCHeap* LambdaFormInvokers::_lambdaform_lines = nullptr; -Array* LambdaFormInvokers::_static_archive_invokers = nullptr; +Array* LambdaFormInvokers::_static_archive_invokers = nullptr; static bool _stop_appending = false; #define NUM_FILTER 4 @@ -252,7 +253,7 @@ void LambdaFormInvokers::dump_static_archive_invokers() { } } if (count > 0) { - _static_archive_invokers = ArchiveBuilder::new_ro_array(count); + _static_archive_invokers = ArchiveBuilder::new_ro_array(count); int index = 0; for (int i = 0; i < len; i++) { char* str = _lambdaform_lines->at(i); @@ -261,7 +262,7 @@ void LambdaFormInvokers::dump_static_archive_invokers() { Array* line = ArchiveBuilder::new_ro_array((int)str_len); strncpy(line->adr_at(0), str, str_len); - _static_archive_invokers->at_put(index, ArchiveBuilder::current()->any_to_offset_u4(line)); + _static_archive_invokers->at_put(index, AOTCompressedPointers::encode_not_null(line)); index++; } } @@ -274,8 +275,8 @@ void LambdaFormInvokers::dump_static_archive_invokers() { void LambdaFormInvokers::read_static_archive_invokers() { if (_static_archive_invokers != nullptr) { for (int i = 0; i < _static_archive_invokers->length(); i++) { - u4 offset = _static_archive_invokers->at(i); - Array* line = ArchiveUtils::offset_to_archived_address*>(offset); + narrowPtr encoded = _static_archive_invokers->at(i); + Array* line = AOTCompressedPointers::decode_not_null*>(encoded); char* str = line->adr_at(0); append(str); } diff --git a/src/hotspot/share/cds/lambdaFormInvokers.hpp b/src/hotspot/share/cds/lambdaFormInvokers.hpp index 583a863a1c2..9b91850f5b1 100644 --- a/src/hotspot/share/cds/lambdaFormInvokers.hpp +++ b/src/hotspot/share/cds/lambdaFormInvokers.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -24,6 +24,8 @@ #ifndef SHARE_CDS_LAMBDAFORMINVOKERS_HPP #define SHARE_CDS_LAMBDAFORMINVOKERS_HPP + +#include "cds/aotCompressedPointers.hpp" #include "memory/allStatic.hpp" #include "oops/oopHandle.hpp" #include "runtime/handles.hpp" @@ -35,10 +37,11 @@ class Array; class SerializeClosure; class LambdaFormInvokers : public AllStatic { + using narrowPtr = AOTCompressedPointers::narrowPtr; private: static GrowableArrayCHeap* _lambdaform_lines; // For storing LF form lines (LF_RESOLVE only) in read only table. - static Array* _static_archive_invokers; + static Array* _static_archive_invokers; static void regenerate_class(char* name, ClassFileStream& st, TRAPS); public: static void append(char* line); diff --git a/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp b/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp index d091067c116..4d212dbf2c2 100644 --- a/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp +++ b/src/hotspot/share/cds/lambdaProxyClassDictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -23,6 +23,7 @@ */ #include "cds/aotClassFilter.hpp" +#include "cds/aotCompressedPointers.hpp" #include "cds/archiveBuilder.hpp" #include "cds/cdsConfig.hpp" #include "cds/cdsProtectionDomain.hpp" @@ -49,11 +50,11 @@ unsigned int LambdaProxyClassKey::hash() const { } unsigned int RunTimeLambdaProxyClassKey::hash() const { - return primitive_hash(_caller_ik) + - primitive_hash(_invoked_name) + - primitive_hash(_invoked_type) + - primitive_hash(_method_type) + - primitive_hash(_instantiated_method_type); + return primitive_hash(cast_to_u4(_caller_ik)) + + primitive_hash(cast_to_u4(_invoked_name)) + + primitive_hash(cast_to_u4(_invoked_type)) + + primitive_hash(cast_to_u4(_method_type)) + + primitive_hash(cast_to_u4(_instantiated_method_type)); } #ifndef PRODUCT @@ -71,12 +72,12 @@ void LambdaProxyClassKey::print_on(outputStream* st) const { void RunTimeLambdaProxyClassKey::print_on(outputStream* st) const { ResourceMark rm; st->print_cr("LambdaProxyClassKey : " INTPTR_FORMAT " hash: %0x08x", p2i(this), hash()); - st->print_cr("_caller_ik : %d", _caller_ik); - st->print_cr("_instantiated_method_type : %d", _instantiated_method_type); - st->print_cr("_invoked_name : %d", _invoked_name); - st->print_cr("_invoked_type : %d", _invoked_type); - st->print_cr("_member_method : %d", _member_method); - st->print_cr("_method_type : %d", _method_type); + st->print_cr("_caller_ik : %d", cast_to_u4(_caller_ik)); + st->print_cr("_instantiated_method_type : %d", cast_to_u4(_instantiated_method_type)); + st->print_cr("_invoked_name : %d", cast_to_u4(_invoked_name)); + st->print_cr("_invoked_type : %d", cast_to_u4(_invoked_type)); + st->print_cr("_member_method : %d", cast_to_u4(_member_method)); + st->print_cr("_method_type : %d", cast_to_u4(_method_type)); } void RunTimeLambdaProxyClassInfo::print_on(outputStream* st) const { @@ -418,8 +419,7 @@ public: (RunTimeLambdaProxyClassInfo*)ArchiveBuilder::ro_region_alloc(byte_size); runtime_info->init(key, info); unsigned int hash = runtime_info->hash(); - u4 delta = _builder->any_to_offset_u4((void*)runtime_info); - _writer->add(hash, delta); + _writer->add(hash, AOTCompressedPointers::encode_not_null(runtime_info)); return true; } }; diff --git a/src/hotspot/share/cds/lambdaProxyClassDictionary.hpp b/src/hotspot/share/cds/lambdaProxyClassDictionary.hpp index 91e508bfdc5..dfb75532917 100644 --- a/src/hotspot/share/cds/lambdaProxyClassDictionary.hpp +++ b/src/hotspot/share/cds/lambdaProxyClassDictionary.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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,8 +25,9 @@ #ifndef SHARE_CDS_LAMBDAPROXYCLASSINFO_HPP #define SHARE_CDS_LAMBDAPROXYCLASSINFO_HPP +#include "cds/aotCompressedPointers.hpp" #include "cds/aotMetaspace.hpp" -#include "cds/archiveBuilder.hpp" +#include "classfile/compactHashtable.hpp" #include "classfile/javaClasses.hpp" #include "memory/metaspaceClosure.hpp" #include "utilities/growableArray.hpp" @@ -132,19 +133,20 @@ public: }; class RunTimeLambdaProxyClassKey { - u4 _caller_ik; - u4 _invoked_name; - u4 _invoked_type; - u4 _method_type; - u4 _member_method; - u4 _instantiated_method_type; + using narrowPtr = AOTCompressedPointers::narrowPtr; + narrowPtr _caller_ik; + narrowPtr _invoked_name; + narrowPtr _invoked_type; + narrowPtr _method_type; + narrowPtr _member_method; + narrowPtr _instantiated_method_type; - RunTimeLambdaProxyClassKey(u4 caller_ik, - u4 invoked_name, - u4 invoked_type, - u4 method_type, - u4 member_method, - u4 instantiated_method_type) : + RunTimeLambdaProxyClassKey(narrowPtr caller_ik, + narrowPtr invoked_name, + narrowPtr invoked_type, + narrowPtr method_type, + narrowPtr member_method, + narrowPtr instantiated_method_type) : _caller_ik(caller_ik), _invoked_name(invoked_name), _invoked_type(invoked_type), @@ -154,15 +156,12 @@ class RunTimeLambdaProxyClassKey { public: static RunTimeLambdaProxyClassKey init_for_dumptime(LambdaProxyClassKey& key) { - assert(ArchiveBuilder::is_active(), "sanity"); - ArchiveBuilder* b = ArchiveBuilder::current(); - - u4 caller_ik = b->any_to_offset_u4(key.caller_ik()); - u4 invoked_name = b->any_to_offset_u4(key.invoked_name()); - u4 invoked_type = b->any_to_offset_u4(key.invoked_type()); - u4 method_type = b->any_to_offset_u4(key.method_type()); - u4 member_method = b->any_or_null_to_offset_u4(key.member_method()); // could be null - u4 instantiated_method_type = b->any_to_offset_u4(key.instantiated_method_type()); + narrowPtr caller_ik = AOTCompressedPointers::encode_not_null(key.caller_ik()); + narrowPtr invoked_name = AOTCompressedPointers::encode_not_null(key.invoked_name()); + narrowPtr invoked_type = AOTCompressedPointers::encode_not_null(key.invoked_type()); + narrowPtr method_type = AOTCompressedPointers::encode_not_null(key.method_type()); + narrowPtr member_method = AOTCompressedPointers::encode(key.member_method()); // could be null + narrowPtr instantiated_method_type = AOTCompressedPointers::encode_not_null(key.instantiated_method_type()); return RunTimeLambdaProxyClassKey(caller_ik, invoked_name, invoked_type, method_type, member_method, instantiated_method_type); @@ -176,12 +175,12 @@ public: Symbol* instantiated_method_type) { // All parameters must be in shared space, or else you'd get an assert in // ArchiveUtils::to_offset(). - return RunTimeLambdaProxyClassKey(ArchiveUtils::archived_address_to_offset(caller_ik), - ArchiveUtils::archived_address_to_offset(invoked_name), - ArchiveUtils::archived_address_to_offset(invoked_type), - ArchiveUtils::archived_address_to_offset(method_type), - ArchiveUtils::archived_address_or_null_to_offset(member_method), // could be null - ArchiveUtils::archived_address_to_offset(instantiated_method_type)); + return RunTimeLambdaProxyClassKey(AOTCompressedPointers::encode_address_in_cache(caller_ik), + AOTCompressedPointers::encode_address_in_cache(invoked_name), + AOTCompressedPointers::encode_address_in_cache(invoked_type), + AOTCompressedPointers::encode_address_in_cache(method_type), + AOTCompressedPointers::encode_address_in_cache_or_null(member_method), // could be null + AOTCompressedPointers::encode_address_in_cache(instantiated_method_type)); } unsigned int hash() const; diff --git a/src/hotspot/share/cds/runTimeClassInfo.cpp b/src/hotspot/share/cds/runTimeClassInfo.cpp index fe940ca6c18..a1f50ab4ffa 100644 --- a/src/hotspot/share/cds/runTimeClassInfo.cpp +++ b/src/hotspot/share/cds/runTimeClassInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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 @@ -22,15 +22,15 @@ * */ +#include "cds/aotCompressedPointers.hpp" #include "cds/archiveBuilder.hpp" #include "cds/dumpTimeClassInfo.hpp" #include "cds/runTimeClassInfo.hpp" #include "classfile/systemDictionaryShared.hpp" void RunTimeClassInfo::init(DumpTimeClassInfo& info) { - ArchiveBuilder* builder = ArchiveBuilder::current(); InstanceKlass* k = info._klass; - _klass_offset = builder->any_to_offset_u4(k); + _klass = AOTCompressedPointers::encode_not_null(k); if (!SystemDictionaryShared::is_builtin(k)) { CrcInfo* c = crc(); @@ -50,8 +50,8 @@ void RunTimeClassInfo::init(DumpTimeClassInfo& info) { RTVerifierConstraint* vf_constraints = verifier_constraints(); char* flags = verifier_constraint_flags(); for (i = 0; i < _num_verifier_constraints; i++) { - vf_constraints[i]._name = builder->any_to_offset_u4(info._verifier_constraints->at(i).name()); - vf_constraints[i]._from_name = builder->any_or_null_to_offset_u4(info._verifier_constraints->at(i).from_name()); + vf_constraints[i]._name = AOTCompressedPointers::encode_not_null(info._verifier_constraints->at(i).name()); + vf_constraints[i]._from_name = AOTCompressedPointers::encode(info._verifier_constraints->at(i).from_name()); } for (i = 0; i < _num_verifier_constraints; i++) { flags[i] = info._verifier_constraint_flags->at(i); @@ -61,14 +61,14 @@ void RunTimeClassInfo::init(DumpTimeClassInfo& info) { if (_num_loader_constraints > 0) { RTLoaderConstraint* ld_constraints = loader_constraints(); for (i = 0; i < _num_loader_constraints; i++) { - ld_constraints[i]._name = builder->any_to_offset_u4(info._loader_constraints->at(i).name()); + ld_constraints[i]._name = AOTCompressedPointers::encode_not_null(info._loader_constraints->at(i).name()); ld_constraints[i]._loader_type1 = info._loader_constraints->at(i).loader_type1(); ld_constraints[i]._loader_type2 = info._loader_constraints->at(i).loader_type2(); } } if (k->is_hidden() && info.nest_host() != nullptr) { - _nest_host_offset = builder->any_to_offset_u4(info.nest_host()); + _nest_host = AOTCompressedPointers::encode_not_null(info.nest_host()); } if (k->has_archived_enum_objs()) { int num = info.num_enum_klass_static_fields(); @@ -83,11 +83,12 @@ void RunTimeClassInfo::init(DumpTimeClassInfo& info) { InstanceKlass* RunTimeClassInfo::klass() const { if (AOTMetaspace::in_aot_cache(this)) { // is inside a mmaped CDS archive. - return ArchiveUtils::offset_to_archived_address(_klass_offset); + return AOTCompressedPointers::decode_not_null(_klass); } else { // is a temporary copy of a RunTimeClassInfo that's being initialized // by the ArchiveBuilder. - return ArchiveBuilder::current()->offset_to_buffered(_klass_offset); + size_t byte_offset = AOTCompressedPointers::get_byte_offset(_klass); + return ArchiveBuilder::current()->offset_to_buffered(byte_offset); } } diff --git a/src/hotspot/share/cds/runTimeClassInfo.hpp b/src/hotspot/share/cds/runTimeClassInfo.hpp index 371924f9065..d63a04698bb 100644 --- a/src/hotspot/share/cds/runTimeClassInfo.hpp +++ b/src/hotspot/share/cds/runTimeClassInfo.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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,6 +25,7 @@ #ifndef SHARE_CDS_RUNTIMECLASSINFO_HPP #define SHARE_CDS_RUNTIMECLASSINFO_HPP +#include "cds/aotCompressedPointers.hpp" #include "cds/aotMetaspace.hpp" #include "cds/archiveBuilder.hpp" #include "cds/archiveUtils.hpp" @@ -41,8 +42,10 @@ class Method; class Symbol; class RunTimeClassInfo { - public: - enum : char { + using narrowPtr = AOTCompressedPointers::narrowPtr; + +public: + enum : char { FROM_FIELD_IS_PROTECTED = 1 << 0, FROM_IS_ARRAY = 1 << 1, FROM_IS_OBJECT = 1 << 2 @@ -56,19 +59,19 @@ class RunTimeClassInfo { // This is different than DumpTimeClassInfo::DTVerifierConstraint. We use // u4 instead of Symbol* to save space on 64-bit CPU. struct RTVerifierConstraint { - u4 _name; - u4 _from_name; - Symbol* name() { return ArchiveUtils::offset_to_archived_address(_name); } + narrowPtr _name; + narrowPtr _from_name; + Symbol* name() { return AOTCompressedPointers::decode_not_null(_name); } Symbol* from_name() { - return (_from_name == 0) ? nullptr : ArchiveUtils::offset_to_archived_address(_from_name); + return AOTCompressedPointers::decode(_from_name); } }; struct RTLoaderConstraint { - u4 _name; + narrowPtr _name; char _loader_type1; char _loader_type2; - Symbol* constraint_name() { return ArchiveUtils::offset_to_archived_address(_name); } + Symbol* constraint_name() { return AOTCompressedPointers::decode_not_null(_name); } }; struct RTEnumKlassStaticFields { int _num; @@ -76,8 +79,8 @@ class RunTimeClassInfo { }; private: - u4 _klass_offset; - u4 _nest_host_offset; + narrowPtr _klass; + narrowPtr _nest_host; int _num_verifier_constraints; int _num_loader_constraints; @@ -185,7 +188,7 @@ public: InstanceKlass* nest_host() { assert(!ArchiveBuilder::is_active(), "not called when dumping archive"); - return ArchiveUtils::offset_to_archived_address_or_null(_nest_host_offset); + return AOTCompressedPointers::decode(_nest_host); // may be null } RTLoaderConstraint* loader_constraints() { diff --git a/src/hotspot/share/classfile/compactHashtable.hpp b/src/hotspot/share/classfile/compactHashtable.hpp index 944fb876521..2fe92be0f6d 100644 --- a/src/hotspot/share/classfile/compactHashtable.hpp +++ b/src/hotspot/share/classfile/compactHashtable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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,6 +25,7 @@ #ifndef SHARE_CLASSFILE_COMPACTHASHTABLE_HPP #define SHARE_CLASSFILE_COMPACTHASHTABLE_HPP +#include "cds/aotCompressedPointers.hpp" #include "cds/cds_globals.hpp" #include "oops/array.hpp" #include "oops/symbol.hpp" @@ -123,6 +124,9 @@ public: ~CompactHashtableWriter(); void add(unsigned int hash, u4 encoded_value); + void add(unsigned int hash, AOTCompressedPointers::narrowPtr encoded_value) { + add(hash, cast_to_u4(encoded_value)); + } void dump(SimpleCompactHashtable *cht, const char* table_name); private: @@ -371,11 +375,11 @@ public: // // OffsetCompactHashtable -- This is used to store many types of objects // in the CDS archive. On 64-bit platforms, we save space by using a 32-bit -// offset from the CDS base address. +// narrowPtr from the CDS base address. template -inline V read_value_from_compact_hashtable(address base_address, u4 offset) { - return (V)(base_address + offset); +inline V read_value_from_compact_hashtable(address base_address, u4 narrowp) { + return AOTCompressedPointers::decode_not_null(cast_from_u4(narrowp), base_address); } template < diff --git a/src/hotspot/share/classfile/symbolTable.cpp b/src/hotspot/share/classfile/symbolTable.cpp index c49aa10fa0d..20aa7f0776d 100644 --- a/src/hotspot/share/classfile/symbolTable.cpp +++ b/src/hotspot/share/classfile/symbolTable.cpp @@ -22,6 +22,7 @@ * */ +#include "cds/aotCompressedPointers.hpp" #include "cds/archiveBuilder.hpp" #include "cds/cdsConfig.hpp" #include "cds/dynamicArchive.hpp" @@ -690,7 +691,7 @@ void SymbolTable::copy_shared_symbol_table(GrowableArray* symbols, assert(fixed_hash == hash_symbol((const char*)sym->bytes(), sym->utf8_length(), false), "must not rehash during dumping"); sym->set_permanent(); - writer->add(fixed_hash, builder->buffer_to_offset_u4((address)sym)); + writer->add(fixed_hash, AOTCompressedPointers::encode_not_null(sym)); } } diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index afc190c36cf..cfb20412ab8 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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,6 +25,7 @@ #include "cds/aotClassFilter.hpp" #include "cds/aotClassLocation.hpp" +#include "cds/aotCompressedPointers.hpp" #include "cds/aotLogging.hpp" #include "cds/aotMetaspace.hpp" #include "cds/archiveBuilder.hpp" @@ -1282,11 +1283,10 @@ unsigned int SystemDictionaryShared::hash_for_shared_dictionary(address ptr) { class CopySharedClassInfoToArchive : StackObj { CompactHashtableWriter* _writer; bool _is_builtin; - ArchiveBuilder *_builder; public: CopySharedClassInfoToArchive(CompactHashtableWriter* writer, bool is_builtin) - : _writer(writer), _is_builtin(is_builtin), _builder(ArchiveBuilder::current()) {} + : _writer(writer), _is_builtin(is_builtin) {} void do_entry(InstanceKlass* k, DumpTimeClassInfo& info) { if (!info.is_excluded() && info.is_builtin() == _is_builtin) { @@ -1299,11 +1299,10 @@ public: Symbol* name = info._klass->name(); name = ArchiveBuilder::current()->get_buffered_addr(name); hash = SystemDictionaryShared::hash_for_shared_dictionary((address)name); - u4 delta = _builder->buffer_to_offset_u4((address)record); if (_is_builtin && info._klass->is_hidden()) { // skip } else { - _writer->add(hash, delta); + _writer->add(hash, AOTCompressedPointers::encode_not_null(record)); } if (log_is_enabled(Trace, aot, hashtables)) { ResourceMark rm; diff --git a/src/hotspot/share/include/cds.h b/src/hotspot/share/include/cds.h index a7bc896172c..76de42db755 100644 --- a/src/hotspot/share/include/cds.h +++ b/src/hotspot/share/include/cds.h @@ -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 @@ -40,7 +40,7 @@ #define CDS_DYNAMIC_ARCHIVE_MAGIC 0xf00baba8 #define CDS_PREIMAGE_ARCHIVE_MAGIC 0xcafea07c #define CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION 13 -#define CURRENT_CDS_ARCHIVE_VERSION 19 +#define CURRENT_CDS_ARCHIVE_VERSION 20 typedef struct CDSFileMapRegion { int _crc; // CRC checksum of this region. diff --git a/src/hotspot/share/oops/trainingData.cpp b/src/hotspot/share/oops/trainingData.cpp index 1a16fd70e44..f52c22ad38a 100644 --- a/src/hotspot/share/oops/trainingData.cpp +++ b/src/hotspot/share/oops/trainingData.cpp @@ -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 @@ -22,6 +22,7 @@ * */ +#include "cds/aotCompressedPointers.hpp" #include "cds/cdsConfig.hpp" #include "ci/ciEnv.hpp" #include "ci/ciMetadata.hpp" @@ -512,8 +513,7 @@ void TrainingData::dump_training_data() { #endif // ASSERT td = ArchiveBuilder::current()->get_buffered_addr(td); uint hash = TrainingData::Key::cds_hash(td->key()); - u4 delta = ArchiveBuilder::current()->buffer_to_offset_u4((address)td); - writer.add(hash, delta); + writer.add(hash, AOTCompressedPointers::encode_not_null(td)); } writer.dump(&_archived_training_data_dictionary_for_dumping, "training data dictionary"); } diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index d426fd31a43..ae3835dd344 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -22,9 +22,11 @@ * */ +#include "cds/aotCompressedPointers.hpp" #include "cds/archiveBuilder.hpp" #include "cds/archiveUtils.inline.hpp" #include "classfile/classLoader.hpp" +#include "classfile/compactHashtable.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/stringTable.hpp" #include "classfile/vmClasses.hpp" @@ -2933,8 +2935,7 @@ public: assert(buffered_entry != nullptr,"sanity check"); uint hash = fp->compute_hash(); - u4 delta = _builder->buffer_to_offset_u4((address)buffered_entry); - _writer->add(hash, delta); + _writer->add(hash, AOTCompressedPointers::encode_not_null(buffered_entry)); if (lsh.is_enabled()) { address fp_runtime_addr = (address)buffered_fp + ArchiveBuilder::current()->buffer_to_requested_delta(); address entry_runtime_addr = (address)buffered_entry + ArchiveBuilder::current()->buffer_to_requested_delta(); diff --git a/src/hotspot/share/runtime/sharedRuntime.hpp b/src/hotspot/share/runtime/sharedRuntime.hpp index 11bd39c839f..a026a4b7d69 100644 --- a/src/hotspot/share/runtime/sharedRuntime.hpp +++ b/src/hotspot/share/runtime/sharedRuntime.hpp @@ -25,7 +25,6 @@ #ifndef SHARE_RUNTIME_SHAREDRUNTIME_HPP #define SHARE_RUNTIME_SHAREDRUNTIME_HPP -#include "classfile/compactHashtable.hpp" #include "code/codeBlob.hpp" #include "code/vmreg.hpp" #include "interpreter/linkResolver.hpp" @@ -38,6 +37,7 @@ class AdapterHandlerEntry; class AdapterFingerPrint; class MetaspaceClosure; +class SerializeClosure; class vframeStream; // Runtime is the base class for various runtime interfaces diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index f65a3441bf4..1bbef8537ff 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -22,6 +22,7 @@ * */ +#include "cds/aotCompressedPointers.hpp" #include "cds/filemap.hpp" #include "classfile/classLoaderDataGraph.hpp" #include "classfile/javaClasses.hpp" @@ -762,7 +763,7 @@ CDS_ONLY(nonstatic_field(FileMapInfo, _header, FileMapHeader*)) \ CDS_ONLY( static_field(FileMapInfo, _current_info, FileMapInfo*)) \ CDS_ONLY(nonstatic_field(FileMapHeader, _regions[0], CDSFileMapRegion)) \ - CDS_ONLY(nonstatic_field(FileMapHeader, _cloned_vtables_offset, size_t)) \ + CDS_ONLY(nonstatic_field(FileMapHeader, _cloned_vtables, AOTCompressedPointers::narrowPtr)) \ CDS_ONLY(nonstatic_field(FileMapHeader, _mapped_base_address, char*)) \ CDS_ONLY(nonstatic_field(CDSFileMapRegion, _mapped_base, char*)) \ CDS_ONLY(nonstatic_field(CDSFileMapRegion, _used, size_t)) \ @@ -1203,6 +1204,7 @@ \ /* all enum types */ \ \ + declare_integer_type(AOTCompressedPointers::narrowPtr) \ declare_integer_type(Bytecodes::Code) \ declare_integer_type(InstanceKlass::ClassState) \ declare_integer_type(JavaThreadState) \ diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java index 94200e31b7e..14d8af58e4d 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java @@ -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 @@ -97,10 +97,12 @@ public class FileMapInfo { headerObj = VMObjectFactory.newObject(FileMapHeader.class, header); // char* mapped_base_address = header->_mapped_base_address - // size_t cloned_vtable_offset = header->_cloned_vtable_offset + // narrowPtr cloned_vtable_narrowPtr = header->_cloned_vtable_offset + // size_t cloned_vtable_offset = AOTCompressedPointers::get_byte_offset(cloned_vtable_narrowPtr); // CppVtableInfo** vtablesIndex = mapped_base_address + cloned_vtable_offset; mapped_base_address = get_AddressField(FileMapHeader_type, header, "_mapped_base_address"); - long cloned_vtable_offset = get_CIntegerField(FileMapHeader_type, header, "_cloned_vtables_offset"); + long cloned_vtable_narrowPtr = get_CIntegerField(FileMapHeader_type, header, "_cloned_vtables"); + long cloned_vtable_offset = cloned_vtable_narrowPtr; // Currently narrowPtr is the same as offset vtablesIndex = mapped_base_address.addOffsetTo(cloned_vtable_offset); // CDSFileMapRegion* rw_region = &header->_region[rw];