JVM crashes with following log:
```
#
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (/mnt/local/code/valhalla/src/hotspot/share/opto/graphKit.cpp:3414), pid=1533674, tid=1533690
# assert(stopped() || !toop->is_inlinetypeptr() || obj->is_InlineType()) failed: should have been scalarized
#
# JRE version: OpenJDK Runtime Environment (21.0) (fastdebug build 21-internal-git-94636f4c8)
# Java VM: OpenJDK 64-Bit Server VM (fastdebug 21-internal-git-94636f4c8, compiled mode, sharing, compressed oops, compressed class ptrs, g1 gc, linux-aarch64)
# Problematic frame:
# V [libjvm.so+0xd2c070] GraphKit::gen_checkcast(Node*, Node*, Node**, bool)+0x46c
```
For a method call which returns an abstract class, and the subclass of the abstract class is a value class. When the method is called and there is a cast after it, which is used to cast the abstract class to its subclass (i.e. the value class), the above issue happens. The cause is the compiler checks the basic type of method return type to decide whether it is a inline type when handling java method call. The type may comes from the signature of the method declaration (i.e. the abstract class type). But when handling the "checkcast" bytecode, the compiler uses the relative speculative type which may use the profiling info as the reference. At this time, if the subclass is a value class, it is an inline type.
Following is the case:
```
public static MultiValues add(MultiValues v1, MultiValues v2) {
return v1.factory(v1.value1() + v2.value1(), v1.value2() + v2.value2());
}
public static void main(String[] args) {
Point p1 = new Point(RD.nextInt(), RD.nextInt());
Point p2 = new Point(RD.nextInt(), RD.nextInt());
for (int i = 0; i < LOOP_COUNT; i++) {
p1 = (Point) add(p1, p2);
}
System.out.println("PASS");
}
static abstract class MultiValues {
public abstract int value1();
public abstract int value2();
public abstract MultiValues factory(int value1, int value2);
}
static value class Point extends MultiValues {
private int x;
private int y;
private Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public int value1() {
return x;
}
@Override
public int value2() {
return y;
}
@Override
public Point factory(int value1, int value2) {
return new Point(value1, value2);
}
}
```
```
#
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (/mnt/local/code/valhalla/src/hotspot/share/opto/graphKit.cpp:3414), pid=1533674, tid=1533690
# assert(stopped() || !toop->is_inlinetypeptr() || obj->is_InlineType()) failed: should have been scalarized
#
# JRE version: OpenJDK Runtime Environment (21.0) (fastdebug build 21-internal-git-94636f4c8)
# Java VM: OpenJDK 64-Bit Server VM (fastdebug 21-internal-git-94636f4c8, compiled mode, sharing, compressed oops, compressed class ptrs, g1 gc, linux-aarch64)
# Problematic frame:
# V [libjvm.so+0xd2c070] GraphKit::gen_checkcast(Node*, Node*, Node**, bool)+0x46c
```
For a method call which returns an abstract class, and the subclass of the abstract class is a value class. When the method is called and there is a cast after it, which is used to cast the abstract class to its subclass (i.e. the value class), the above issue happens. The cause is the compiler checks the basic type of method return type to decide whether it is a inline type when handling java method call. The type may comes from the signature of the method declaration (i.e. the abstract class type). But when handling the "checkcast" bytecode, the compiler uses the relative speculative type which may use the profiling info as the reference. At this time, if the subclass is a value class, it is an inline type.
Following is the case:
```
public static MultiValues add(MultiValues v1, MultiValues v2) {
return v1.factory(v1.value1() + v2.value1(), v1.value2() + v2.value2());
}
public static void main(String[] args) {
Point p1 = new Point(RD.nextInt(), RD.nextInt());
Point p2 = new Point(RD.nextInt(), RD.nextInt());
for (int i = 0; i < LOOP_COUNT; i++) {
p1 = (Point) add(p1, p2);
}
System.out.println("PASS");
}
static abstract class MultiValues {
public abstract int value1();
public abstract int value2();
public abstract MultiValues factory(int value1, int value2);
}
static value class Point extends MultiValues {
private int x;
private int y;
private Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public int value1() {
return x;
}
@Override
public int value2() {
return y;
}
@Override
public Point factory(int value1, int value2) {
return new Point(value1, value2);
}
}
```