RFR: 8221554: aarch64 cross-modifying code

Erik Österlund eosterlund at openjdk.java.net
Thu Oct 1 06:06:41 UTC 2020


On Wed, 30 Sep 2020 08:36:32 GMT, Alan Hayward <github.com+4146708+a74nh at openjdk.org> wrote:

> The AArch64 port uses maybe_isb in places where an ISB might be required
> because the code may have safepointed. These maybe_isbs are very conservative
> and are used in many places are used when a safepoint has not happened.
> 
> cross_modify_fence was added in common code to place a barrier in all the
> places after a safepoint has occurred. All the uses of it are in common code,
> yet it remains unimplemented on AArch64.
> 
> This set of patches implements cross_modify_fence for AArch64 and reconsiders
> every uses of maybe_isb, discarding many of them. In addition, it introduces
> a new diagnostic option, which when enabled on AArch64 tests the correct
> usage of the barriers.
> 
> Advantage of this patch is threefold:
> * Reducing the number of ISBs - giving a theoretical performance improvement.
> * Use of common code instead of backend specific code.
> * Additional test diagnostic options
> 
> Patch 1: Split cross_modify_fence
> =================================
> This is simply refactoring work split out to simplify the other two patches.
> 
> instruction_fence() is provided by each target and simply places
> a fence for the instruction stream.
> 
> cross_modify_fence() is now a member of JavaThread and just calls
> instruction_fence. This function will be extended in Patch 3.
> 
> Patch 2: Use cross_modify_fence instead of maybe_isb
> ====================================================
> 
> The [n] References refer to the comments for cross_modify_fence in
> thread.hpp.
> 
> This is all the existing uses of maybe_isb in the AArch64 target:
> 
> 1) Instances of Java code calling a VM function
>    * This encapsulates the changes to:
>    ** MacroAssembler::call_VM_leaf_base()
>    ** generate_fast_get_int_field0()
>    ** stubGenerator_aarch64 generate_throw_exception()
>    ** sharedRuntime_aarch64 generate_handler_blob()
>    ** SharedRuntime::generate_resolve_blob()
>    ** C1 LIR_Assembler::rt_call
>    ** C1 StubAssembler::call_RT(): used by Used by generate_exception_throw,
>                                    generate_handle_exception, generate_code_for.
>    ** OptoRuntime::generate_exception_blob()
>    * Any changes will be caught due to calls to [2] or [3] by the VM function.
>    * Any calls that do not call [2] or [3] do not require an ISB.
>    * This patch is more optimal for these cases.
> 
> 2) Instances of Java code calling a JNI function
>    * This encapsulates the changes to:
>    ** SharedRuntime::generate_native_wrapper()
>    ** TemplateInterpreterGenerator::generate_native_entry()
>    * A safepoint still in progress after the call with be caught by [4].
>    * An ISB is still required for the case where there was a safepoint
>      but it completed during the call. This happens if the code doesn't
>      branch on safepoint_in_progress
>    * In the SharedRuntime version, the two possible calls to
>      reguard_yellow_pages and complete_monitor_unlocking_C are after the thread
>      goes back into it's original state, so are covered by [2] and [3], the
>      same as a normal VM call.
>    * This patch is only more optimal for the two post-JNI calls.
> 
> 3) Patching functions
>    * This encapsulates the changes to:
>    ** patch_callers_callsite() (called by gen_c2i_adapter())
>    * This results in code being patched, but does not safepoint
>    * Therefore an ISB is required.
>    * This patch introduces no change here.
> 
> 4) C1 MacroAssembler::emit_static_call_stub()
>    * Calls ISB (not maybe_isb)
>    * By design, the patching doesn't require that the up-to-date
>      destination is required for proper functioning.
>    * However, the ISB makes it most likely that the new destination will
>      be picked up.
>    * This patch introduces no change here.
> 
> Patch 3: Add cross modify fence verification
> ============================================
> 
> The VerifyCrossModifyFence diagnostic flag enables confirmation to the correct
> usage of instruction barriers. It can safely be enabled on any Java run.
> 
> Enabling it will cause the following:
> 
> * Once all threads have been brought to a safepoint, each thread will be
>   marked.
> 
> * On a cross_modify_fence and safepoint_fence the mark for that thread
>   will be cleared.
> 
> * On entry to a method and in a safepoint poll, then the thread is checked.
>   If it is marked, then the code will error.

I am about to integrate concurrent stack scanning for ZGC. This patch changes things a bit so that disarming of the
poll word is always done only by the thread itself. The consequence is that if a thread is in native or blocked, and
the safepoint finishes, then the thread will when waking up, still take one slow path to figure out all is done, disarm
the poll and run the cross modifying fence. The consequence is that we trivially need the cross modifying fence only in
the poll slow path and nowhere else. So maybe if you wait for that one, we can delete a few more ISBs, and IMO also
delete the verification code, as you can't really mess it up any more.

-------------

PR: https://git.openjdk.java.net/jdk/pull/428


More information about the hotspot-dev mailing list