[jira] [Commented] (GROOVY-9892) STC: VerifyError when embedding unary pre/postfix inc/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 pre/postfix inc/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=17263282#comment-17263282 ]

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

Bisecting with the following test case:

{code:groovy|title=src/test/groovy/transform/stc/Groovy9892Bug.groovy}
package groovy.transform.stc

class Groovy9892Bug extends StaticTypeCheckingTestCase {
    void test() {
        assertScript '''
@groovy.transform.CompileStatic
class OuterClass {
    int counter = 0

    def call() {
        { ->
            "Hello${++counter}Bar"
        }.call()
    }
}
assert new OuterClass().call() == 'Hello1Bar'
'''
    }
}
{code}

{noformat}
git bisect start GROOVY_3_0_6 GROOVY_3_0_5 && git bisect run ./gradlew --console=plain :test --tests groovy.transform.stc.Groovy9892Bug
{noformat}

{noformat:title=git bisect log}
# bad: [6eb8bbbf62120a29cae04d3cdddf0e4e28954760] Release 3.0.6: update versions
# good: [0be35bb155d6188a6ccc727dea41646cefa706ac] Release 3.0.5: update versions
git bisect start 'GROOVY_3_0_6' 'GROOVY_3_0_5'
# good: [095c9bdd1abab714903ffa79d14bfc201f408a61] fix unintentional glitch on JDK14
git bisect good 095c9bdd1abab714903ffa79d14bfc201f408a61
# bad: [c94e24727172e9c895b657a2cbcb2286cd7cf78a] GROOVY-9711: @Sortable annotation always sorts by the parent properties (closes 1360)
git bisect bad c94e24727172e9c895b657a2cbcb2286cd7cf78a
# bad: [f8b7f33c489ba0e1e876eaf3633ce3de3471bbe5] GROOVY-9670: Bump TestNG to 7.3.0
git bisect bad f8b7f33c489ba0e1e876eaf3633ce3de3471bbe5
# bad: [640e9304fe8950400d94adaad474c0c341209df0] minor fix-ups
git bisect bad 640e9304fe8950400d94adaad474c0c341209df0
# good: [8bf2dc0a240e49f2430f375dc709faf559806924] GROOVY-9648: Bad error message when attempting to call a missing constructor with named args
git bisect good 8bf2dc0a240e49f2430f375dc709faf559806924
# good: [7c46b70ae33501a7b66beef807622ba6f1eb07a7] Minor tweak for "GROOVY-9657: JmxMetaMapBuilder.buildOperationMapFrom throw StringIndexOutOfBoundsException" (closes #1323)
git bisect good 7c46b70ae33501a7b66beef807622ba6f1eb07a7
# good: [4d04c10b5d81b7b70352cf9407ba7d664de77fb4] GROOVY-7232: check resolve strategy of each closure during method search
git bisect good 4d04c10b5d81b7b70352cf9407ba7d664de77fb4
# bad: [40ee3fd0c19530b4308c7c1b3e30abd4d45ed54a] GROOVY-7304: handle private field access from closure for ++x and x++
git bisect bad 40ee3fd0c19530b4308c7c1b3e30abd4d45ed54a
# first bad commit: [40ee3fd0c19530b4308c7c1b3e30abd4d45ed54a] GROOVY-7304: handle private field access from closure for ++x and x++
{noformat}


... reveals commit [{{40ee3fd0c19530b4308c7c1b3e30abd4d45ed54a}}|https://github.com/apache/groovy/commit/40ee3fd0c19530b4308c7c1b3e30abd4d45ed54a] (fix for [GROOVY-7304]) as the regression.

> 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)
> ASM 9.0
>            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)