On Fri, 11 Sep 2026 07:18:40 GMT, Marc Chevalier <[email protected]> wrote:

>> The identity hash code of value objects currently can produce 0. A zero 
>> value is usually not anticipated for System.identityHashCode calls unless 
>> the argument is null; the 0 hash also cannot be cached. Thus, we should move 
>> away from the 0 hash.
>> 
>> ---------
>> - [x] I confirm that I make this contribution in accordance with the 
>> [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai).
>
> 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

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

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

Reply via email to