[9] RFR (XS): 8155635: C2: assert(flat != TypePtr::BOTTOM) failed: cannot alias-analyze an untyped ptr
Vladimir Kozlov
vladimir.kozlov at oracle.com
Thu May 5 19:43:14 UTC 2016
On 5/5/16 12:10 PM, Vladimir Ivanov wrote:
>>>>
>>>> Can you explain why we have such graph shape where we access memory
>>>> after a merge point and on one merged path has NULL as pointer to
>>>> object. There should be NULL check after merge before memory access in
>>>> such case.
>>> It's not necessarily a normal oop pointer. Double-register addressing
>>> mode is the source of such shapes. Consider the following example:
>>>
>>> Object o = (flag ? INSTANCE : null);
>>> long off = (flag ? F_OFFSET : ADDR);
>>> UNSAFE.getLong(o, off);
>>
>> I think for this graph shape C2 type system gave up and drops type to
>> general Ptr::BOTTOM because it does not know that 'off' can be address
>> and not a normal offset on dead path where base is NULL. We usually do:
>>
>> long l = flag ? o.field : UNSAFE.getLong(addr);
>> And for UNSAFE.getLong(addr) we generate Raw pointer address
>> (make_unsafe_address()).
>>
>> What I am saying is that C2 treat long value as address only when it was
>> used as direct parameter for unsafe. See
>> LibraryCallKit::classify_unsafe_addr().
>
> The type I see during compilation for "opaque" access (mixed on-heap & off-heap) is the following:
>
> Oop:UnsafeAddP:exact+any * [narrow]
>
> LibraryCallKit::classify_unsafe_addr() produces Type::AnyPtr for such shapes. But it is used in LibraryCallKit::make_unsafe_address() just to decide on base value:
MAy be classify_unsafe_addr() should produce RawPtr type in such case.
>
> inline Node* LibraryCallKit::make_unsafe_address(Node* base, Node* offset) {
> int kind = classify_unsafe_addr(base, offset);
> if (kind == Type::RawPtr) {
> return basic_plus_adr(top(), base, offset);
> } else {
> return basic_plus_adr(base, offset);
> }
> }
>
> Maybe we need to enhance the logic and produce a special shape for such accesses.
Yes, I think it is good place to enhance it since we know that we do unsafe access and can generate RAW acccess.
>
>> Who produces ADDR? May be we can't set flag to indicate that it is RAW
>> address.
>
> I don't see how we can achieve that. It's just a long constant (or value) which represents an absolute address at runtime:
>
> static final long addr = UNSAFE.allocateMemory(10);
Yes, flag will not work. But we access such addr only through UNSAFE api. So we should be able to produce RAW type for it at that point.
Thanks,
Vladimir
>
>> We should discuss it with John who is *the* expert in this.
>
> John, what are your thoughts about that?
>
> Best regards,
> Vladimir Ivanov
>
>>
>> Thanks,
>> Vladimir
>>
>>>
>>> is translated into:
>>>
>>> LoadL mem (AddP (Phi #NULL #NonNull) off)
>>>
>>> If such AddP is split through the Phi, it turns into (AddP #NULL #NULL
>>> off) and (AddP #NonNull #NonNull off). The former is untyped and
>>> causes problems later.
>>>
>>> What I can't replicate is how X-shaped control flow eligible for
>>> SplitIf transformation is produced.
>>>
>>> In the failing case, initial null & exact type checks of an oop local
>>> (on OSR entry) merge into redundant X-shaped block. Unsafe accesses
>>> uses the local as a base later.
>>>
>>> Best regards,
>>> Vladimir Ivanov
>>>
>>>>
>>>> On 4/29/16 4:11 PM, Vladimir Ivanov wrote:
>>>>> http://cr.openjdk.java.net/~vlivanov/8155635/webrev.00/
>>>>> https://bugs.openjdk.java.net/browse/JDK-8155635
>>>>>
>>>>> SplitIf transformation can produce untyped pointers when slitting AddP
>>>>> nodes for unsafe accesses through a Phi which
>>>>> merges non-null & null values:
>>>>> AddP ... (Phi (ConP #NULL) (CheckCastPP Oop:...:NotNull))
>>>>>
>>>>> Proposed fix is to enable oop pointer to raw pointer conversion for
>>>>> absolute addresses.
>>>>>
>>>>> I also experimented with blocking SplitIf transformation is such
>>>>> cases, but the transformation seems viable and
>>>>> considerably simplifies the graph: X-shaped control flow is untangled
>>>>> by eliminating redundant and the transformation
>>>>> sharpens types on both branches.
>>>>>
>>>>> I checked specifically how Phi merges raw & oop pointers after the
>>>>> split and it works fine.
>>>>>
>>>>> Testing: failing test, JPRT, RBT (hs-tier0-comp.js).
>>>>>
>>>>> Thanks!
>>>>>
>>>>> Best regards,
>>>>> Vladimir Ivanov
>>>>>
>>>>> PS: though AddP (Phi #NULL #NotNull) shape is common, I wasn't able to
>>>>> write a simplified test case which triggers
>>>>> SplitIf transformation.
More information about the hotspot-compiler-dev
mailing list