[ 
https://issues.apache.org/jira/browse/GROOVY-9892?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Frédéric Chuong updated GROOVY-9892:
------------------------------------
    Description: 
h1. Issue

With Groovy 3.0.6 (& 3.0.7), when embedding an outer field unary pre/postfix 
operation within a GString, combined with static compilation 
({{\@CompileStatic}}), 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.CheckClassAdapter

@CompileStatic
class OuterClass {
    int counter = 0

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

    static void main(String[] args) {
        CheckClassAdapter.verify(new 
ClassReader('org/example/OuterClass$_call_closure1'), true, new 
PrintWriter(System.err))
        assert new OuterClass().call() == 'Hello1Bar'
    }
}
{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:12)
        at org.example.OuterClass.main(OuterClass.groovy:19)
{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:12)
        at org.example.OuterClass.main(OuterClass.groovy:19)
{noformat}

This did not happen with Groovy 3.0.5.

{noformat:title=ASM CheckClassAdapter output / Groovy 3.0.6 bytecode 
KO|borderColor=red}
org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 34: 
Method owner: expected Lorg/codehaus/groovy/runtime/GStringImpl;, but found 
[Ljava/lang/Object;
        at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:291)
        at 
org.objectweb.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:1063)
        at 
org.objectweb.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:1021)
        at org.example.OuterClass.main(OuterClass.groovy:18)
Caused by: org.objectweb.asm.tree.analysis.AnalyzerException: Method owner: 
expected Lorg/codehaus/groovy/runtime/GStringImpl;, but found 
[Ljava/lang/Object;
        at 
org.objectweb.asm.tree.analysis.BasicVerifier.naryOperation(BasicVerifier.java:390)
        at 
org.objectweb.asm.tree.analysis.BasicVerifier.naryOperation(BasicVerifier.java:43)
        at 
org.objectweb.asm.tree.analysis.Frame.executeInvokeInsn(Frame.java:646)
        at org.objectweb.asm.tree.analysis.Frame.execute(Frame.java:573)
        at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:187)
        ... 3 more
doCall()Ljava/lang/Object;
00000 OuterClass$_call_closure1 .  :  :     NEW 
org/codehaus/groovy/runtime/GStringImpl
00001 OuterClass$_call_closure1 .  : GStringImpl  :     DUP
00002 OuterClass$_call_closure1 .  : GStringImpl GStringImpl  :     ICONST_1
00003 OuterClass$_call_closure1 .  : GStringImpl GStringImpl I  :     ANEWARRAY 
java/lang/Object
00004 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object  :     DUP
00005 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object  :   
  ICONST_0
00006 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I  : 
    ALOAD 0
