[foreign-memaccess] RFR: 8227424: C2 assertion failures with debug build
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Tue Jul 9 10:20:43 UTC 2019
Hi Nick,
thanks for the fix - it looks good to me, but I'll defer to Vlad with
respect to the HS fix.
The ASM fix you made makes sense, I agree that the spec is not crystal
clear about it - section 6 (execution) just says that the operand popped
must be objectref, not much.
However, if you look at the verifier rules for getfield in chapter 4,
you see this:
"A /getfield/ instruction with operand |CP| is type safe iff |CP| refers
to a constant pool entry denoting a field whose declared type is
|FieldType|, declared in a class |FieldClassName|, and one can validly
replace a type matching |FieldClassName| with type |FieldType| on the
incoming operand stack yielding the outgoing type state"
To me this seems to suggest more strongly that the type of the receiver
in the operand stack has to match that of the field owner. This is
captured in this rule:
validTypeTransition(Environment,
[class(FieldClassName, CurrentLoader)], FieldType,
StackFrame, NextStackFrame),
This will trigger a sequence of rules for popping 'matching' types from
the stack, where the notion of matching has to do with subclassing -
that is, a found type T matches an expected type S if T <: S.
In the case of the ASM generated code, I believe we have it the wrong
way around, as the expected type is VarHandleMemoryAddressAsInts1, but
the found type is just VarHandleMemoryAddressBase - which I don't think
is enough to satisfy the verifier rules. I think it's more likely that
this rule has never been enforced too strictly - but it's nevertheless
there.
I agree that it would be nice to know some background here - if the code
indeed violates the verifier spec, why is this just a debug-only assertion?
Maurizio
On 09/07/2019 10:04, Nick Gasson wrote:
> Hi,
>
> I tried the foreign-memaccess branch on AArch64. It works fine but I ran
> into a crash and an assertion failure when I tested with a fastdebug
> Hotspot build. I've got a patch to fix these two issues here:
>
> Bug: https://bugs.openjdk.java.net/browse/JDK-8227424 (crash log attached)
> Webrev: http://cr.openjdk.java.net/~ngasson/foreign/8227424/webrev.0/
>
> The first failure is a segfault in C2 LoadNode::make. The
> foreign-memaccess branch has a change to
> LibraryCallKit::generate_current_thread to bypass GraphKit::make_load
> and call LoadNode::make directly to load the current Thread
> pointer. LoadNode::make takes a TypePtr* adr_type argument that is only
> used in an assertion:
>
> assert(!(adr_type->isa_oopptr() &&
> adr_type->offset() == oopDesc::klass_offset_in_bytes()),
> "use LoadKlassNode instead");
>
> generate_current_thread passes NULL for this argument so the assertion
> crashes. Replaced NULL with p->bottom_type()->is_ptr() which is what
> GraphKit::make_load would have done.
>
> The second failure is an assertion error while running the
> TestByteBuffer jtreg test:
>
> # Internal Error (src/hotspot/share/opto/parse3.cpp:85), pid=22340, tid=22379
> # assert(_gvn.type(obj)->higher_equal(tjp)) failed: cast_up is no longer needed
>
> This happens when C2 is parsing the bytecodes for
> VarHandleMemoryAddressAsInts1::get:
>
> static int get(java.lang.invoke.VarHandleMemoryAddressBase, java.lang.Object, long);
> Code:
> 0: ldc #51 // String CONSTANT_PLACEHOLDER_4
> 2: checkcast #53 // class java/lang/invoke/MethodHandle
> 5: aload_0
> 6: aload_1
> 7: aload_0
> 8: getfield #56 // Field java/lang/invoke/VarHandleMemoryAddressBase.offset:J
> 11: aload_0
> 12: getfield #16 // Field dim0:J
> 15: lload_2
> 16: lmul
> 17: ladd
> 18: invokevirtual #59 // Method java/lang/invoke/MethodHandle.invokeExact:(Ljava/lang/invoke/VarHandleMemoryAddressBase;Ljava/lang/Object;J)I
> 21: ireturn
>
> The error occurs at the getfield instruction at BCI 12 above. In this
> assertion `obj' is the object reference pushed by the aload_0 at BCI 11
> which has type VarHandleMemoryAddressBase. The getfield is referencing
> VarHandleMemoryAddressAsInts1::dim0 and `tjp' is the type of the field
> holder, VarHandleMemoryAddressAsInts1. The assert then expects the type
> of obj to be equal to tjp. As far as I can tell this isn't required by
> the JVMLS though.
>
> I worked around this by adding a checkcast before the getfield, but I
> wonder if the assertion in C2 is wrong / redundant? It's been there
> since the initial import in 2007 so I don't know what the history is.
>
> Tested foreign-memaccess jdk_foreign on x86 and AArch64.
>
> Thanks,
> Nick
More information about the panama-dev
mailing list