[lworld] VerifyError: Bad type on operand stack, limitation in javac for value type constructors
Harold David Seigel
harold.seigel at oracle.com
Fri Jul 13 18:47:23 UTC 2018
Hi Paul,
For a withfield instruction, do you expect the verifier to push the type
of the field on its stack or the type of the valuetype containing the
field. Currently, it pushes the valuetype on the stack.
This is a JVM Spec issue.
Harold
On 7/13/2018 2:24 PM, Paul Sandoz wrote:
> Hi,
>
> The program below compiles but fails when executed:
>
> $ java -XX:+EnableValhalla A
> Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
> Exception Details:
> Location:
> A$Point.$makeValue$()LA$Point; @12: i2b
> Reason:
> Type 'A$Point' (current frame, stack[1]) is not assignable to integer
> Current Frame:
> bci: @12
> flags: { }
> locals: { 'A$Point' }
> stack: { 'A$Point', 'A$Point' }
> Bytecode:
> 0000000: cb00 024b 2a2a 03cc 0004 594b 91cc 0003
> 0000010: 4b2a b0
>
> at A.main(A.java:31)
>
>
> The cause is this constructor:
>
> Point() {
> x = y = 0; // This is the cause
> }
>
> the byte code of which is:
>
> A$Point();
> descriptor: ()V
> flags: (0x0000)
> Code:
> stack=1, locals=1, args_size=1
> 0: aload_0
> 1: invokespecial #1 // Method java/lang/Object."<init>":()V
> 4: return
> LineNumberTable:
> line 6: 0
>
>
> If the constructor is updated to the following then things work:
>
> Point() {
> x = 0;
> y = 0;
> }
>
> static A$Point point();
> descriptor: ()LA$Point;
> flags: (0x0008) ACC_STATIC
> Code:
> stack=2, locals=0, args_size=0
> 0: iconst_0
> 1: iconst_0
> 2: invokestatic #6 // Method point:(II)LA$Point;
> 5: areturn
>
>
> There is a limitation in javac's current approach mapping field assignments to arguments passed to the static factory method.
>
> Paul.
>
> public class A {
> static final __ByValue class Point {
> final int x;
> final int y;
>
> Point() {
> x = y = 0; // This is the cause
> }
>
> static Point point(int x, int y) {
> Point p = __MakeDefault Point();
> p = __WithField(p.x, x);
> p = __WithField(p.y, y);
> return p;
> }
>
> @Override
> public boolean equals(Object o) {
> if (!(o instanceof Point)) return false;
> Point op = (Point) o;
>
> return x == op.x && y == op.y;
> }
>
> static Point point() {
> return point(0, 0);
> }
> }
>
> public static void main(String[] args) {
> Point p = Point.point();
> }
> }
>
More information about the valhalla-dev
mailing list