RFR: 8328306: AArch64: MacOS lazy JIT "write xor execute" switching [v4]
Andrew Dinn
adinn at openjdk.org
Tue Sep 2 11:06:46 UTC 2025
On Thu, 21 Aug 2025 00:27:48 GMT, David Holmes <dholmes at openjdk.org> wrote:
>>> I'm not sure I'm really understanding the rules here. Is it the case that the old code would switch between write and exec in a more block structured pattern - changing when needed
>>
>> The old code doesn't change when needed but at every VM transition whether needed or not. But only 1% of VM transitions need to change.
>>
>>> and then restoring. But the new approach only changes when needed and never restores?
>>
>> More or less, yes. (Although obviously we have to reset the mode when returning from VM mode.)
>>
>>> If so then I worry that the need to change mode at any given point is a function of the code path to that point, rather than being an obvious property of the code itself.
>>
>> We change mode when we're _all but certain_ that we need to. That seems right to me. If the mode doesn't need changing because it's already set, that's OK. Why do you think this might be a problem?
>>
>>> The "healing" allows this to work,
>>
>> To be clear: healing never happens in testing.
>>
>>> but I'm not sure how you would ever explain the placement rules to anyone. ?? For example, I find the placement within the `Assembler` constructor extremely obscure but presumably the code that creates the `Assembler` instance then proceeds to use that instance to write into the code cache?
>>
>> Yes, exactly. We create Assembler instances whenever we need to generate code, and we don't share those instances, so the constructor is sweet spot to change mode. We don't keep Assembler instances hanging around. We could argue that this is temporal coupling, a code smell, but WX mode is a temporal property, so to a large extent that can't be helped..
>
>> We change mode when we're _all but certain_ that we need to. That seems right to me. If the mode doesn't need changing because it's already set, that's OK. Why do you think this might be a problem?
>
> My concern is that if we have code that needs a specific mode, but it is not obvious at that piece of code that this is the case, then things will work fine if somewhere on the path to that code we set the right mode. But if we introduce a new path to that code that might not be the case and so we will introduce a new place where we switch modes. That can lead to redundancy. The whole thing (as it has from day one) seems ad-hoc.
>
> But if the proposed scheme performs better in general, and is not obviously "worse" from the ad-hoc perspective then ...
@dholmes-ora I accept that this approach is not fully robust in the face of changes to the code base. However, in mitigation of that risk, the approach of targeting the major gateway calls that precede most subsequent code updates (e.g. creating an assembler instance) means that only a relatively small number of code paths which bypass those known gateways currently are, or will ever be, susceptible to such failure.
Furthermore, weighed against that risk are 1) a mechanism we can use both to catch failures during testing and to avoid any danger when something escapes into production and 2) a significant gain in performance from avoiding (literally) millions of unnecessary transitions.
I don't normally support pushing changes which are inherently fragile in the face of code updates. However, in this case I think the mechanisms in place to mitigate the risk and limit any damage and the performance gains to be had make it worth adopting.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/26562#issuecomment-3244849530
More information about the hotspot-dev
mailing list