On Wed, 16 Sep 2026 14:34:57 GMT, Frederic Parain <[email protected]> wrote:

>> src/java.base/share/classes/java/lang/runtime/ValueObjectMethods.java line 
>> 176:
>> 
>>> 174:         // to enable caching. The identity hash of the value class 
>>> distinguishes
>>> 175:         // different value classes and is easy for the compiler to 
>>> fetch.
>>> 176:         return (result & 0x7fffffff) == 0 ? typeHash : result;
>> 
>> We need to check if the hash that will be retrieved later is null or not, 
>> but between this return and the storage, the hash is masked to fit in the 
>> cache of the mark word, which is at most 31 bits. So, 0x80_00_00_00 will 
>> also be cut into a 0 hash.
>> 
>> I made this masking here in a quick and dirty way: it assumes we will keep 
>> 31 bits, which I think it wrong at least on 32 bits architectures (if I 
>> understand the comments about the mark word correctly). Yet, I didn't manage 
>> to get the mask from the VM as we do in Mark.java. So, this is to be fixed 
>> by somebody who knows this side of JDK better than me.
>> 
>> If we omit the masking here (and we do `result == 0`), then the test 
>> `test/hotspot/jtreg/compiler/valhalla/valuetypes/TestHashcodeFastPath.java` 
>> fails. Specifically the first instance of the assert
>> 
>> Asserts.assertNE(h(would_have_zero_hashcode1), 0);
>> 
>> since it actually runs fully in the interpreter (`h` is excluded and the 
>> enclosing method is marked with `@Run`, so not compiled).
>> 
>> Another option is not to do the filtering here, but somewhere around
>> https://github.com/openjdk/jdk/blob/e45a4e7a8514c1193e2ff92ead04630d93a760ec/src/hotspot/share/prims/jvm.cpp#L815
>> in the caller, where we are in the C++ world and accessing the mask is easy 
>> (but there, getting `System.identityHashCode(type)` is harder).
>
> Here's the markword format given in markWord.hpp:
> 
> // Bit-format of an object header (most significant first, big endian layout 
> below):
> //
> //  32 bits:
> //  --------
> //             hash:25              age:4  self-fwd:1  lock:2
> //
> //  64 bits (without compact headers):
> //  ----------------------------------
> //  unused:22  hash:31  valhalla:4  age:4  self-fwd:1  lock:2
> //
> //  64 bits (with compact headers):
> //  -------------------------------
> //  klass:22   hash:31  valhalla:4  age:4  self-fwd:1  lock:2

Related relevant code include:
- where we set the hash in the markword:
https://github.com/openjdk/jdk/blob/ea04454135e2e431d3518261dc0e68064d8f4a5b/src/hotspot/share/prims/jvm.cpp#L827-L828
- the code doing it:
https://github.com/openjdk/jdk/blob/ea04454135e2e431d3518261dc0e68064d8f4a5b/src/hotspot/share/oops/markWord.hpp#L297-L301
- the code getting the hash:
https://github.com/openjdk/jdk/blob/ea04454135e2e431d3518261dc0e68064d8f4a5b/src/hotspot/share/oops/markWord.hpp#L269-L272


Basically, it's just masking and shifting.

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

PR Review Comment: https://git.openjdk.org/jdk/pull/32660#discussion_r4027925966

Reply via email to