RFR: 8365047: Remove exception handler stub code in C2 [v7]
Ruben
duke at openjdk.org
Tue Oct 21 11:15:17 UTC 2025
On Wed, 15 Oct 2025 14:00:32 GMT, Martin Doerr <mdoerr at openjdk.org> wrote:
>> Ruben has updated the pull request with a new target base due to a merge or a rebase. The pull request now contains 10 commits:
>>
>> - Merge from the main branch
>> - Address review comments
>> - Address review comments
>> - Address review comments
>> - The patch is contributed by @TheRealMDoerr
>> - Offset the deoptimization handler entry point
>>
>> Change-Id: I596317ec6a364b341e4642636fa5cf08f87ed722
>> - Revert "Ensure stub code is not adjacent to a call"
>> - Ensure stub code is not adjacent to a call
>> - Address review comments
>> - 8365047: Remove exception handler stub code in C2
>>
>> The C2 exception handler stub code is only a trampoline to the
>> generated exception handler blob. This change removes the extra
>> step on the way to the generated blob.
>>
>> According to some comments in the source code, the exception handler
>> stub code used to be patched upon deoptimization, however presumably
>> these comments are outdated as the patching upon deoptimization happens
>> for post-call NOPs only.
>
> One probably related issue on linuxaarch64 while testing "gc/epsilon/TestObjects.java":
> SIGSEGV in caller_is_deopted:
>
>
> Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
> V [libjvm.so+0x5531b8] caller_is_deopted(JavaThread*)+0x2f8 (nativeInst_aarch64.hpp:536)
> V [libjvm.so+0x555000] Runtime1::move_mirror_patching(JavaThread*)+0x20 (c1_Runtime1.cpp:1400)
> v ~RuntimeStub::C1 Runtime load_mirror_patching_blob 0x0000f7cf038f316c
>
>
>
> siginfo: si_signo: 11 (SIGSEGV), si_code: 2 (SEGV_ACCERR), si_addr: 0x0000f7cf03c60000
>
>
> That address is at the end of the stub section:
>
>
> R0 =0x00000000f001cee8 is an oop: java.util.HashMap
> {0x00000000f001cee8} - klass: 'java/util/HashMap' - flags: is_cloneable_fast
> - ---- fields (total size 5 words):
> - transient 'keySet' 'Ljava/util/Set;' @8 null (0x00000000)
> - transient 'values' 'Ljava/util/Collection;' @12 null (0x00000000)
> - transient 'table' '[Ljava/util/HashMap$Node;' @16 a 'java/util/HashMap$Node'[128] {0x00000000f001cf10} (0xf001cf10)
> - transient 'entrySet' 'Ljava/util/Set;' @20 null (0x00000000)
> - transient 'size' 'I' @24 60 (0x0000003c)
> - transient 'modCount' 'I' @28 60 (0x0000003c)
> - 'threshold' 'I' @32 96 (0x00000060)
> - final 'loadFactor' 'F' @36 0.750000 (0x3f400000)
> R1 =0x0000001fd503201f is an unknown value
> R2 =0x0000f7cf03c5fffc is at entry_point+276 in (nmethod*)0x0000f7cf03c5fdc8
> Compiled method (c1) 5966 2946 1 java.util.HashMap::values (25 bytes)
> total in heap [0x0000f7cf03c5fdc8,0x0000f7cf03c60000] = 568
> main code [0x0000f7cf03c5fec0,0x0000f7cf03c5ffd0] = 272
> stub code [0x0000f7cf03c5ffd0,0x0000f7cf03c60000] = 48
> mutable data [0x0000f7ced888a580,0x0000f7ced888a5c0] = 64
> relocation [0x0000f7ced888a580,0x0000f7ced888a5b0] = 48
> metadata [0x0000f7ced888a5b0,0x0000f7ced888a5c0] = 16
> immutable data [0x0000f7ced888a500,0x0000f7ced888a578] = 120
> dependencies [0x0000f7ced888a500,0x0000f7ced888a508] = 8
> scopes pcs [0x0000f7ced888a508,0x0000f7ced888a558] = 80
> scopes data [0x0000f7ced888a558,0x0000f7ced888a570] = 24
> speculations [0x0000f7ced888a570,0x0000f7ced888a574] = 4
> 0x0000f7cf03c5fff8: 62 74 ef 17 ff ff ff 17
> --------------------------------------------------------------------------------
> 0x0000f7cf03c5fff8: b 0x0000f7cf0383d180
> 0x0000f7cf03c5fffc: b 0x0000f7cf03c5fff8
> --------------------------------------------------------------------------------
> R3 =0x0000f7cf03817578 points into unknown readable ...
Thank you for the reviews and help with testing, @TheRealMDoerr, @adinn.
Apologies for the delayed response - it is due to being out of office. I'm planning to resume work on this PR from tomorrow.
I believe the specific issue revealed in the failed test is due to the `NativePostCallNop::check` is trying to read both NOP and MOVK in a combined 8-byte read, which requires at least two instructions after the perceived call site to be readable. In this case, the deoptimization handler stub code has only one valid instruction after the entry point. As the stub code is positioned right at the end of a page, presumably with the next page not mapped, the combined read fails. A possible solution to this would be to check for NOP only as the first step, and to check for MOVK conditionally.
This issue appears to be potentially independent from the `far_jump` being used instead of `far_call`.
I am planning to spend some time figuring out why tests on my side didn't catch the issue with `far_jump` used instead of `far_call`, and on preparing a test that would deterministically detect the issue with stub code positioned right before an unmapped page.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/26678#issuecomment-3426020854
More information about the serviceability-dev
mailing list