RFR: 8346280: C2: implement late barrier elision for G1

Roberto Castañeda Lozano rcastanedalo at openjdk.org
Fri Jan 24 09:38:48 UTC 2025


On Wed, 22 Jan 2025 15:20:19 GMT, Roberto Castañeda Lozano <rcastanedalo at openjdk.org> wrote:

> G1 barriers can be safely elided from writes to newly allocated objects as long as no safepoint is taken between the allocation and the write. This changeset complements early G1 barrier elision (performed by the platform-independent phases of C2, and limited to writes immediately following allocations) with a more general elision pass done at a late stage.
> 
> The late elision pass exploits that it runs at a stage where the relative order of memory accesses and safepoints cannot change anymore to elide barriers from initialization writes that do not immediately follow the corresponding allocation, e.g. in conditional initialization writes:
> 
> 
> o = new MyObject();
> if (...) {
>     o.myField = ...;  // barrier elided only after this changeset
>                       // (assuming no safepoint in the if condition)
> }
> 
> 
> or in initialization writes placed after exception-throwing checks:
> 
> 
> o = new MyObject();
> if (...) {
>     throw new Exception("");
> }
> o.myField = ...;  // barrier elided only after this changeset
>                   // (assuming no safepoint in the above if condition)
> 
> 
> These patterns are commonly found in Java code, e.g. in the core libraries:
> 
> - [conditional initialization](https://github.com/openjdk/jdk/blob/25fecaaf87400af535c242fe50296f1f89ceeb16/src/java.base/share/classes/java/lang/String.java#L4850), or
> 
> - [initialization after exception-throwing checks (in the superclass constructor)](https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/nio/X-Buffer.java.template#L324).
> 
> The optimization also enhances barrier elision for array initialization writes, for example eliding barriers from small array initialization loops (for which safepoints are not inserted):
> 
> 
> Object[] a = new Object[...];
> for (int i = 0; i < a.length; i++) {
>     a[i] = ...;  // barrier elided only after this changeset
> }
> 
> 
> or eliding barriers from array initialization writes with unknown array index:
> 
> 
> Object[] a = new Object[...];
> a[index] = ...;  // barrier elided only after this changeset
> 
> 
> The logic used to perform this additional barrier elision is a subset of a pre-existing ZGC-specific optimization. This changeset simply reuses the relevant subset (barrier elision for writes to newly-allocated objects) by extracting the core of the optimization logic from `zBarrierSetC2.cpp` into the GC-shared file `barrierSetC2.cpp`. The functions `block_has_safepoint`, `block_index`, `look_through_node`, `is_{undefined|unknown|concrete}`, `get_base_and_offset`, `is_array...

> It can be fixed like this:
> 
> ```diff
> diff --git a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp
> index 538e87a8f19..311ea2871f7 100644
> --- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp
> +++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp
> @@ -558,7 +558,9 @@ static const Node* get_base_and_offset(const MachNode* mach, intptr_t& offset) {
>      // The memory address is computed by 'base' and fed to 'mach' via an
>      // indirect memory operand (indicated by offset == 0). The ultimate base and
>      // offset can be fetched directly from the inputs and Ideal type of 'base'.
> -    offset = base->bottom_type()->isa_oopptr()->offset();
> +    const TypeOopPtr* oopptr = base->bottom_type()->isa_oopptr();
> +    if (oopptr == nullptr) return nullptr;
> +    offset = oopptr->offset();
>      // Even if 'base' is not an Ideal AddP node anymore, Matcher::ReduceInst()
>      // guarantees that the base address is still available at the same slot.
>      base = base->in(AddPNode::Base);
> ```
> 
> Do you want to include the fix and we file a separate issue for jdk24 and older?

Thanks Martin! I agree with your analysis and proposed solution. I have reported the issue ([JDK-8348562](https://bugs.openjdk.org/browse/JDK-8348562)) and assigned it to you, feel free to assign back if you prefer me to submit the fix. Since we are not in a hurry with this RFE, I think I will simply wait until JDK-8348562 is integrated to update this changeset.

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

PR Comment: https://git.openjdk.org/jdk/pull/23235#issuecomment-2612073374


More information about the hotspot-compiler-dev mailing list