RFR: JDK-8220714: C2 Compilation failure when accessing off-heap memory using Unsafe

Roman Kennke rkennke at redhat.com
Thu Mar 21 12:00:38 UTC 2019


Hi Vladimir,

Thanks for reviewing!

Not sure what happened to the webrev. Parts of it seem to have snuck in 
from a previous working version. Here's a good one:

http://cr.openjdk.java.net/~rkennke/JDK-8220714/webrev.01/

Thanks,
Roman


> Proposed fix looks good [1].
> 
> (FYI the patch [2] differs significantly from the webrev.)
> 
>> Looking on changes and it seems you can modify it a little:
>>
>>    // Can base be NULL? Otherwise, always on-heap access.
>>    bool can_access_non_heap = 
>> TypePtr::NULL_PTR->higher_equal(_gvn.type(base));
>>    if (!can_access_non_heap) {
>>      heap_base_oop = base;
>>      decorators |= IN_HEAP;
>>    } else if (type == T_OBJECT) {
>>      return false; // off-heap oop accesses are not supported
>>    }
> 
> It doesn't look right.
> 
> There're 3 cases we care about here:
>    * on-heap accesses (non-NULL base)
>    * off-heap accesses (NULL base)
>    * mixed accesses (base may be NULL)
> 
> 'can_access_non_heap' distinguishes on-heap accesses from off-heap/mixed 
> ones.
> 
> 'heap_base_oop != top()' distinguishes off-heap accesses from 
> on-heap/mixed ones.
> 
> Best regards,
> Vladimir Ivanov
> 
> [1]
> 
> -  bool can_access_non_heap = 
> TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop));
> +  bool can_access_non_heap = 
> TypePtr::NULL_PTR->higher_equal(_gvn.type(base));
> 
> 
> [2] 
> http://cr.openjdk.java.net/~rkennke/JDK-8220714/webrev.00/jdk-jdk.changeset
> 
> -  bool can_access_non_heap = 
> TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop));
> +  bool can_access_non_heap = 
> TypePtr::NULL_PTR->higher_equal(_gvn.type(UseNewCode ? base : 
> heap_base_oop));
> 
> 
>> On 3/15/19 4:39 AM, Roman Kennke wrote:
>>> A user reported misbehaving off-heap access. It looks like a C2
>>> compilation failure that seems to only trigger with Shenandoah:
>>>
>>> https://mail.openjdk.java.net/pipermail/shenandoah-dev/2019-March/009060.html 
>>>
>>>
>>> Eg with G1 generates this assembly for swapping two array elements:
>>> mov (%r8),%r9d
>>> mov (%r10),%r11d
>>> mov %r9d,(%r10)
>>> mov %r11d,(%r8)
>>>
>>> While with Shenandoah we get this:
>>> mov (%r9),%ecx
>>> mov %ecx,(%r10,%r11,1)
>>> mov %ecx,(%r9)
>>>
>>> I.e. the two loads seem to have been wrongly coalesced into one.
>>>
>>> Even though that is only triggered by Shenandoah, it seems to be a legit
>>> and generic C2 problem.
>>>
>>> Bug:
>>> https://bugs.openjdk.java.net/browse/JDK-8220714
>>> Webrev:
>>> http://cr.openjdk.java.net/~rkennke/JDK-8220714/webrev.00/
>>>
>>> The issue seems to be that off-heap accesses are supposed to use
>>> MO_RELAXED mem-ordering instead of MO_UNORDERED, as implemented in
>>> C2Access::needs_cpu_membar(). However, it seems we wrongly set this here
>>> (library_call.cpp around l2410:
>>>
>>>    // Can base be NULL? Otherwise, always on-heap access.
>>>    bool can_access_non_heap =
>>> TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop));
>>>    if (!can_access_non_heap) {
>>>      decorators |= IN_HEAP;
>>>    }
>>>
>>> However, heap_base_oop is initialized to top() a few lines up, and then
>>> never updated, at least not for the off-heap-access case. And top
>>> doesn't match NULL_PTR afaik.
>>>
>>> The proposed fix uses base instead of heap_base_oop for that check, this
>>> should be updated correcly through make_unsafe_addr() and
>>> classify_unsafe_addr().
>>>
>>> For some reason, this bug only seems to be exposed when running
>>> Shenandoah, and then only when actually compiling with barriers. We
>>> could not reproduce this with any other GC. It totally eludes me why
>>> that is so. For this reason, the testcase goes under the
>>> gc/shenandoah/compiler directory.
>>>
>>> Roman
>>>


More information about the hotspot-compiler-dev mailing list