[14] RFR(S): 8233164: C2 fails with assert(phase->C->get_alias_index(t) == phase->C->get_alias_index(t_adr)) failed: correct memory chain

Tobias Hartmann tobias.hartmann at oracle.com
Fri Dec 20 11:34:50 UTC 2019


Hi Vladimir,

thanks for the quick review!

Best regards,
Tobias

On 20.12.19 12:25, Vladimir Ivanov wrote:
> 
>> http://cr.openjdk.java.net/~thartmann/8233164/webrev.00/
> 
> Looks good.
> 
> Best regards,
> Vladimir Ivanov
> 
>> The problem is that the arraycopy ideal transformation does not correctly wire memory inputs on
>> individual loads from a non-escaping src array.
>>
>> I was able to extract a test from the intermittently failing application that depends on indify
>> string concat (test1). From that, I've created another test that does not depend on Strings (test2).
>>
>> Gory details based on test2:
>> Two subsequent arraycopies copy data from two sources into the same destination. The ideal
>> transformation replaces the first arraycopy by a forward and backward copy (because
>> ArrayCopyNode::array_copy_test_overlap determines that the arrays may overlap). A PhiNode is added
>> to select between the memory outputs of the forward and backward stores:
>> http://hg.openjdk.java.net/jdk/jdk/file/2fbc66ef1a1d/src/hotspot/share/opto/arraycopynode.cpp#l617
>>
>>   574    StoreB    ===  559  572  553  573  [[ 568  576 ]]  @byte[int:0..max-2]:NotNull:exact+any ...
>>   567    StoreB    ===  558  562  565  566  [[ 560  576 ]]  @byte[int:0..max-2]:NotNull:exact+any ...
>>   575    Region    ===  575  558  559  [[ 575  576 ]]
>>   576    Phi    ===  575  567  574  [[]]  #memory  Memory: @byte[int:>=0]:exact+any *, idx=6;
>>
>> The second arraycopy can't be optimized (yet) because the src operand and its length are not known
>> but once Escape Analysis is executed, it determines that both source arrays are non-escaping. Now
>> the ideal transformation is able to replace the second arraycopy by loads/stores as well.
>>
>> The memory slice for the first load is selected from the MergeMem based on its address type
>> ('atp_src') which is the general byte[int:>=0] slice due to a CastPP that hides the type of the
>> non-escaping source array. As a result, we wire it to the byte[int:>=0] memory Phi that was created
>> when optimizing the first arraycopy:
>>
>>   305    CheckCastPP ===  302  300  [[ 385  316  420  494 ]]  #byte[int:1]:NotNull:exact *,iid=288
>>   494    CastPP    ===  486  305  [[ 526  514  626  626 ]]  #byte[int:>=0]:NotNull:exact *
>>   626    AddP    === _  494  494  68  [[ 629 ]]
>>   576    Phi    ===  575  567  574  [[ 560  628  629 ]]  #memory  Memory: @byte[int:>=0]:exact+any
>>   629    LoadB    ===  508  576  626  [[]]  @byte[int:>=0]:NotNull:exact+any *, idx=6; #byte
>>
>> That's obviously incorrect because now the LoadB has an address input into a non-escaping source
>> with type byte[int:1], iid=288 and a memory input from the independent byte[int:>=0] slice:
>> http://cr.openjdk.java.net/~thartmann/8233164/graph_Failure.png
>>
>> Basically, 629 LoadB uses memory from 47 AllocateArray when loading from an address into
>> non-escaping 288 AllocateArray. We then hit an assert in MemNode::optimize_memory_chain.
>>
>> The fix is to use _src_type/_dest_type (introduced by JDK-8076188) as address types for the loads
>> and stores. These will have the correct type if the source or destination array is non-escaping.
>>
>> The affected code is in there for a long time but I can only reproduce this back until JDK 13 b08
>> when JDK-8217990 was fixed. I don't think that fix is related but since the crash greatly depends on
>> the order in which nodes are processed by IGVN, it probably just triggers the issue (for example, if
>> we process a CastPP node first, it goes away and we get the correct type from the CheckCastPP). The
>> code was also changed significantly by JDK-8210887 in JDK 12.
>>
>> Thanks,
>> Tobias
>>


More information about the hotspot-compiler-dev mailing list