RFR: 8300148: Consider using a StoreStore barrier instead of Release barrier on ctor exit [v7]

Aleksey Shipilev shade at openjdk.org
Wed Apr 3 08:50:10 UTC 2024


On Wed, 3 Apr 2024 01:13:39 GMT, Joshua Cao <duke at openjdk.org> wrote:

>> The [JSR 133 cookbook](https://gee.cs.oswego.edu/dl/jmm/cookbook.html) has long recommended using a `StoreStore` barrier at the end of constructors that write to final fields. `StoreStore` barriers are much cheaper on arm machines as shown in benchmarks in this issue as well as https://bugs.openjdk.org/browse/JDK-8324186.
>> 
>> This change does not improve the case for constructors for objects with volatile fields because [MemBarRelease is emitted for volatile stores](https://github.com/openjdk/jdk/blob/8fc9097b3720314ef7efaf1f3ac31898c8d6ca19/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp#L211). This is demonstrated in test case `classWithVolatile`, where this patch does not impact the IR.
>> 
>> I had to modify some code around escape analysis to make sure there are no regressions in eliminating allocations and `StoreStore`'s. The [current handling of StoreStore's in escape analysis](https://github.com/openjdk/jdk/blob/8fc9097b3720314ef7efaf1f3ac31898c8d6ca19/src/hotspot/share/opto/escape.cpp#L2590) makes the assumption that the barriers input is a `Proj` to an `Allocate` ([example](https://github.com/openjdk/jdk/blob/8fc9097b3720314ef7efaf1f3ac31898c8d6ca19/src/hotspot/share/opto/library_call.cpp#L1553)). This is contrary to the barriers in the end of the constructor where there the barrier directly takes in an `Allocate` without an in between `Proj`. I opted to instead eliminate `StoreStore`s in GVN, exactly how `MemBarRelease` is handled.
>> 
>> I had to add [checks for StoreStore in macro.cpp](https://github.com/openjdk/jdk/blob/8fc9097b3720314ef7efaf1f3ac31898c8d6ca19/src/hotspot/share/opto/macro.cpp#L636), or else we fail some [cases for reducing allocation merges](https://github.com/openjdk/jdk/blob/8fc9097b3720314ef7efaf1f3ac31898c8d6ca19/test/hotspot/jtreg/compiler/c2/irTests/scalarReplacement/AllocationMergesTests.java#L1233-L1256).
>> 
>> Passes hotspot tier1 locally on a Linux machine.
>> 
>> ### Benchmarks
>> 
>> Running Renaissance ParNnemonics on an Amazon Graviton (arm) instance.
>> 
>> Baseline:
>> 
>> Result "org.renaissance.jdk.streams.JmhParMnemonics.run":
>>   N = 25
>>   mean =   3309.611 ±(99.9%) 86.699 ms/op
>> 
>>   Histogram, ms/op:
>>     [3000.000, 3050.000) = 0
>>     [3050.000, 3100.000) = 4
>>     [3100.000, 3150.000) = 1
>>     [3150.000, 3200.000) = 0
>>     [3200.000, 3250.000) = 0
>>     [3250.000, 3300.000) = 0
>>     [3300.000, 3350.000) = 9
>>     [3350.000, 3400.000) = 6
>>     [3400.000, 3450.000) = 5
>> 
>>   Percentiles, ms/op:
>>       p(0...
>
> Joshua Cao has updated the pull request incrementally with two additional commits since the last revision:
> 
>  - Statistics for barriers generated/eliminated
>  - global flag to turn on storestore barrier emission and membar acquires
>    IR tests

More comments:

src/hotspot/share/opto/c2_globals.hpp line 795:

> 793:   develop(bool, UseStoreStoreForCtor, true,                                 \
> 794:           "Use storestore barrier instead of release barrier for"           \
> 795:           "on constructor exit")                                            \

For in-field use / debugging, we really need to make a diagnostic product flag.

src/hotspot/share/opto/escape.cpp line 200:

> 198:         // escape status of the associated Allocate node some of them
> 199:         // may be eliminated.
> 200:         if (n->req() > MemBarNode::Precedent) {

Should be protected by a feature flag? Like:


  if (!UseStoreStoreForCtor || n->req() > MemBarNode::Precedent) {

src/hotspot/share/opto/macro.cpp line 639:

> 637:                  (use->is_Phi() || use->is_EncodeP() ||
> 638:                   use->Opcode() == Op_MemBarRelease ||
> 639:                   use->Opcode() == Op_MemBarStoreStore)) {

Should be protected by a feature flag?

src/hotspot/share/opto/memnode.cpp line 3438:

> 3436:         }
> 3437:       }
> 3438:     } else if (opc == Op_MemBarRelease || opc == Op_MemBarStoreStore) {

Should be protected by a feature flag?

src/hotspot/share/opto/stringopts.cpp line 2013:

> 2011:     // a reference to the newly constructed object (see Parse::do_exits()).
> 2012:     assert(AllocateNode::Ideal_allocation(result) != nullptr, "should be newly allocated");
> 2013:     kit.insert_mem_bar(Op_MemBarStoreStore, result);

Should be protected by a feature flag?

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

PR Review: https://git.openjdk.org/jdk/pull/18505#pullrequestreview-1976033867
PR Review Comment: https://git.openjdk.org/jdk/pull/18505#discussion_r1549263678
PR Review Comment: https://git.openjdk.org/jdk/pull/18505#discussion_r1549268541
PR Review Comment: https://git.openjdk.org/jdk/pull/18505#discussion_r1549268950
PR Review Comment: https://git.openjdk.org/jdk/pull/18505#discussion_r1549265535
PR Review Comment: https://git.openjdk.org/jdk/pull/18505#discussion_r1549265267


More information about the hotspot-compiler-dev mailing list