RFR(XL): 8224675: Late GC barrier insertion for ZGC

Nils Eliasson nils.eliasson at oracle.com
Wed May 29 12:18:27 UTC 2019


Hi Roland,

On 2019-05-29 09:48, Roland Westrelin wrote:
> Hi Nils,
>
>> Webrev: http://cr.openjdk.java.net/~neliasso/8224675/webrev.01/
> zBarrierSetC2.cpp: typo loadbarrers line 756
Fixed
> lcm.cpp:
>
> void PhaseCFG:: call_catch_cleanup(Block* block) {
>
> space after ::?
Fixed
>
> loopnode.cpp:
>
> Node *u
>
> I thought the usually recommended style was:
>
> Node* u
Yes.
> loopnode.cpp:
>
> Do we really need a new entry in the gc api for barrier_insertion()
> couldn't this go under optimize_loops()?

It could. There is only remove_range_check_casts in between right now. I 
choose to have it as its own for separation, in a similar way to how 
LoopOptsNone are used.


> memnode.hpp:
>
>   168   enum LoadBarrier {
>   169     UnProcessed     = 0,
>   170     RequireBarrier  = 1,
>   171     WeakBarrier     = 3,  // Inclusive with RequireBarrier
>   172     ExpandedBarrier = 4
>   173   };
>
> Shouldn't that be abstracted away through the gc api somehow?

Yes.

I would have preferred using the node-flags, but they are all taken 
unless we expand it to 32 bits, or overload the flags that are only used 
during codegen and later. That would require some verification of the 
flag use to catch any mistakes.

>
> zBarrierSetC2.cpp:
>
> typo (witch):
>
> 981     // For each load use, see witch catch projs dominates, create load clone lazily and reconnect
Fixed
>
> In fixup_uses_in_catch() wouldn't you need to deal with phis the way you
> do in call_catch_cleanup_one():
>
> 1019     // We found no single catchproj that dominated the use - The use is at a point after
> 1020     // where control flow from multiple catch projs have merged. We will have to create
> 1021     // phi nodes before the use and tie the output from the cloned loads together. It
> 1022     // can be a single phi or a number of chained phis, depending on control flow

No - it's a two step process.

There is a load hanging off a call with multiple catch projs. (There can 
be no other control-flow in between.) The load have uses, either (1) in 
the catch blocks, or (2) in some cases in the call block, hanging off 
the load.

fixup_uses_in_catch responsibility is to turn (2) into (1). It clones 
all uses of the load, in the call block, out to the catch blocks. This 
is done recursively. There can never be any phis here.


> Is there a chance that a load would be processed by
> fixup_uses_in_catch()? I see call_catch_cleanup_one() is where they are
> expected to be handled but you only go there if
> load->is_barrier_required() is true. So could you have a load for which
> is_barrier_required() is true have a use for which is_barrier_required()
> is not true and both of them be in the catch block?

In theory yes. If the load without a barrier is a use of the load with a 
barrier, it would be processed first. When the load with a barrier is 
processed, it would clone the load without a barrier, like any other node.

Another case is two loads that both require a barrier. One would be 
processed first, that one can't have the other one as a use, because the 
loads are processed in post order. And when the other load is processed, 
the first has already been cloned out.

Thanks for the feedback!

I'll get back with a new webrev.

// Nils

>
> Roland.


More information about the hotspot-compiler-dev mailing list