Another option is to make the internal stored hash a long and then the first 
part can be used to track whether it has been computed and then just cast the 
long to an int to retrieve the value. If it has been computed, one bit is 
flipped in the upper 32 bits. Then a read is just a single long read + int 
cast, and a write is just the computed hashCode plus an OR.

The main downside of course is that it adds 3 bytes to each string (of course 
alignment and padding etc might change that overhead).


@Stable private long hash; // Default to 0

public int hashCode() {
    long h = hash;
    if ((h & ~(1L << 32)) == 0) // if calculated bit is not set, the calculate
        hash = h = (1L << 32) | (isLatin1()
            ? StringLatin1.hashCode(value)
            : StringUTF16.hashCode(value));
    return (int)h;
}


Cheers,
√


Viktor Klang
Software Architect, Java Platform Group
Oracle
________________________________
From: core-libs-dev <core-libs-dev-r...@openjdk.org> on behalf of 
fo...@univ-mlv.fr <fo...@univ-mlv.fr>
Sent: Friday, 11 April 2025 11:04
To: Chen Liang <chen.l.li...@oracle.com>
Cc: core-libs-dev <core-libs-dev@openjdk.org>
Subject: Re: java.lang.String hashCode and @Stable ?



________________________________
From: "Chen Liang" <chen.l.li...@oracle.com>
To: "Remi Forax" <fo...@univ-mlv.fr>, "core-libs-dev" 
<core-libs-dev@openjdk.org>
Sent: Thursday, April 10, 2025 8:16:39 PM
Subject: Re: java.lang.String hashCode and @Stable ?
Hi Remi,
I think this is probably due to these fields being added too early - the stable 
on string byte array is also added lately.

That said, I don't think adding stable on both fields completely resolves the 
constant folding issues around string hash code. The current code can only 
constant fold non-zero hash; a zero hash is folded to a read to hash field, 
which cannot fold further because it's a read of the default value from a 
stable field.
A solution may be to change hashIsZero to a byte field indicating 3 states - 
hash unset (0), hash computed to field, hash computed and is zero. This allows 
the zero hash to constant fold as well at the cost of non-constant hash access 
performance, as now there are two reads.

yes,
and obviously, it has to be done without introducing a perf regression if the 
String is not constant folded.

I think it would be nice to try that as a follow-up of JDK-8354300.


Also this reminds me of https://bugs.openjdk.org/browse/JDK-8332249 - maybe 
Method::hashCode was hot because the string hash code could not fold.

Usually in framework like Spring, Method are cached either by the framework or 
by java.lang.Class own cache so the Method itself is rarely a constant.


Regards, Chen

regards,
Rémi

________________________________
From: core-libs-dev <core-libs-dev-r...@openjdk.org> on behalf of Remi Forax 
<fo...@univ-mlv.fr>
Sent: Thursday, April 10, 2025 4:18 AM
To: core-libs-dev <core-libs-...@openjdk.java.net>
Subject: java.lang.String hashCode and @Stable ?

Question,
why String.hash and String.hashIsZero are not declared @Stable ?

regards,
Rémi

Reply via email to