[ https://issues.apache.org/jira/browse/GROOVY-9892?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Frédéric Chuong updated GROOVY-9892: ------------------------------------ Summary: STC: VerifyError when embedding unary pre/postfix inc/decrement operation of outer field in GString (was: STC: VerifyError when embedding unary prefix/postfix increment/decrement operation of outer field in GString) > 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, 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) |
Free forum by Nabble | Edit this page |