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