[jira] [Created] (GROOVY-9892) STC: VerifyError when embedding unary prefix/postfix increment/decrement operation of outer field in GString

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[jira] [Created] (GROOVY-9892) STC: VerifyError when embedding unary prefix/postfix increment/decrement operation of outer field in GString

Eric Milles (Jira)
Frédéric Chuong created GROOVY-9892:
---------------------------------------

             Summary: STC: VerifyError when embedding unary prefix/postfix increment/decrement operation of outer field in GString
                 Key: GROOVY-9892
                 URL: https://issues.apache.org/jira/browse/GROOVY-9892
             Project: Groovy
          Issue Type: Bug
          Components: Static compilation
    Affects Versions: 3.0.7, 3.0.6
         Environment: OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.265-b01, mixed mode)
Eclipse OpenJ9 VM (build openj9-0.21.0, JRE 1.8.0 Windows 10 amd64-64-Bit Compressed References 20200728_776 (JIT enabled, AOT enabled)
            Reporter: Frédéric Chuong


h1. Issue

With Groovy 3.0.6 (3.0.7), when embedding an outer field unary \*fix operation within a GString, the generated bytecode fails at class loading time (VerifyError)

{code:groovy}
package org.example

import groovy.transform.CompileStatic
import org.objectweb.asm.ClassReader
import org.objectweb.asm.util.Textifier
import org.objectweb.asm.util.TraceClassVisitor

@CompileStatic
class OuterClass {
    int counter

    def call() {
        { ->
            "Hello${++counter}Bar"
        }.call()
    }

    static void main(String[] args) {
        printClass('org/example/OuterClass$_call_closure1')
        assert new OuterClass().call() == 'Hello1Bar'
    }

    static void printClass(String className) {
        new ClassReader(className).accept(new TraceClassVisitor(null, new Textifier(), new PrintWriter(System.err)), 0)
    }
}
{code}

{noformat:title=HotSpot VM error}
java.lang.VerifyError: Bad type on operand stack
Exception Details:
  Location:
    org/example/OuterClass$_call_closure1.doCall()Ljava/lang/Object; @46: aastore
  Reason:
    Type integer (current frame, stack[4]) is not assignable to reference type
  Current Frame:
    bci: @46
    flags: { }
    locals: { 'org/example/OuterClass$_call_closure1', integer }
    stack: { uninitialized 0, uninitialized 0, '[Ljava/lang/Object;', '[Ljava/lang/Object;', integer, integer, 'java/lang/Integer' }
  Bytecode:
    0x0000000: bb00 1c59 04bd 001e 5903 2ac0 0002 b600
    0x0000010: 2112 09b8 0027 c000 09b6 002b 0460 593c
    0x0000020: 2ab6 002c c000 091b b800 30b8 0036 5305
    0x0000030: bd00 3859 0312 3a53 5904 123c 53b7 003f
    0x0000040: b000 bf                                
  Stackmap Table:
    full_frame(@65,{},{Object[#65]})

        at org.example.OuterClass.call(OuterClass.groovy:13)
        at org.example.OuterClass.main(OuterClass.groovy:20)
{noformat}

{noformat:title=OpenJ9 VM error}
java.lang.VerifyError: JVMVRFY012 stack shape inconsistent; class=org/example/OuterClass$_call_closure1, method=doCall()Ljava/lang/Object;, pc=46
Exception Details:
  Location:
    org/example/OuterClass$_call_closure1.doCall()Ljava/lang/Object; @46: JBaastore
  Reason:
    Type 'java/lang/Integer' (current frame, stack[6]) is not assignable to 'java/lang/Object'
  Current Frame:
    bci: @46
    flags: { }
    locals: { 'org/example/OuterClass$_call_closure1', integer }
    stack: { 'uninitialized', 'uninitialized', '[Ljava/lang/Object;', '[Ljava/lang/Object;', integer, integer, 'java/lang/Integer' }
  Stackmap Table:
    full_frame(@65,{},{Object[#19]})
        at org.example.OuterClass.call(OuterClass.groovy:13)
        at org.example.OuterClass.main(OuterClass.groovy:20)
{noformat}

This did not happen with Groovy 3.0.5.

{noformat:title=Groovy 3.0.6 bytecode KO|borderColor=red}
  // access flags 0x1
  public doCall()Ljava/lang/Object;
   L0
    LINENUMBER 14 L0
    NEW org/codehaus/groovy/runtime/GStringImpl
    DUP
    ICONST_1
    ANEWARRAY java/lang/Object
    DUP
    ICONST_0
    ALOAD 0
    CHECKCAST org/example/OuterClass$_call_closure1
    INVOKEVIRTUAL org/example/OuterClass$_call_closure1.getThisObject ()Ljava/lang/Object;
    LDC Lorg/example/OuterClass;.class
    INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType (Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
    CHECKCAST org/example/OuterClass
    INVOKEVIRTUAL org/example/OuterClass.getCounter ()I
    ICONST_1
    IADD
    DUP
    ISTORE 1
    ALOAD 0
    INVOKEVIRTUAL groovy/lang/Closure.getThisObject ()Ljava/lang/Object;
    CHECKCAST org/example/OuterClass
    ILOAD 1
    INVOKESTATIC org/example/OuterClass.pfaccess$00 (Lorg/example/OuterClass;I)I
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
    AASTORE
    ICONST_2
    ANEWARRAY java/lang/String
    DUP
    ICONST_0
    LDC "Hello"
    AASTORE
    DUP
    ICONST_1
    LDC "Bar"
    AASTORE
    INVOKESPECIAL org/codehaus/groovy/runtime/GStringImpl.<init> ([Ljava/lang/Object;[Ljava/lang/String;)V
    ARETURN
   L1
   FRAME FULL [] [java/lang/Throwable]
    NOP
    ATHROW
    LOCALVARIABLE this Lorg/example/OuterClass$_call_closure1; L0 L1 0
    MAXSTACK = 8
    MAXLOCALS = 2
{noformat}
{noformat:title=Groovy 3.0.5 OK|borderColor=green}
// class version 52.0 (52)
// access flags 0x31
public final class org/example/OuterClass$_call_closure1 extends groovy/lang/Closure implements org/codehaus/groovy/runtime/GeneratedClosure {

  // compiled from: OuterClass.groovy
  OUTERCLASS org/example/OuterClass call ()Ljava/lang/Object;
  // access flags 0x11
  public final INNERCLASS org/example/OuterClass$_call_closure1 null _call_closure1

  // access flags 0x100A
  private static synthetic Lorg/codehaus/groovy/reflection/ClassInfo; $staticClassInfo

  // access flags 0x1089
  public static transient synthetic Z __$stMC

  // access flags 0x1
  public <init>(Ljava/lang/Object;Ljava/lang/Object;)V
   L0
    ALOAD 0
    ALOAD 1
    ALOAD 2
    INVOKESPECIAL groovy/lang/Closure.<init> (Ljava/lang/Object;Ljava/lang/Object;)V
   L1
    RETURN
    LOCALVARIABLE this Lorg/example/OuterClass$_call_closure1; L0 L1 0
    LOCALVARIABLE _outerInstance Ljava/lang/Object; L0 L1 1
    LOCALVARIABLE _thisObject Ljava/lang/Object; L0 L1 2
    MAXSTACK = 3
    MAXLOCALS = 3

  // access flags 0x1
  public doCall()Ljava/lang/Object;
   L0
    LINENUMBER 14 L0
    NEW org/codehaus/groovy/runtime/GStringImpl
    DUP
    ICONST_1
    ANEWARRAY java/lang/Object
    DUP
    ICONST_0
    ALOAD 0
    CHECKCAST org/example/OuterClass$_call_closure1
    INVOKEVIRTUAL org/example/OuterClass$_call_closure1.getThisObject ()Ljava/lang/Object;
    LDC Lorg/example/OuterClass;.class
    INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType (Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
    CHECKCAST org/example/OuterClass
    INVOKEVIRTUAL org/example/OuterClass.getCounter ()I
    ICONST_1
    IADD
    DUP
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
    LDC Lorg/example/OuterClass$_call_closure1;.class
    ALOAD 0
    LDC "counter"
    CHECKCAST java/lang/String
    INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.setGroovyObjectProperty (Ljava/lang/Object;Ljava/lang/Class;Lgroovy/lang/GroovyObject;Ljava/lang/String;)V
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
    AASTORE
    ICONST_2
    ANEWARRAY java/lang/String
    DUP
    ICONST_0
    LDC "Hello"
    AASTORE
    DUP
    ICONST_1
    LDC "Bar"
    AASTORE
    INVOKESPECIAL org/codehaus/groovy/runtime/GStringImpl.<init> ([Ljava/lang/Object;[Ljava/lang/String;)V
    ARETURN
   L1
   FRAME FULL [] [java/lang/Throwable]
    NOP
    ATHROW
    LOCALVARIABLE this Lorg/example/OuterClass$_call_closure1; L0 L1 0
    MAXSTACK = 10
    MAXLOCALS = 1

  // access flags 0x1004
  protected synthetic $getStaticMetaClass()Lgroovy/lang/MetaClass;
    ALOAD 0
    INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class;
    LDC Lorg/example/OuterClass$_call_closure1;.class
    IF_ACMPEQ L0
    ALOAD 0
    INVOKESTATIC org/codehaus/groovy/runtime/ScriptBytecodeAdapter.initMetaClass (Ljava/lang/Object;)Lgroovy/lang/MetaClass;
    ARETURN
   L0
   FRAME SAME
    GETSTATIC org/example/OuterClass$_call_closure1.$staticClassInfo : Lorg/codehaus/groovy/reflection/ClassInfo;
    ASTORE 1
    ALOAD 1
    IFNONNULL L1
    ALOAD 0
    INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class;
    INVOKESTATIC org/codehaus/groovy/reflection/ClassInfo.getClassInfo (Ljava/lang/Class;)Lorg/codehaus/groovy/reflection/ClassInfo;
    DUP
    ASTORE 1
    PUTSTATIC org/example/OuterClass$_call_closure1.$staticClassInfo : Lorg/codehaus/groovy/reflection/ClassInfo;
   L1
   FRAME APPEND [org/codehaus/groovy/reflection/ClassInfo]
    ALOAD 1
    INVOKEVIRTUAL org/codehaus/groovy/reflection/ClassInfo.getMetaClass ()Lgroovy/lang/MetaClass;
    ARETURN
    MAXSTACK = 2
    MAXLOCALS = 2
}
{noformat}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)