RFR: 8302351: "assert(!JavaThread::current()->is_interp_only_mode() || !nm->method()->is_continuation_enter_intrinsic() || ContinuationEntry::is_interpreted_call(return_pc)) failed: interp_only_mode but not in enterSpecial interpreted entry" in fixup_callers_callsite
Patricio Chilano Mateo
pchilanomate at openjdk.org
Fri Jun 2 17:42:34 UTC 2023
On Wed, 31 May 2023 07:49:13 GMT, Dean Long <dlong at openjdk.org> wrote:
> This patch seems like a step in the right direction, so let's keep the assert and special-case _linkToNative. It is the only special case I know of.
>
I have updated the PR with the suggested refactoring. Now, I have stress tested the patch by simulating always switching to interpreter only mode when going through this resolve methods in SharedRuntime and I found there is also an issue with the other method handle intrinsics, besides _linkToNative. If we return the c2i entry when resolving any of this methods we will end up jumping to the code generated by generate_method_handle_interpreter_entry(), but that code has an implicit null check for the MH receiver in generate_method_handle_dispatch(). If that is indeed null the signal handler will redirect us to generate_throw_exception() where we will call SharedRuntime::throw_NullPointerException_at_call() to create the exception. But the stack has already been changed in the c2i adapter to pass the arguments to the callee and also in that MH interpreter entry [1]. So when walking the stack we will crash when getting the sender of this compiled method that went through the c2i + MH in
terpreter entry. I found this issue with test compiler/jsr292/NullConstantReceiver.java. The bottom line issue is that we jumped to the interpreter target from the c2i entry but we never actually created an interpreter frame because we throw an exception before that, and since we modified the stack already we cannot walk it anymore.
Today we never hit this issue because it seems the _from_compiled_entry for method handle intrinsics never points to the c2i, but always to the compiled entry generated by gen_special_dispatch() (there has been an interesting discussion about this in 8302320). One way to keep this behavior and still catch the switch to interpreted only mode when resolving this methods could be to still return the _from_compiled_entry for method handle intrinsics, but modify jump_from_method_handle() to check for interpreted only mode in both cases, not just when coming from interpreted code [2]. So if we came from compiled code and we are in interpreted only mode jump to the c2i instead. I have tested that and seems to work but I'm open to suggestions on this. I'm going away on vacations for a few days though so I'll resume work on this once I'm back.
[1] https://github.com/openjdk/jdk/blob/master/src/hotspot/cpu/x86/methodHandles_x86.cpp#L311
[2] https://github.com/openjdk/jdk/blob/master/src/hotspot/cpu/x86/methodHandles_x86.cpp#L138
-------------
PR Comment: https://git.openjdk.org/jdk/pull/14108#issuecomment-1574091628
More information about the hotspot-dev
mailing list