RFR: 8308869: C2: use profile data in subtype checks when profile has more than one class [v3]
Tobias Hartmann
thartmann at openjdk.org
Thu Jun 15 05:15:15 UTC 2023
On Tue, 13 Jun 2023 14:29:42 GMT, Roland Westrelin <roland at openjdk.org> wrote:
>> In this simple micro benchmark:
>>
>> https://github.com/franz1981/java-puzzles/blob/main/src/main/java/red/hat/puzzles/polymorphism/RequireNonNullCheckcastScalability.java#L70
>>
>> Performance drops sharply with polluted profile:
>>
>>
>> Benchmark (typePollution) Mode Cnt Score Error Units
>> RequireNonNullCheckcastScalability.isDuplicated1 false thrpt 10 1453.372 ± 24.919 ops/us
>>
>>
>> to:
>>
>>
>> Benchmark (typePollution) Mode Cnt Score Error Units
>> RequireNonNullCheckcastScalability.isDuplicated1 true thrpt 10 28.579 ± 2.280 ops/us
>>
>>
>> The test has 2 type checks to 2 different interfaces so caching with
>> `secondary_super_cache` doesn't help.
>>
>> The micro-benchmark only uses 2 different concrete classes
>> (`DuplicatedContext` and `NonDuplicatedContext`) and they are recorded
>> in profile data at the type checks. But c2 only take advantage of
>> profile data at type checks if they report a single class.
>>
>> What I propose is that the full blown type check expanded in
>> `Phase::gen_subtype_check()` takes advantage of profile data. So in
>> the case of the micro benchmark, before checking the
>> `secondary_super_cache`, generated code checks whether the object
>> being type checked is a `DuplicatedContext` or a
>> `NonDuplicatedContext`.
>>
>> This works fairly well on this micro benchmark:
>>
>>
>> Benchmark (typePollution) Mode Cnt Score Error Units
>> RequireNonNullCheckcastScalability.isDuplicated1 true thrpt 10 871.224 ± 20.750 ops/us
>>
>>
>> It also scales much better if there are multiple threads running the
>> same test (`secondary_super_cache` doesn't scale well: see
>> JDK-8180450).
>>
>> Now if the micro-benchmark is changed according to the comment:
>>
>> https://github.com/franz1981/java-puzzles/blob/d2d60af3d0dfe7a2567807395138edcb1d1c24f5/src/main/java/red/hat/puzzles/polymorphism/RequireNonNullCheckcastScalability.java#L62
>>
>> so the type check hits in the `secondary_super_cache`, the current
>> code performs much better:
>>
>>
>> Benchmark (typePollution) Mode Cnt Score Error Units
>> RequireNonNullCheckcastScalability.isDuplicated1 true thrpt 10 871.224 ± 20.750 ops/us
>>
>>
>> but leveraging profiling as explained above performs even better:
>>
>>
>> Benchmark ...
>
> Roland Westrelin has updated the pull request incrementally with one additional commit since the last revision:
>
> review
Impressive work, Roland!
I did not review the code in detail yet but here are some failures from preliminary testing:
`applications/ctw/modules/java_base_2.java` and some other CTW tests fails on AArch64:
# Internal Error (/open/src/hotspot/cpu/aarch64/assembler_aarch64.hpp:548), pid=60565, tid=30979
# assert(offset_ok_for_immed(offset(), size)) failed: must be, was: 32776, 3
Current CompileTask:
C1: 330461 92946 b 3 sun.security.tools.keytool.Resources::<clinit> (5678 bytes)
Stack: [0x000000016cc14000,0x000000016ce17000], sp=0x000000016ce13ed0, free space=2047k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.dylib+0x1385054] VMError::report_and_die(int, char const*, char const*, char*, Thread*, unsigned char*, void*, void*, char const*, int, unsigned long)+0x4bc (assembler_aarch64.hpp:548)
V [libjvm.dylib+0x13859f0] VMError::report_and_die(Thread*, void*, char const*, int, char const*, char const*, char*)+0x40
V [libjvm.dylib+0x6a9518] report_vm_error(char const*, int, char const*, char const*, ...)+0x6c
V [libjvm.dylib+0x112b08] Address::encode(Instruction_aarch64*) const+0x230
V [libjvm.dylib+0x1127d4] Assembler::ld_st2(Register, Address const&, int, int, int)+0x258
V [libjvm.dylib+0x42634c] LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck*)+0x6f0
V [libjvm.dylib+0x412f44] LIR_OpTypeCheck::emit_code(LIR_Assembler*)+0x20
V [libjvm.dylib+0x41b7fc] LIR_Assembler::emit_lir_list(LIR_List*)+0x1f4
V [libjvm.dylib+0x41bae8] LIR_Assembler::emit_block(BlockBegin*)+0x154
V [libjvm.dylib+0x41b914] LIR_Assembler::emit_code(BlockList*)+0xa4
V [libjvm.dylib+0x3d0708] Compilation::emit_code_body()+0x150
V [libjvm.dylib+0x3d1234] Compilation::compile_java_method()+0x39c
V [libjvm.dylib+0x3d15a4] Compilation::compile_method()+0x128
V [libjvm.dylib+0x3d1b18] Compilation::Compilation(AbstractCompiler*, ciEnv*, ciMethod*, int, BufferBlob*, bool, DirectiveSet*)+0x1e8
V [libjvm.dylib+0x3d45d0] Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0x254
V [libjvm.dylib+0x620750] CompileBroker::invoke_compiler_on_method(CompileTask*)+0xa0c
V [libjvm.dylib+0x61fa84] CompileBroker::compiler_thread_loop()+0x3c8
V [libjvm.dylib+0xa26908] JavaThread::thread_main_inner()+0x334
V [libjvm.dylib+0x12b0764] Thread::call_run()+0x134
V [libjvm.dylib+0x102317c] thread_native_entry(Thread*)+0x160
C [libsystem_pthread.dylib+0x706c] _pthread_start+0x94
`compiler/jvmci/compilerToVM/ReprofileTest.java` fails with:
java.lang.AssertionError: 56 != 48
at jdk.internal.vm.ci/jdk.vm.ci.hotspot.HotSpotMethodDataAccessor.getSize(HotSpotMethodDataAccessor.java:82)
at jdk.internal.vm.ci/jdk.vm.ci.hotspot.HotSpotProfilingInfo.findBCI(HotSpotProfilingInfo.java:168)
at jdk.internal.vm.ci/jdk.vm.ci.hotspot.HotSpotProfilingInfo.getExecutionCount(HotSpotProfilingInfo.java:138)
at jdk.internal.vm.ci/jdk.vm.ci.meta.ProfilingInfo.toString(ProfilingInfo.java:149)
at jdk.internal.vm.ci/jdk.vm.ci.hotspot.HotSpotProfilingInfo.toString(HotSpotProfilingInfo.java:202)
at compiler.jvmci.compilerToVM.ReprofileTest.runSanityTest(ReprofileTest.java:101)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1593)
at compiler.jvmci.compilerToVM.ReprofileTest.main(ReprofileTest.java:64)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at com.sun.javatest.regtest.agent.MainWrapper$MainTask.run(MainWrapper.java:138)
at java.base/java.lang.Thread.run(Thread.java:1583)
`serviceability/sa/ClhsdbCDSCore.java` fails with:
# SIGSEGV (0xb) at pc=0x0000000103b40894, pid=6427, tid=9987
#
# JRE version: Java(TM) SE Runtime Environment (22.0) (fastdebug build 22-internal-2023-06-14-1110599.tobias.hartmann.jdk2)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 22-internal-2023-06-14-1110599.tobias.hartmann.jdk2, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, bsd-aarch64)
# Problematic frame:
# V [libjvm.dylib+0x1308894] Unsafe_PutInt(JNIEnv_*, _jobject*, _jobject*, long, int)+0x170
Stack: [0x000000016f7f8000,0x000000016f9fb000], sp=0x000000016f9fa8c0, free space=2058k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [libjvm.dylib+0x1308894] Unsafe_PutInt(JNIEnv_*, _jobject*, _jobject*, long, int)+0x170
j jdk.internal.misc.Unsafe.putInt(Ljava/lang/Object;JI)V+0 java.base at 22-internal
j jdk.internal.misc.Unsafe.putInt(JI)V+4 java.base at 22-internal
j CrashApp.main([Ljava/lang/String;)V+5
v ~StubRoutines::call_stub 0x0000000113e5417c
V [libjvm.dylib+0x9f275c] JavaCalls::call_helper(JavaValue*, methodHandle const&, JavaCallArguments*, JavaThread*)+0x648
V [libjvm.dylib+0xae32f8] jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, JavaThread*)+0x25c
V [libjvm.dylib+0xae9c7c] jni_CallStaticVoidMethod+0x248
C [libjli.dylib+0xb2bc] JavaMain+0xd60
C [libjli.dylib+0xd4c4] ThreadJavaMain+0xc
C [libsystem_pthread.dylib+0x726c] _pthread_start+0x94
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j jdk.internal.misc.Unsafe.putInt(Ljava/lang/Object;JI)V+0 java.base at 22-internal
j jdk.internal.misc.Unsafe.putInt(JI)V+4 java.base at 22-internal
j CrashApp.main([Ljava/lang/String;)V+5
v ~StubRoutines::call_stub 0x0000000113e5417c
`serviceability/sa/TestPrintMdo.java` fails with:
stderr: [Exception in thread "main" java.lang.InternalError: 72 144 0
at jdk.hotspot.agent/sun.jvm.hotspot.oops.MethodData.dataAt(MethodData.java:282)
at jdk.hotspot.agent/sun.jvm.hotspot.oops.MethodData.nextData(MethodData.java:318)
at jdk.hotspot.agent/sun.jvm.hotspot.oops.MethodData.printDataOn(MethodData.java:359)
at jdk.hotspot.agent/sun.jvm.hotspot.CommandProcessor$19$1.visit(CommandProcessor.java:938)
at jdk.hotspot.agent/sun.jvm.hotspot.classfile.ClassLoaderData.classesDo(ClassLoaderData.java:107)
at jdk.hotspot.agent/sun.jvm.hotspot.classfile.ClassLoaderDataGraph.classesDo(ClassLoaderDataGraph.java:84)
at jdk.hotspot.agent/sun.jvm.hotspot.CommandProcessor$19.doit(CommandProcessor.java:926)
at jdk.hotspot.agent/sun.jvm.hotspot.CommandProcessor.executeCommand(CommandProcessor.java:2212)
at jdk.hotspot.agent/sun.jvm.hotspot.CommandProcessor.executeCommand(CommandProcessor.java:2182)
at jdk.hotspot.agent/sun.jvm.hotspot.CommandProcessor.run(CommandProcessor.java:2053)
at jdk.hotspot.agent/sun.jvm.hotspot.CLHSDB.run(CLHSDB.java:112)
at jdk.hotspot.agent/sun.jvm.hotspot.CLHSDB.main(CLHSDB.java:44)
at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.runCLHSDB(SALauncher.java:281)
at jdk.hotspot.agent/sun.jvm.hotspot.SALauncher.main(SALauncher.java:500)
`testlibrary_tests/ir_framework/tests/TestIRMatching.java` fails with:
1) Method "public boolean ir_framework.tests.CheckCastArray.array()" - [Failed IR rules: 2]:
* @IR rule 1: "@compiler.lib.ir_framework.IR(phase={DEFAULT}, applyIfCPUFeatureAnd={}, applyIf={}, applyIfCPUFeatureOr={}, applyIfCPUFeature={}, counts={}, applyIfAnd={}, failOn={"_#CHECKCAST_ARRAY#_"}, applyIfOr={}, applyIfNot={})"
> Phase "PrintOptoAssembly":
- failOn: Graph contains forbidden nodes:
* Constraint 1: "(((?i:cmp|CLFI|CLR).*precise \[.*:|.*(?i:mov|or).*precise \[.*:.*\\R.*(cmp|CMP|CLR)))"
- Matched forbidden node:
* cmpl R10, narrowklass: precise [java/lang/Object: 0x00007fcab601f3e8 * (java/lang/Cloneable,java/io/Serializable): :Constant:
* @IR rule 3: "@compiler.lib.ir_framework.IR(phase={DEFAULT}, applyIfCPUFeatureAnd={}, applyIf={}, applyIfCPUFeatureOr={}, applyIfCPUFeature={}, counts={}, applyIfAnd={}, failOn={"_#C#CHECKCAST_ARRAY_OF#_", "MyClasss", "_#C#CHECKCAST_ARRAY_OF#_", "Object"}, applyIfOr={}, applyIfNot={})"
> Phase "PrintOptoAssembly":
- failOn: Graph contains forbidden nodes:
* Constraint 2: "(((?i:cmp|CLFI|CLR).*precise \[.*Object:|.*(?i:mov|or).*precise \[.*Object:.*\\R.*(cmp|CMP|CLR)))"
- Matched forbidden node:
* cmpl R10, narrowklass: precise [java/lang/Object:
2) Method "public java.lang.Object[] ir_framework.tests.CheckCastArray.arrayCopy(java.lang.Object[],java.lang.Class)" - [Failed IR rules: 1]:
* @IR rule 1: "@compiler.lib.ir_framework.IR(phase={DEFAULT}, applyIfCPUFeatureAnd={}, applyIf={}, applyIfCPUFeatureOr={}, applyIfCPUFeature={}, counts={}, applyIfAnd={}, failOn={"_#CHECKCAST_ARRAYCOPY#_"}, applyIfOr={}, applyIfNot={})"
> Phase "PrintOptoAssembly":
- failOn: Graph contains forbidden nodes:
* Constraint 1: "(.*((?i:call_leaf_nofp,runtime)|CALL,\\s?runtime leaf nofp|BCTRL.*.leaf call).*checkcast_arraycopy.*)"
- Matched forbidden node:
* 1a5 call_leaf_nofp,runtime checkcast_arraycopy
-------------
PR Comment: https://git.openjdk.org/jdk/pull/14375#issuecomment-1592372554
More information about the hotspot-compiler-dev
mailing list