RFR: 8363998: Implement Compressed Class Pointers for 32-bit

Thomas Stuefe stuefe at openjdk.org
Sat Jul 26 18:32:32 UTC 2025


We plan to remove the uncompressed Klass pointer mode (`-UseCompressedClassPointers`) soon. Uncompressed Klass pointers are deprecated for JDK 25, and are planned to be removed for JDK 26. For background and motivation, please refer to this discussion [1] and the description and comments in this deprecation CSR [2].

A significant roadblock for removing `-UseCompressedClassPointers` had been the ongoing existence of 32-bit. 32-bit relies on uncompressed Klass pointers. 

Now, some of us think that 32-bit ports are on their way out [3]. We already removed support for x86 with JEP 503 in JDK 25, but we still have arm32 and zero 32-bit. The usefulness of the latter is arguable, seeing that the build is broken more often than not. However, even if we do rid ourselves of 32-bit eventually, that won't happen quickly: further discussions are needed, and then we will need a proper JEP with a deprecation phase for at least one release, probably more. That is too slow - I want to get rid of `-UseCompressedClassPointers` a lot sooner than that.

Therefore, I needed to find a way to support `+UseCompressedClassPointers` on 32-bit. Alternatives would have been:
- remove `-UseCompressedClassPointers` for 64-bit, but leave it in for 32-bit. This would have greatly diminished the benefits though, since we would have to keep a lot of shared coding for the sake of 32-bit.
- Just get rid of `-UseCompressedClassPointers` and leave 32-bit brokenness to the maintainers of 32-bit ports; but that would be throwing 32-bit under the bus knowingly, and I did not want to do that.

-------

This patch adds support for `+UseCompressedClassPointers` on 32-bit in a minimally invasive way that keeps technical debt low. Additionally, the code is clearly marked and can be removed cleanly once we completely remove 32-bit support in two or three releases.

How to do this? Most is straightforward: pointers are 32-bit, so they are already "compressed". We set up narrow Klass encoding such that `base = NULL` and `shift = 0`; the entire 32-bit address space is therefore our encoding range. Since narrowKlass is 32-bit, that works. We now behave exactly as we would behave on 64-bit in "unscaled" encoding mode, with encoding and decoding being no-ops.

We also don't change the object layout; header stays the same - Klass is stored in the second word of the header as before, regardless of whether you interpret the word as `narrowKlass` or `Klass*`.

We also don't need to make many changes in terms of storage. Today, on 32-bit systems, Klass structures live inside the non-Klass metaspace regions, which are scattered arbitrarily throughout the address space. On 64-bit, we need a class space to confine Klass structures to the encoding range; here, where the encoding range encompasses the entire address space, we don't need a class space. Note that should we ever consider supporting some form of compact object headers on 32-bit - god forbid that ever happens - we need to revise this design (+COH, aka "Lilliput 1", would be pointless on 32-bit anyway).

However, the devil was in the details: a lot of code relied on the assumption that `+UseCompressedClassPointers` means "we run with a class space". That assumption now is broken, since we run with narrow Klass encoding, but without class space. The code also often assumed that `+UseCompressedClassPointers` == 64-bit, and that is not wrong, too. These things needed fixing. I introduced a new macro "NEEDS_CLASS_SPACE" which is `1` if the platform requires a class space for `+UseCompressedClassPointers`. This is `1` on 64-bit, `0` on 32-bit. I did not just use `#ifdef _LP64` since I wanted to mark these sections in the code clearly. We may need to revisit them at a later time.

CDS: CDS can continue to function as it did before on 32-bit, by being oblivious to the existence of class space and narrow Klass encoding. It simply places the CDS archive anywhere, just as it did before; Klass structures within it will continue to work. However, note that we still won't support Heap archive sections for CDS: even though we now run with `+UseCompressedClassPointers`, the placement of CDS archive and all other Klass-carrying metaspace sections is still random, so we still cannot encode narrow Klass pointers into the objects at dump time.

This is how things are reported in VM.info now - note how both klass range and encoding range cover almost all of the address space, minus small buffer areas at the bottom (below addressable space) and the top (one page):


---------------  P R O C E S S  ---------------

CDS archive(s) mapped at: [0xb6110000-0xb6c00000-0xb6c00000), size 11468800, SharedBaseAddress: 0xb6110000, ArchiveRelocationMode: 1.
UseCompressedClassPointers 1, UseCompactObjectHeaders 0
Narrow klass pointer bits 32, Max shift 0
Narrow klass base: 0x00000000, Narrow klass shift: 0
Encoding Range: [0x00000000 - 0xfffff000), (4294963200 bytes)
Klass Range:    [0x01000000 - 0xfffff000), (4278185984 bytes)
Klass ID Range:  [16777216 - 4294963193) (4278185977)
Protection zone: [0x00000000 - 0x01000000), (16777216 bytes)

-------

Testing:

All of this was developed and tested on arm on a Raspberry. I made sure gtests run cleanly through, I ran a couple of tests from the Metaspace suite, and tested spring petclinic. All of this with C1/C2 and CDS active. Works fine now with `+UseCompressedClassPointers`.

I did not test Zero 32-bit, nor do I intent to. This works well enough on 32-bit now to survive casual use and as many tests as I cared to throw at my poor old Raspberry. This is enough for me. Any further fixes will have to be done by those responsible for maintaining 32-bit ports, and be done in follow-up RFEs.

-------

[1] [hotspot-dev: Deprecate -UseCompressedClassPointers?](https://mail.openjdk.org/pipermail/hotspot-dev/2025-February/101023.html)
[2] [Deprecation CSR](https://bugs.openjdk.org/browse/JDK-8350754)
[3] [jdk-dev: The future of 32-bit?](https://mail.openjdk.org/pipermail/jdk-dev/2025-April/009889.html)

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

Commit messages:
 - fix gtests on arm32
 - Fix display of encoding range
 - copyrights
 - cosmetics
 - some cleanups in arm cpu coding
 - ARM32 helloworld now works
 - wip
 - oops/compressedKlass
 - oops/ObjLayout
 - Start

Changes: https://git.openjdk.org/jdk/pull/26491/files
  Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=26491&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8363998
  Stats: 185 lines in 17 files changed: 114 ins; 45 del; 26 mod
  Patch: https://git.openjdk.org/jdk/pull/26491.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/26491/head:pull/26491

PR: https://git.openjdk.org/jdk/pull/26491


More information about the hotspot-dev mailing list