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

Srikanth srikanth.adayapalam at oracle.com
Mon Jul 16 13:17:17 UTC 2018


I am not Paul :) but the present behavior you describe looks correct to me.

Bottomline, javac is generating bad code for the case concerned.
https://bugs.openjdk.java.net/browse/JDK-8207332

I doubt that there is a verifier defect here, but we will see after 
javac reforms itself.

Thanks
Srikanth

On Saturday 14 July 2018 12:17 AM, Harold David Seigel wrote:
> 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