[lworld] VerifyError: Bad type on operand stack, limitation in javac for value type constructors

Paul Sandoz paul.sandoz at oracle.com
Fri Jul 13 18:24:00 UTC 2018


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