00007 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
OuterClass$_call_closure1  :     CHECKCAST org/example/OuterClass$_call_closure1
00008 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
OuterClass$_call_closure1  :     INVOKEVIRTUAL 
org/example/OuterClass$_call_closure1.getThisObject ()Ljava/lang/Object;
00009 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
Object  :     LDC Lorg/example/OuterClass;.class
00010 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
Object Class  :     INVOKESTATIC 
org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType 
(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
00011 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
Object  :     CHECKCAST org/example/OuterClass
00012 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
OuterClass  :     INVOKEVIRTUAL org/example/OuterClass.getCounter ()I
Caused by: org.objectweb.asm.tree.analysis.AnalyzerException: Method owner: 
expected Lorg/codehaus/groovy/runtime/GStringImpl;, but found 
[Ljava/lang/Object;

00013 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I I  
:     ICONST_1
00014 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I I 
I  :     IADD
00015 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I I  
:     DUP
00016 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I I 
I  :     ISTORE 1
00017 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I I  
:     ALOAD 0
00018 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I I 
OuterClass$_call_closure1  :     INVOKEVIRTUAL 
groovy/lang/Closure.getThisObject ()Ljava/lang/Object;
00019 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I I 
Object  :     CHECKCAST org/example/OuterClass
00020 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I I 
OuterClass  :     ILOAD 1
00021 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I I 
OuterClass I  :     INVOKESTATIC org/example/OuterClass.pfaccess$00 
(Lorg/example/OuterClass;I)I
00022 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I I 
I  :     INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
00023 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I I 
Integer  :     AASTORE
00024 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object  :   
  ICONST_2
00025 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I  : 
    ANEWARRAY java/lang/String
00026 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
String  :     DUP
00027 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
String String  :     ICONST_0
00028 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
String String I  :     LDC "Hello"
00029 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
String String I String  :     AASTORE
00030 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
String  :     DUP
00031 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
String String  :     ICONST_1
00032 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
String String I  :     LDC "Bar"
00033 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
String String I String  :     AASTORE
00034 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
String  :     INVOKESPECIAL org/codehaus/groovy/runtime/GStringImpl.<init> 
([Ljava/lang/Object;[Ljava/lang/String;)V
00035 ?           :     ARETURN
00036 ?           :    L0
00037 ?           :    FRAME FULL [] [java/lang/Throwable]
00038 ?           :     NOP
00039 ?           :     ATHROW
{noformat}
{noformat:title=ASM CheckClassAdapter output / Groovy 3.0.5 
OK|borderColor=green}
doCall()Ljava/lang/Object;
00000 OuterClass$_call_closure1  :  :     NEW 
org/codehaus/groovy/runtime/GStringImpl
00001 OuterClass$_call_closure1  : GStringImpl  :     DUP
00002 OuterClass$_call_closure1  : GStringImpl GStringImpl  :     ICONST_1
00003 OuterClass$_call_closure1  : GStringImpl GStringImpl I  :     ANEWARRAY 
java/lang/Object
00004 OuterClass$_call_closure1  : GStringImpl GStringImpl Object  :     DUP
00005 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object  :     
ICONST_0
00006 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I  :   
  ALOAD 0
00007 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I 
OuterClass$_call_closure1  :     CHECKCAST org/example/OuterClass$_call_closure1
00008 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I 
OuterClass$_call_closure1  :     INVOKEVIRTUAL 
org/example/OuterClass$_call_closure1.getThisObject ()Ljava/lang/Object;
00009 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I 
Object  :     LDC Lorg/example/OuterClass;.class
00010 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I 
Object Class  :     INVOKESTATIC 
org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType 
(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
00011 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I 
Object  :     CHECKCAST org/example/OuterClass
00012 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I 
OuterClass  :     INVOKEVIRTUAL org/example/OuterClass.getCounter ()I
00013 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I  : 
    ICONST_1
00014 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I I  
:     IADD
00015 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I  : 
    DUP
00016 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I I  
:     INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
00017 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I 
Integer  :     LDC Lorg/example/OuterClass$_call_closure1;.class
00018 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I 
Integer Class  :     ALOAD 0
00019 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I 
Integer Class OuterClass$_call_closure1  :     LDC "counter"
00020 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I 
Integer Class OuterClass$_call_closure1 String  :     CHECKCAST java/lang/String
00021 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I 
Integer Class OuterClass$_call_closure1 String  :     INVOKESTATIC 
org/codehaus/groovy/runtime/ScriptBytecodeAdapter.setGroovyObjectProperty 
(Ljava/lang/Object;Ljava/lang/Class;Lgroovy/lang/GroovyObject;Ljava/lang/String;)V
00022 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I  : 
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
00023 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I 
Integer  :     AASTORE
00024 OuterClass$_call_closure1  : GStringImpl GStringImpl Object  :     
ICONST_2
00025 OuterClass$_call_closure1  : GStringImpl GStringImpl Object I  :     
ANEWARRAY java/lang/String
00026 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String  :     
DUP
00027 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String String 
 :     ICONST_0
00028 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String String 
I  :     LDC "Hello"
00029 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String String 
I String  :     AASTORE
00030 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String  :     
DUP
00031 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String String 
 :     ICONST_1
00032 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String String 
I  :     LDC "Bar"
00033 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String String 
I String  :     AASTORE
00034 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String  :     
INVOKESPECIAL org/codehaus/groovy/runtime/GStringImpl.<init> 
([Ljava/lang/Object;[Ljava/lang/String;)V
00035 OuterClass$_call_closure1  : GStringImpl  :     ARETURN
00036 ?            :    L0
00037 ?            :    FRAME FULL [] [java/lang/Throwable]
00038 ?            :     NOP
00039 ?            :     ATHROW
{noformat}


h1. Workaround

A workaround is to lift the unary operation out of the GString (i.e. use a 
temporary variable).

  was:
h1. Issue

With Groovy 3.0.6 (& 3.0.7), when embedding an outer field unary pre/postfix 
operation within a GString, combined with static compilation 
({{\@CompileStatic}}), 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}

h1. Workaround

A workaround is to lift the unary operation out of the GString (i.e. use a 
temporary variable).


> STC: VerifyError when embedding unary pre/postfix inc/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.6, 3.0.7
>         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
>            Priority: Major
>
> h1. Issue
> With Groovy 3.0.6 (& 3.0.7), when embedding an outer field unary pre/postfix 
> operation within a GString, combined with static compilation 
> ({{\@CompileStatic}}), 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.CheckClassAdapter
> @CompileStatic
> class OuterClass {
>     int counter = 0
>     def call() {
>         { ->
>             "Hello${++counter}Bar"
>         }.call()
>     }
>     static void main(String[] args) {
>         CheckClassAdapter.verify(new 
> ClassReader('org/example/OuterClass$_call_closure1'), true, new 
> PrintWriter(System.err))
>         assert new OuterClass().call() == 'Hello1Bar'
>     }
> }
> {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:12)
>       at org.example.OuterClass.main(OuterClass.groovy:19)
> {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:12)
>       at org.example.OuterClass.main(OuterClass.groovy:19)
> {noformat}
> This did not happen with Groovy 3.0.5.
> {noformat:title=ASM CheckClassAdapter output / Groovy 3.0.6 bytecode 
> KO|borderColor=red}
> org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 34: 
> Method owner: expected Lorg/codehaus/groovy/runtime/GStringImpl;, but found 
> [Ljava/lang/Object;
>       at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:291)
>       at 
> org.objectweb.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:1063)
>       at 
> org.objectweb.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:1021)
>       at org.example.OuterClass.main(OuterClass.groovy:18)
> Caused by: org.objectweb.asm.tree.analysis.AnalyzerException: Method owner: 
> expected Lorg/codehaus/groovy/runtime/GStringImpl;, but found 
> [Ljava/lang/Object;
>       at 
> org.objectweb.asm.tree.analysis.BasicVerifier.naryOperation(BasicVerifier.java:390)
>       at 
> org.objectweb.asm.tree.analysis.BasicVerifier.naryOperation(BasicVerifier.java:43)
>       at 
> org.objectweb.asm.tree.analysis.Frame.executeInvokeInsn(Frame.java:646)
>       at org.objectweb.asm.tree.analysis.Frame.execute(Frame.java:573)
>       at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:187)
>       ... 3 more
> doCall()Ljava/lang/Object;
> 00000 OuterClass$_call_closure1 .  :  :     NEW 
> org/codehaus/groovy/runtime/GStringImpl
> 00001 OuterClass$_call_closure1 .  : GStringImpl  :     DUP
> 00002 OuterClass$_call_closure1 .  : GStringImpl GStringImpl  :     ICONST_1
> 00003 OuterClass$_call_closure1 .  : GStringImpl GStringImpl I  :     
> ANEWARRAY java/lang/Object
> 00004 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object  :     DUP
> 00005 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object  : 
>     ICONST_0
> 00006 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I  
> :     ALOAD 0
> 00007 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
> OuterClass$_call_closure1  :     CHECKCAST 
> org/example/OuterClass$_call_closure1
> 00008 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
> OuterClass$_call_closure1  :     INVOKEVIRTUAL 
> org/example/OuterClass$_call_closure1.getThisObject ()Ljava/lang/Object;
> 00009 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
> Object  :     LDC Lorg/example/OuterClass;.class
> 00010 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
> Object Class  :     INVOKESTATIC 
> org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType 
> (Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
> 00011 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
> Object  :     CHECKCAST org/example/OuterClass
> 00012 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
> OuterClass  :     INVOKEVIRTUAL org/example/OuterClass.getCounter ()I
> Caused by: org.objectweb.asm.tree.analysis.AnalyzerException: Method owner: 
> expected Lorg/codehaus/groovy/runtime/GStringImpl;, but found 
> [Ljava/lang/Object;
> 00013 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
> I  :     ICONST_1
> 00014 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
> I I  :     IADD
> 00015 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
> I  :     DUP
> 00016 OuterClass$_call_closure1 .  : GStringImpl GStringImpl Object Object I 
> I I  :     ISTORE 1
> 00017 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I 
> I  :     ALOAD 0
> 00018 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I 
> I OuterClass$_call_closure1  :     INVOKEVIRTUAL 
> groovy/lang/Closure.getThisObject ()Ljava/lang/Object;
> 00019 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I 
> I Object  :     CHECKCAST org/example/OuterClass
> 00020 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I 
> I OuterClass  :     ILOAD 1
> 00021 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I 
> I OuterClass I  :     INVOKESTATIC org/example/OuterClass.pfaccess$00 
> (Lorg/example/OuterClass;I)I
> 00022 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I 
> I I  :     INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
> 00023 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I 
> I Integer  :     AASTORE
> 00024 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object  : 
>     ICONST_2
> 00025 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object I  
> :     ANEWARRAY java/lang/String
> 00026 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
> String  :     DUP
> 00027 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
> String String  :     ICONST_0
> 00028 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
> String String I  :     LDC "Hello"
> 00029 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
> String String I String  :     AASTORE
> 00030 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
> String  :     DUP
> 00031 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
> String String  :     ICONST_1
> 00032 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
> String String I  :     LDC "Bar"
> 00033 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
> String String I String  :     AASTORE
> 00034 OuterClass$_call_closure1 I  : GStringImpl GStringImpl Object Object 
> String  :     INVOKESPECIAL org/codehaus/groovy/runtime/GStringImpl.<init> 
> ([Ljava/lang/Object;[Ljava/lang/String;)V
> 00035 ?           :     ARETURN
> 00036 ?           :    L0
> 00037 ?           :    FRAME FULL [] [java/lang/Throwable]
> 00038 ?           :     NOP
> 00039 ?           :     ATHROW
> {noformat}
> {noformat:title=ASM CheckClassAdapter output / Groovy 3.0.5 
> OK|borderColor=green}
> doCall()Ljava/lang/Object;
> 00000 OuterClass$_call_closure1  :  :     NEW 
> org/codehaus/groovy/runtime/GStringImpl
> 00001 OuterClass$_call_closure1  : GStringImpl  :     DUP
> 00002 OuterClass$_call_closure1  : GStringImpl GStringImpl  :     ICONST_1
> 00003 OuterClass$_call_closure1  : GStringImpl GStringImpl I  :     ANEWARRAY 
> java/lang/Object
> 00004 OuterClass$_call_closure1  : GStringImpl GStringImpl Object  :     DUP
> 00005 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object  :   
>   ICONST_0
> 00006 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I  : 
>     ALOAD 0
> 00007 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I 
> OuterClass$_call_closure1  :     CHECKCAST 
> org/example/OuterClass$_call_closure1
> 00008 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I 
> OuterClass$_call_closure1  :     INVOKEVIRTUAL 
> org/example/OuterClass$_call_closure1.getThisObject ()Ljava/lang/Object;
> 00009 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I 
> Object  :     LDC Lorg/example/OuterClass;.class
> 00010 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I 
> Object Class  :     INVOKESTATIC 
> org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType 
> (Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
> 00011 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I 
> Object  :     CHECKCAST org/example/OuterClass
> 00012 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I 
> OuterClass  :     INVOKEVIRTUAL org/example/OuterClass.getCounter ()I
> 00013 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I  
> :     ICONST_1
> 00014 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I 
> I  :     IADD
> 00015 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I  
> :     DUP
> 00016 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I 
> I  :     INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
> 00017 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I 
> Integer  :     LDC Lorg/example/OuterClass$_call_closure1;.class
> 00018 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I 
> Integer Class  :     ALOAD 0
> 00019 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I 
> Integer Class OuterClass$_call_closure1  :     LDC "counter"
> 00020 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I 
> Integer Class OuterClass$_call_closure1 String  :     CHECKCAST 
> java/lang/String
> 00021 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I 
> Integer Class OuterClass$_call_closure1 String  :     INVOKESTATIC 
> org/codehaus/groovy/runtime/ScriptBytecodeAdapter.setGroovyObjectProperty 
> (Ljava/lang/Object;Ljava/lang/Class;Lgroovy/lang/GroovyObject;Ljava/lang/String;)V
> 00022 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I I  
> :     INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
> 00023 OuterClass$_call_closure1  : GStringImpl GStringImpl Object Object I 
> Integer  :     AASTORE
> 00024 OuterClass$_call_closure1  : GStringImpl GStringImpl Object  :     
> ICONST_2
> 00025 OuterClass$_call_closure1  : GStringImpl GStringImpl Object I  :     
> ANEWARRAY java/lang/String
> 00026 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String  :   
>   DUP
> 00027 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String 
> String  :     ICONST_0
> 00028 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String 
> String I  :     LDC "Hello"
> 00029 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String 
> String I String  :     AASTORE
> 00030 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String  :   
>   DUP
> 00031 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String 
> String  :     ICONST_1
> 00032 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String 
> String I  :     LDC "Bar"
> 00033 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String 
> String I String  :     AASTORE
> 00034 OuterClass$_call_closure1  : GStringImpl GStringImpl Object String  :   
>   INVOKESPECIAL org/codehaus/groovy/runtime/GStringImpl.<init> 
> ([Ljava/lang/Object;[Ljava/lang/String;)V
> 00035 OuterClass$_call_closure1  : GStringImpl  :     ARETURN
> 00036 ?            :    L0
> 00037 ?            :    FRAME FULL [] [java/lang/Throwable]
> 00038 ?            :     NOP
> 00039 ?            :     ATHROW
> {noformat}
> h1. Workaround
> A workaround is to lift the unary operation out of the GString (i.e. use a 
> temporary variable).



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

Reply via email to