On Wed, 5 Aug 2026 09:46:05 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:
> 
>   Also a normal range for testing

src/hotspot/share/opto/inlinetypenode.cpp line 1055:

> 1053:       Node* la = make_load(offset, TypeLong::LONG, T_LONG);
> 1054:       result = kit->AddI(kit->MulI(thirty_one, result), 
> kit->ConvL2I(la));
> 1055:       result = kit->AddI(kit->MulI(thirty_one, result), 
> kit->ConvL2I(kit->URShiftL(la, kit->intcon(32))));

Note that as was suggested in 
<https://github.com/openjdk/jdk/pull/31123#discussion_r3354053360> (and 
[JDK‑8388062]), this and `ValueObjectMethods​::valueObjectHashCode(…)` should 
probably be updated to use the same computation as `Long::hashCode`.

[JDK‑8388062]: https://bugs.openjdk.org/browse/JDK-8388062

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

PR Review Comment: https://git.openjdk.org/jdk/pull/32144#discussion_r3719879854

Reply via email to