RFR: 8365047: Remove exception handler stub code in C2 [v2]
Ruben
duke at openjdk.org
Fri Sep 12 16:40:47 UTC 2025
On Mon, 1 Sep 2025 09:51:38 GMT, Andrew Dinn <adinn at openjdk.org> wrote:
>> If we end up adding a nop or illegal instruction, then we can also undo the work-around that we did in JDK-8172844 for a similar problem.
>
> @dean-long I think there is an alternative fix for this that we should consider. The problem here arises because a return address for a legitimate call from the body may alias the nmethod's deopt_handler start. However, that aliasing is solely down to how we are recording and comparing addresses and I think we can easily and safely avoid it.
>
> The nmethod's deopt handler offset is set to identify the start of the deopt handler code generated into the stubs area. We need to be able to identify that stub's first instruction because we have to patch it into the stack or link register as a return address and then return to it in order to initiate a deopt. Removing the exception handler means it is now possible for it to directly follow the main code and alias the return address of a trailing call.
>
> We actually work hard to ensure that this same start address is recorded on the stack when we enter the deopt blob. The generated handler code always uses a jump to enter the deopt blob. However, it makes that jump look like a call by patching in a return address that equals the stub start. On Intel we make a fake call in order to push a return address and then carefully decrement the pushed address to refer to the stub start rather than the pushed address (i.e. the one that follows the fake call). On aarch64 it requires less work. The stub start is loaded into lr before jumping effectively simulating a call that just preceded the start address.
>
> Doing all this fiddling of the return pc is what makes the frame code test for a deopt caller frame both *simple* -- just compare the pc to the nmethod's deopt address -- and *ambiguous* -- oops! it could have been a trailing call in the main code. However, we can easily avoid the ambiguity. We can switch to an actual call in the generated code and adjust the deopt_pc test in the frame code to look for the nmethod's deopt address *plus* some arch-specific constant offset. The offset's size is determined by whatever instructions we need to plant in order to get to and make the call. We can make this safe against code changes by binding a label after the call and asserting that the difference between the label address and stub start address equals the relevant constant.
>
> That will give correct results if we traverse the frame stack inside or below the deopt blob code. But what about when we fiddle the return stack to force a return into the deopt stub? i.e. when the return address is the nmethod's deopt stub address? I don't b...
Thank you, @adinn , @dean-long.
I've updated the patch:
- Reverted the change adding NOPs at the end of main code section
- Moved the deoptimization handler stub code entry point to the end of the stub.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/26678#issuecomment-3286011603
More information about the hotspot-dev
mailing list