[jira] [Commented] (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] [Commented] (GROOVY-9892) STC: VerifyError when embedding unary prefix/postfix increment/decrement operation of outer field in GString

Eric Milles (Jira)

    [ https://issues.apache.org/jira/browse/GROOVY-9892?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17262506#comment-17262506 ]

Frédéric Chuong commented on GROOVY-9892:
-----------------------------------------

There was an older bug where such unary pre/postfix operation were discussed [GROOVY-9385], not sure whether it's relevant to the current issue.

> 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.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 \*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}
> 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)