RFR: 8376822: UseCompactObjectHeaders: fill Klass alignment gaps in AOT cache [v2]

Johan Sjölen jsjolen at openjdk.org
Tue Feb 24 11:48:09 UTC 2026


On Mon, 23 Feb 2026 00:34:30 GMT, Ioi Lam <iklam at openjdk.org> wrote:

>> When  `UseCompactObjectHeaders` is enabled, `Klass` objects must be aligned by 1024 bytes. This leaves many gaps in the "rw" region of the AOT cache.
>> 
>> This PR manages the gaps using an `RBTree`. The gaps are sorted in ascending sizes. Gaps of the same size are sorted in ascending addresses. When allocating a small object, we try to find a suitable gap with the lowest address.
>> 
>> Because we have lots of small metaspace objects in the AOT cache, the gaps are always filled. We save abuot 5% of footprint with the JDK's default CDS archive (777KB out of 15.7MB):
>> 
>> 
>> $ java -Xshare:dump -XX:+UseCompactObjectHeaders -Xlog:aot,aot+alloc=trace | grep -i gap | tail -2
>> [0.407s][trace][aot,alloc] 8 bytes @ 0x716e804623f0 in a gap of 8 bytes (used gaps 10293 times, remain gap = 0 bytes in 0 blocks)
>> [0.443s][info ][aot      ] Allocated 10293 objects of 777264 bytes in gaps
>> $ ls -l images/jdk/lib/server/classes_coh.jsa 
>> -rw-rw-r-- 1 iklam iklam 15704064 Feb 22 16:17 images/jdk/lib/server/classes_coh.jsa
>> 
>> 
>> Related changes
>> 
>> - Address sorting added to AOTMapLogger
>> - The null assertion in `ArchivePtrMarker::mark_pointer()` was wrong for the dynamic archive (`ptr_base()` points to the bottom of the dynamic archive, not the bottom of the AOT metaspace).
>
> Ioi Lam has updated the pull request incrementally with one additional commit since the last revision:
> 
>   moved offset != 0 check

src/hotspot/share/cds/archiveUtils.cpp line 293:

> 291: using AllocGapNode = RBNode<DumpRegion::AllocGap, Empty>;
> 292: 
> 293: class DumpRegion::AllocGapTree : public RBTreeCHeap<AllocGap, Empty, AllocGapCmp, mtClassShared> {

Is there a reason that we're subclassing here instead of having a RBTreeCHeap as a member of this class?

src/hotspot/share/cds/archiveUtils.cpp line 310:

> 308:   }
> 309: 
> 310:   char* allocate_from_gap(size_t num_bytes) {

`precond` that `num_bytes` is divisble by `SharedSpaceObjectAlignment`?

src/hotspot/share/cds/archiveUtils.cpp line 318:

> 316:     AllocGapNode* node = closest_ge(target);
> 317:     if (node == nullptr) {
> 318:       return nullptr; // Didn't find any useable gap.

Sp nit: 'usable' is preferred

src/hotspot/share/cds/archiveUtils.cpp line 373:

> 371:   if (alignment == SharedSpaceObjectAlignment && type != MetaspaceClosureType::SymbolType) {
> 372:     // The addresses of Symbols must be in the same order as they are in ArchiveBuilder::SourceObjList.
> 373:     // If we put them in gaps, their orders will change.

"orders" -> "order"

src/hotspot/share/utilities/rbTree.hpp line 437:

> 435:   if (a > b) return RBTreeOrdering::GT;
> 436:   return RBTreeOrdering::EQ;
> 437: }

@caspernorrbin , seems OK?

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/29869#discussion_r2846236108
PR Review Comment: https://git.openjdk.org/jdk/pull/29869#discussion_r2846284198
PR Review Comment: https://git.openjdk.org/jdk/pull/29869#discussion_r2846259232
PR Review Comment: https://git.openjdk.org/jdk/pull/29869#discussion_r2846297766
PR Review Comment: https://git.openjdk.org/jdk/pull/29869#discussion_r2846442873


More information about the hotspot-dev mailing list