RFR: 8350208: CTW: GraphKit::add_safepoint_edges asserts "not enough operands for reexecution"
Dean Long
dlong at openjdk.org
Thu Dec 4 03:24:59 UTC 2025
On Tue, 2 Dec 2025 10:30:46 GMT, Quan Anh Mai <qamai at openjdk.org> wrote:
> Hi,
>
> This PR fixes the issue of the compiler crashing with "not enough operands for reexecution". The issue here is that during `Parse::catch_inline_exceptions`, the old stack is gone, and we cannot reexecute the current bytecode anymore. However, there are some places where we try to insert safepoints into the graph, such as if the handler is a backward jump, or if one of the exceptions in the handlers is not loaded. Since the `_reexecute` state of the current jvms is "undefined", it is inferred automatically that it should reexecute for some bytecodes such as `putfield`. The solution then is to explicitly set `_reexecute` to false.
>
> I can manage to write a unit test for the case of a backward handler, for the other cases, since the exceptions that can be thrown for a bytecode that is inferred to reexecute are `NullPointerException`, `ArrayIndexOutOfBoundsException`, and `ArrayStoreException`. I find it hard to construct such a test in which one of them is not loaded.
>
> Please kindly review, thanks a lot.
It seems to be very difficult to force the back-edge safepoint to deoptimize. I tried creating a thread that calls System.gc(), but so far no crash. Still, I think the state is incorrect if reexecute=false. Setting reexecute to false means it will skip the current instruction. To correctly handle a deoptimization on the backwards branch, the debug state, bci, and exception location should match. I think we have 3 choices to prepare for maybe_add_safepoint():
1. preserve stack inputs, use original bci, do not push exception oop, let interpreter reexecute and throw the exception (reexecute=true)
This might be as simple as reversing the order of calls to push_ex_oop and maybe_add_safepoint.
2. trim stack, push exception object, use bci of exception handler (reexecute=true)
This would require temporarily changing the bci for the maybe_add_safepoint call.
3. trim stack, throw exception (move to Thread) (reexecute=true)
This requires extra unconditional overhead even though safepoint rarely happens.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/28597#issuecomment-3609883724
More information about the hotspot-compiler-dev
mailing list