Jason Winnebeck created GROOVY-7705:
---------------------------------------

             Summary: CompileStatic closure accessing "thisObject" priviate 
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)

Reply via email to