[ https://issues.apache.org/jira/browse/GROOVY-7705?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15064834#comment-15064834 ]
Jason Winnebeck commented on GROOVY-7705: ----------------------------------------- Awesome work on this, I did look at the code although I can't comment much about it since I don't know anything about Groovy internals, but I will say that's a really cool test framework on the Groovy side that allows you to check for a specific bytecode instruction. > CompileStatic closure accessing "thisObject" private field: setProperty > instead of synthetic method > --------------------------------------------------------------------------------------------------- > > Key: GROOVY-7705 > URL: https://issues.apache.org/jira/browse/GROOVY-7705 > Project: Groovy > Issue Type: Bug > Components: Static compilation > Affects Versions: 2.4.5 > Reporter: Jason Winnebeck > Assignee: Cédric Champeau > > When a closure sets the private field of a class, it does it via a > ScriptBytecodeAdapter.setGroovyObjectProperty on the closure object itself, > whereas when getting a private field of the class it uses a synthetic > "pfaccess$0" method. > Source: > {code:title=Source} > @CompileStatic > class SetFromClosure { > private int x > void doIt() { > def closure = { > x = 5 > println x > } > closure() > } > } > {code} > Decompiled result of closure class (via Fernflower in IntelliJ): > {code} > class SetFromClosure$_doIt_closure1 extends Closure implements > GeneratedClosure { > public SetFromClosure$_doIt_closure1(Object _outerInstance, Object > _thisObject) { > super(_outerInstance, _thisObject); > } > public Object doCall(Object it) { > byte var2 = 5; > ScriptBytecodeAdapter.setGroovyObjectProperty(Integer.valueOf(var2), > SetFromClosure$_doIt_closure1.class, this, (String)"x"); > DefaultGroovyMethods.println((SetFromClosure)this.getThisObject(), > Integer.valueOf(SetFromClosure.pfaccess$0((SetFromClosure)this.getThisObject()))); > return null; > } > public Object call(Object args) { > return this.doCall(args); > } > public Object call() { > return this.doCall((Object)null); > } > public Object doCall() { > return this.doCall((Object)null); > } > } > {code} > Workaround is to remove "private" keyword on the variable declaration, which > causes Groovy to generate public getter and setter. In that mode, the static > compiler does generate direct calls to both the getter and the setter. In one > example within my project the performance speedup was 10x with this > workaround. The only thing I notice in the workaround that is odd is that > instead of normal Java casts used, ScriptBytecodeAdapter.castToType is used > on "getThisObject" before calling the getters or setters. > This issue could possibly related to GROOVY-6825, but in that case it's an > inner class, and the issue description (currently) is not clear enough to see > if it's also generating a setProperty call. -- This message was sent by Atlassian JIRA (v6.3.4#6332)