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

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Thu Mar 21 00:21:55 UTC 2019


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