-
Notifications
You must be signed in to change notification settings - Fork 5.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
8353237: [AArch64] Incorrect result of VectorizedHashCode intrinsic on Cortex-A53 #24489
base: master
Are you sure you want to change the base?
Conversation
👋 Welcome back avoitylov! A progress list of the required criteria for merging this PR into |
❗ This change is not yet ready to be integrated. |
@voitylov How can this bug be reproduced? Can you write a reproducer to attach to this PR? Also: the title sounds a bit generic: "on some hardware" ... is it all aarch64, or something more specific? You could change the PR title. |
I define a Java source file like this: // A.java
public class A {
public static void main(String[] args) {
System.out.println("HelloWorld!");
}
} Then I build its class file on my computer ( First, the good behaviors: # Load A.class:
$ jdk-25/bin/java A
HelloWorld!
# Compile A.java then load it:
$ jdk-25/bin/java -XX:+UnlockDiagnosticVMOptions -XX:-UseVectorizedHashCodeIntrinsic A.java
HelloWorld! Then, the wrong behavior: $ jdk-25/bin/java A.java
An exception has occurred in the compiler ((version info not available)). Please file a bug against the Java compiler via the Java bug reporting page (https://bugreport.java.com) after checking the Bug Database (https://bugs.java.com) for duplicates. Include your program, the following diagnostic, and the parameters passed to the Java compiler in your report. Thank you.
java.lang.NoClassDefFoundError: com/sun/tools/javac/jvm/ClassReader$AttributeReader
at jdk.compiler/com.sun.tools.javac.jvm.ClassReader.initAttributeReaders(ClassReader.java:885)
at jdk.compiler/com.sun.tools.javac.jvm.ClassReader.<init>(ClassReader.java:308)
at jdk.compiler/com.sun.tools.javac.jvm.ClassReader.instance(ClassReader.java:270)
at jdk.compiler/com.sun.tools.javac.code.ClassFinder.<init>(ClassFinder.java:186)
at jdk.compiler/com.sun.tools.javac.code.ClassFinder.instance(ClassFinder.java:178)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.<init>(JavaCompiler.java:400)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.instance(JavaCompiler.java:129)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.<init>(JavacProcessingEnvironment.java:209)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.instance(JavacProcessingEnvironment.java:194)
at jdk.compiler/com.sun.tools.javac.api.BasicJavacTask.initPlugins(BasicJavacTask.java:218)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.prepareCompiler(JavacTaskImpl.java:204)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.parseInternal(JavacTaskImpl.java:257)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.invocationHelper(JavacTaskImpl.java:152)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.parse(JavacTaskImpl.java:248)
at jdk.compiler/com.sun.tools.javac.launcher.ProgramDescriptor.of(ProgramDescriptor.java:71)
at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.run(SourceLauncher.java:132)
at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.main(SourceLauncher.java:76)
Caused by: java.lang.ClassNotFoundException: com.sun.tools.javac.jvm.ClassReader$AttributeReader
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:490)
... 17 more
Exception in thread "main" java.lang.IllegalStateException: java.lang.NoClassDefFoundError: com/sun/tools/javac/jvm/ClassReader$AttributeReader
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.parse(JavacTaskImpl.java:252)
at jdk.compiler/com.sun.tools.javac.launcher.ProgramDescriptor.of(ProgramDescriptor.java:71)
at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.run(SourceLauncher.java:132)
at jdk.compiler/com.sun.tools.javac.launcher.SourceLauncher.main(SourceLauncher.java:76)
Caused by: java.lang.NoClassDefFoundError: com/sun/tools/javac/jvm/ClassReader$AttributeReader
at jdk.compiler/com.sun.tools.javac.jvm.ClassReader.initAttributeReaders(ClassReader.java:885)
at jdk.compiler/com.sun.tools.javac.jvm.ClassReader.<init>(ClassReader.java:308)
at jdk.compiler/com.sun.tools.javac.jvm.ClassReader.instance(ClassReader.java:270)
at jdk.compiler/com.sun.tools.javac.code.ClassFinder.<init>(ClassFinder.java:186)
at jdk.compiler/com.sun.tools.javac.code.ClassFinder.instance(ClassFinder.java:178)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.<init>(JavaCompiler.java:400)
at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.instance(JavaCompiler.java:129)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.<init>(JavacProcessingEnvironment.java:209)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.instance(JavacProcessingEnvironment.java:194)
at jdk.compiler/com.sun.tools.javac.api.BasicJavacTask.initPlugins(BasicJavacTask.java:218)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.prepareCompiler(JavacTaskImpl.java:204)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.parseInternal(JavacTaskImpl.java:257)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.invocationHelper(JavacTaskImpl.java:152)
at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.parse(JavacTaskImpl.java:248)
... 3 more
Caused by: java.lang.ClassNotFoundException: com.sun.tools.javac.jvm.ClassReader$AttributeReader
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:490)
... 17 more For reference: $ jdk-25/bin/java -version
openjdk version "25-ea" 2025-09-16
OpenJDK Runtime Environment (build 25-ea+16-1816)
OpenJDK 64-Bit Server VM (build 25-ea+16-1816, mixed mode, sharing)
$ uname -a
Linux rock64-aarch64-2 6.13.5-3-aarch64-ARCH #1 SMP PREEMPT_DYNAMIC Wed Mar 5 18:09:23 MST 2025 aarch64 GNU/Linux
$ cat /proc/cpuinfo
processor : 0
BogoMIPS : 48.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4
processor : 1
BogoMIPS : 48.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4
processor : 2
BogoMIPS : 48.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4
processor : 3
BogoMIPS : 48.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4
$ cat /sys/devices/system/cpu/cpu0/regs/identification/revidr_el1
0x0000000000000180
# The erratum 835769 for Cortex A53 is fixed on this CPU:
$ python3
>>> (0x0000000000000180 >> 7) & 1
1 |
I'm saying that a simple HelloWorld reproduces the issue every time on the Rock64. |
The title now reflects the concrete core affected by the issue. The description now lists a concrete jtreg test that can be used to reproduce the issue on that core, but like described previously, any hotspot jtreg test used to fail on that core before the fix. JDK 24 is basically DOA on Cortex-A53. |
Before:
After:
|
I see that the hashcode acceleration is a recent addition, so this doesn't need backports. I suppose the interesting question is how long we intend to support Cortex A53 for. When you build HotSpot for Cortex A53, do you use the |
It will have to be backported to 21u, as the intrinsic is already in 21u-dev. I'll do that once we address 8353237 in jdk/jdk. Our cross compiler has, among other erratum flags, Note that JDK-8079203 does not check the specific erratum flags in a processor. Instead, it adds nop based on processor type, penalizing all A53s. I could not find the history of that decision, maybe because not all A53 implementors used the erratum flags, or for the sake of simplicity. It's also consistent with a typical GCC setting. I decided not to touch this part because of that. |
Hmm. If we're going to fix this problem properly I guess we should add that flag to the build config. Maybe another PR? |
Maybe, but I'm not sure this is the right thing to enforce in the build system across the board either. For example, a cloud vendor with a big Arm fleet without A53s may find such a setting undesirable. |
I don't think there is any possibility that a big cloud vendor would notice. From what I see of GCC-generated code, added NOPs are very rare, because GCC tends to schedule loads long before uses. It's likely that there would be no difference to any GCC-generated code. |
The root of the problem is that VectorizedHashCode intrinsic introduced by JDK-8341194 is not aware of JDK-8079203. JDK-8079203 generates additional nop with madd instruction on Cortex-A53 as a workaround for Cortex-A53 erratum 835769 "AArch64 multiply-accumulate instruction might produce incorrect result". Current VectorizedHashCode intrinsic calculates byte offset to jump inside the unrolled loop code. It assumes 2 instructions per each unrolled iteration (load and madd). JDK-8079203 adds additional nop for Cortex-A53, which breaks offset calculation logic.
Current offset calculation logic is using shift instead of multiplication, power-of-2 number instructions are present in each unrolled loop iteration. To keep it simple, this fix adds one more nop into each loop iteration on Cortex-A53 in order to have 4 instruction per iteration, which is also a power-of-2. To account for that, the shift argument for offset calculation logic is increased by 1, because each loop iteration has 2 times more instructions on Cortex-A53.
This fix is tested on Raspberry Pi 3 (based on Cortex-A53) by running initially reported application and by running hotspot jtreg tests (not a single test could be run on Cortex-A53 before the fix). After the fix, the specialized test hotspot/jtreg/compiler/intrinsics/TestArraysHashCode.java passes.
The performance gain from the intrinsic is also observed on Cortex-A53 using the ArraysHashCode benchmark.
Progress
Issue
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/24489/head:pull/24489
$ git checkout pull/24489
Update a local copy of the PR:
$ git checkout pull/24489
$ git pull https://git.openjdk.org/jdk.git pull/24489/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 24489
View PR using the GUI difftool:
$ git pr show -t 24489
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/24489.diff
Using Webrev
Link to Webrev Comment