On Wed, 5 Aug 2026 09:16:31 GMT, Marc Chevalier <[email protected]> wrote:
>> This PR replaces the Valhalla draft PR >> https://github.com/openjdk/valhalla/pull/2642, which was not integrated due >> to the code freeze immediately before the Valhalla mainline integration. >> >> --------- >> >> It is conceptually very similar to acmp: it has two parts. >> >> # Static Expansion >> >> If the operand of `identityHashCode` is known at compile-time, we can >> basically inline the implementation of >> `ValueObjectMethods.valueObjectHashCode`. There are a few points worth >> noting. >> 1. The seed of the hash is the hash of the mirror class object. That object >> is not a value object, but an identity class. We look in the header of the >> said class whether it was cached already, which is very likely. Otherwise, >> we give up the static expansion: it is not worth replacing a call with a >> call. >> 2. Oops are hell. We don't expand when oops are involved. >> 3. The runtime implementation performs some unsafe gets to get all pieces of >> a segment in a simple, greedy way. Which means that in the case we have a >> value class made of 2 `int`, the likely outcome is that it would get both at >> once with a single call to `getLong`. This is fine, we can do that, but we >> need to mark the access as mismatch and unsafe (but aligned, since the acmp >> maps are smartly done). But in the case we have a class made of a single >> `int`, it would be unfortunate to mark the `getInt` access as mismatch since >> it prevents some optimizations. So if we are getting exactly a field, we >> detect it, and we mark the load as non-mismatch (match?). >> >> # Fast Path >> >> This supports only objects with a simple shape: one segment of data, being >> 1, 2, 4 or 8-byte long, which is enough to cover many migrated classes (but >> not dates for instance). This feature is morally very similar to the acmp >> fast path. It is controlled by the diagnostic flag `UseHashcodeFastPath`. >> Alike acmp, we need to sabotage the fast path in case we can do a static >> expansion later. >> >> I can only suggest you take a look at `inlineKlass.hpp` on how that works. >> >> # Benchmarking >> >> Microbenchmarking is rather unsurprising: >> - haven't changed: >> - `null` was and is still fast (1-2ns) >> - hashcode cached in the header was and is still fast (2ns) >> - identity objects without cached hashcode are not too slow, and still >> aren't (20-25ns) >> - known at compile time (60-70ns): >> - value objects with oops >> - unknown at compile time (60-70ns): >> - value objects with sizes that are not 1, 2, 4 or 8 >> - value objects with oops >> - ... > > Marc Chevalier has updated the pull request incrementally with one additional > commit since the last revision: > > unifying I've changed a bit how the big endian version works, using also shifts, but 2 instead of one. This allows to share more core than comment. This way, we always get our narrowed integer after an arithmetic shift right, so mathematical value should be preserved. ------------- PR Comment: https://git.openjdk.org/jdk/pull/32144#issuecomment-5190207601
