JDK-8278966 : two microbenchmarks tests fail "assert(!jvms->method()->has_exception_handlers()) failed: no exception handler expected" after JDK-8275638
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 17,18
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: x86_64,aarch64
  • Submitted: 2021-12-17
  • Updated: 2022-03-08
  • Resolved: 2022-01-04
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 17 JDK 18 JDK 19
17.0.4-oracleFixed 18 b30Fixed 19Fixed
Related Reports
Relates :  
Description
The following closed tests failed in the JDK18 CI:

applications/microbenchmarks/indy/Test_3.java#id20
applications/microbenchmarks/other/Test_12.java#id0

I've started this bug off as confidential because the tests are
closed. However, after triage by the Compiler team, this bug
can be change into non-confidential if appropriate.

Here's the crashing thread's stack from Test_3.java#id20:

---------------  T H R E A D  ---------------

Current thread (0x00007fd0b80b2870):  JavaThread "C2 CompilerThread3" daemon [_thread_in_native, id=25560, stack(0x00007fd0cfafb000,0x00007fd0cfbfc000)]


Current CompileTask:
C2:   1671  721   !         java.lang.invoke.LambdaForm$MH/0x0000000801028000::guardWithCatch (83 bytes)

Stack: [0x00007fd0cfafb000,0x00007fd0cfbfc000],  sp=0x00007fd0cfbf6e70,  free space=1007k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x8b26bb]  LateInlineMHCallGenerator::do_late_inline_check(Compile*, JVMState*)+0x5b
V  [libjvm.so+0x8aee8f]  CallGenerator::do_late_inline_helper()+0xadf
V  [libjvm.so+0xa8979d]  Compile::inline_incrementally_one()+0x33d
V  [libjvm.so+0xa89aff]  Compile::inline_incrementally(PhaseIterGVN&)+0x18f
V  [libjvm.so+0xa8a759]  Compile::Optimize()+0x5e9
V  [libjvm.so+0xa8d3fe]  Compile::Compile(ciEnv*, ciMethod*, int, Options, DirectiveSet*)+0x159e
V  [libjvm.so+0x8a5d24]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0x664
V  [libjvm.so+0xa9d6f8]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0xc88
V  [libjvm.so+0xa9e4b8]  CompileBroker::compiler_thread_loop()+0x648
V  [libjvm.so+0x1925aba]  JavaThread::thread_main_inner()+0x25a
V  [libjvm.so+0x192de80]  Thread::call_run()+0x100
V  [libjvm.so+0x1610214]  thread_native_entry(Thread*)+0x104


Here's the crashing stack trace from Test_12.java#id0:

---------------  T H R E A D  ---------------

Current thread (0x00007f2da4107ed0):  JavaThread "C2 CompilerThread3" daemon [_thread_in_native, id=13403, stack(0x00007f2ddc1a6000,0x00007f2ddc2a7000)]


Current CompileTask:
C2:   3828  827   !         java.lang.invoke.LambdaForm$MH/0x0000000801027800::tryFinally (77 bytes)

Stack: [0x00007f2ddc1a6000,0x00007f2ddc2a7000],  sp=0x00007f2ddc2a1e70,  free space=1007k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x8b26bb]  LateInlineMHCallGenerator::do_late_inline_check(Compile*, JVMState*)+0x5b
V  [libjvm.so+0x8aee8f]  CallGenerator::do_late_inline_helper()+0xadf
V  [libjvm.so+0xa8979d]  Compile::inline_incrementally_one()+0x33d
V  [libjvm.so+0xa89aff]  Compile::inline_incrementally(PhaseIterGVN&)+0x18f
V  [libjvm.so+0xa8a759]  Compile::Optimize()+0x5e9
V  [libjvm.so+0xa8d3fe]  Compile::Compile(ciEnv*, ciMethod*, int, Options, DirectiveSet*)+0x159e
V  [libjvm.so+0x8a5d24]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0x664
V  [libjvm.so+0xa9d6f8]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0xc88
V  [libjvm.so+0xa9e4b8]  CompileBroker::compiler_thread_loop()+0x648
V  [libjvm.so+0x1925aba]  JavaThread::thread_main_inner()+0x25a
V  [libjvm.so+0x192de80]  Thread::call_run()+0x100
V  [libjvm.so+0x1610214]  thread_native_entry(Thread*)+0x104
Comments
A pull request was submitted for review. URL: https://git.openjdk.java.net/jdk17u-dev/pull/201 Date: 2022-03-07 13:13:26 +0000
07-03-2022

Fix Request (17u): Should get backported for parity with 17.0.4-oracle together with JDK-8275638. Applies cleanly. Test has passed.
07-03-2022

The fix for this bug is in jdk-19+4-141.
05-01-2022

Changeset: e7244c19 Author: Roland Westrelin <roland@openjdk.org> Date: 2022-01-04 10:56:37 +0000 URL: https://git.openjdk.java.net/jdk/commit/e7244c19f4e24698ab074da530bf6c403f0e22cd
04-01-2022

