Question about tearing and buffered primitive classes

Tobias Hartmann tobias.hartmann at oracle.com
Thu Apr 1 07:25:52 UTC 2021


Hi Nick,

Thanks for looking into this!

On 30.03.21 12:41, Nick Gasson wrote:
> However based on my reading of the description in JDK-8237741 [1] this
> should only be necessary when the object is passed by invisible
> reference, not when it's actually flattened.  In Tobias' fix for
> JDK-8238780 [2] a store-store barrier was added to C2's
> InlineTypeBaseNode::buffer() but I can't see where the equivalent
> "buffering" happens in C1.

C2 does aggressive scalarization and therefore needs to buffer at various places when a reference is
required. C1 buffers only after reading from a flat representation, for example in
GraphBuilder::access_field (see NewInlineTypeInstance -> copy_inline_content).

That said, I'm wondering if a store-store barrier is needed there as well.

> Furthermore I don't understand why we can't instead rely on the barrier
> that gets added before returning from a constructor that writes final
> fields?  AIUI a primitive class's fields are always final and `this'
> can't escape its constructor so the effect should be the same as putting
> a barrier after each intermediate allocation inside the constructor.
> 
> GraphBuilder::withfield() calls set_wrote_final() which is used for this
> purpose *but* in GraphBuilder::method_return() we don't set need_mem_bar
> because method()->is_object_constructor() is false for primitive class
> constructors.  So a different patch that also fixes this test case is:

Yes, I think this is the correct fix:

> diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp
> index ead767f596d7..ac7e4ce5f06d 100644
> --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp
> +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp
> @@ -1617,7 +1617,7 @@ void GraphBuilder::method_return(Value x, bool ignore_return) {
> 
>    // The conditions for a memory barrier are described in Parse::do_exits().
>    bool need_mem_bar = false;
> -  if (method()->is_object_constructor() &&
> +  if ((method()->is_object_constructor() || method()->is_static_init_factory()) &&
>         (scope()->wrote_final() ||
>           (AlwaysSafeConstructors && scope()->wrote_fields()) ||
>           (support_IRIW_for_not_multiple_copy_atomic_cpu && scope()->wrote_volatile()))) {

The is_static_init_factory check is simply missing there.

Best regards,
Tobias


More information about the valhalla-dev mailing list