The fix for this bug is in jdk-18+30-2023.
04-01-2022

Changeset: e7244c19 Author: Roland Westrelin <roland@openjdk.org> Date: 2022-01-04 10:56:37 +0000 URL: https://git.openjdk.java.net/jdk18/commit/e7244c19f4e24698ab074da530bf6c403f0e22cd
04-01-2022

A pull request was submitted for review. URL: https://git.openjdk.java.net/jdk18/pull/78 Date: 2022-01-04 08:15:28 +0000
04-01-2022

> Should I proceed with the RFR for the assert tweak? [~roland] yes, please.
03-01-2022

[~vlivanov] Thanks. Should I proceed with the RFR for the assert tweak?
03-01-2022

> What about Dean's concerns with custom/instrumented bytecodes? I discussed it privately with Dean and, though I'm not fond of the constraint imposed by JDK-8275638 fix (has_exception_handlers() == false), I think it's fine for now to rely on the implementation details of java.lang.invoke support in JDK. MH linkers are package-private, so it would require java.base module patching to access them from a custom class file. It would be trivial to write a jtreg which reliably triggers the assert. (There are existing white-box tests for java.lang.invoke impl which poke into its internals.) But all the normal/supported usages of MH linkers are fully controlled by the JDK and confined to DirectMethodHandle cases which don't have exception handlers. Regarding bytecode instrumentation, LambdaForms are compiled to hidden classes which can't be instrumented/modified using JVMTI: https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/invoke/MethodHandles.java#L2003 * A hidden class or interface ... * is not {@linkplain java.lang.instrument.Instrumentation#isModifiableClass(Class) * modifiable} by Java agents or tool agents using the <a href="{@docRoot}/../specs/jvmti.html"> * JVM Tool Interface</a>.
03-01-2022

[~vlivanov] Thanks. What about Dean's concerns with custom/instrumented bytecodes?
03-01-2022

(Leaving JDK-8275638 fix aside for now. I have some questions I'll ask separately.) > [~dlong] Thanks for investigating. what about this as a fix: https://github.com/rwestrel/jdk18/tree/JDK-8278966 ? Proposed assert adjustment looks reasonable.
23-12-2021

@roland, you are probably right that the problem can't be triggered with MethodHandle transformations directly. However, what about custom bytecodes from a .jasm file, or instrumented bytecodes from perhaps a JVMTI classloader hook? Maybe I'm being paranoid, but a bailout seems less risky than an assert.
23-12-2021

[~roland] So in your test case using tryFinally and catchException, it's using invokeBasic I believe, so you assert passes, but where is the null check? Do you think it's possible to create a MethodHandle with both a null check and a virtual call? [~vlivanov], what do you think?
22-12-2021

[~dlong] AFAIU, test5() is: try { test.m(); } finally { } expressed with method handles. test5() is passed either null or a non null test object so it does throw. There are a number of generated adapter methods called between test5() and m() to implement the method handle invocation. One has the linkToVirtual where the exception is thrown. One has the exception handlers. They are not the same.
22-12-2021

> is it safe to safe to assume that MethodHandles.tryFinally() and catchException() will always use invokeBasic and never linkToVirtual/linkToInterface? Or more generally, can we assume that linkToVirtual/linkToInterface will never be used in a method with an exception handler. [~vlivanov][[~jvernee] are the best one to answer this.
21-12-2021

[~dlong] The assumption for the work around is that there can't be a MethodHandle invoker call to a virtual method (that requires a null check) and exception handlers in the same method (that AFAIU is a lambda form generated at runtime by the JDK). Otherwise the work around which pops the stack when there's no exception handlers doesn't work. The reason for the assert is to check that the assumption is correct.
21-12-2021

[~roland] Maybe I'm missing the reason for the assert. If it is to make sure we handle all cases, then I don't see how checking for linkToVirtual/linkToInterface implies that there is no null check. If there is a way to call a MH intrinsic with both a null check and exception handler, then the workaround in JDK-8275638 is not enough. In that case, isn't a bailout better than an assert?
21-12-2021

[~dlong] right, the assert makes assumptions about implementation details but they are the assumptions that were made in JDK-8275638 already.
21-12-2021

[~roland], the test changes look good, but the new assert seems to be relying on implementations details that could change in the future. But I'm not a java.lang.invoke expert, so if you want to keep that assert, I would get it reviewed by an expert. [~mchung], is it safe to safe to assume that MethodHandles.tryFinally() and catchException() will always use invokeBasic and never linkToVirtual/linkToInterface? Or more generally, can we assume that linkToVirtual/linkToInterface will never be used in a method with an exception handler.
21-12-2021

[~dlong] Thanks for investigating. what about this as a fix: https://github.com/rwestrel/jdk18/tree/JDK-8278966 ?
20-12-2021

[~roland], the problem seems to be caused when using MethodHandles.tryFinally(), but I suspect that MethodHandles.catchException() would cause the same problem. I think the assert should simply be removed. Also add tryFinally and catchException test cases.
18-12-2021

ILW = assert in debug build, regression = MMH = P3
17-12-2021