Details
-
Type:
Bug
-
Status:
Closed
-
Priority:
Critical
-
Resolution: Fixed
-
Affects Version/s: 1.8.3
-
Fix Version/s: 1.8.4, 2.0-beta-1
-
Component/s: None
-
Labels:None
-
Environment:Groovy 1.8.3 + Java 1.6.0_27 on Ubuntu Linux 10.04.3
-
Number of attachments :
Description
This sample code:
class GroovyBooleanTest {
public boolean someCall() {
return true;
}
public void somecode() {
boolean val = someCall()
println val
}
}
produces very redundant bytecode (decompiled with jd-gui):
import groovy.lang.GroovyObject; import groovy.lang.MetaClass; import org.codehaus.groovy.runtime.BytecodeInterface8; import org.codehaus.groovy.runtime.ScriptBytecodeAdapter; import org.codehaus.groovy.runtime.callsite.CallSite; import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation; public class GroovyBooleanTest implements GroovyObject { public GroovyBooleanTest() { GroovyBooleanTest this; CallSite[] arrayOfCallSite = $getCallSiteArray(); MetaClass localMetaClass = $getStaticMetaClass(); this.metaClass = localMetaClass; } public boolean someCall() { CallSite[] arrayOfCallSite = $getCallSiteArray(); return DefaultTypeTransformation.booleanUnbox(Boolean.TRUE); return DefaultTypeTransformation.booleanUnbox((Integer)DefaultTypeTransformation.box(0)); } public void somecode() { CallSite[] arrayOfCallSite = $getCallSiteArray(); boolean val = 0; Object localObject; boolean bool1; if ((!BytecodeInterface8.isOrigZ()) || (__$stMC) || (BytecodeInterface8.disabledStandardMetaClass())) { localObject = arrayOfCallSite[0].callCurrent(this); val = DefaultTypeTransformation.booleanUnbox((Boolean)ScriptBytecodeAdapter.castToType(localObject, $get$$class$java$lang$Boolean())); } else { bool1 = someCall(); val = DefaultTypeTransformation.booleanUnbox((Boolean)ScriptBytecodeAdapter.castToType( (Boolean)DefaultTypeTransformation.box(bool1), $get$$class$java$lang$Boolean())); } arrayOfCallSite[1].callCurrent(this, (Boolean)DefaultTypeTransformation.box(val)); } static { __$swapInit(); Long localLong1 = (Long)DefaultTypeTransformation.box(0L); __timeStamp__239_neverHappen1319001147656 = DefaultTypeTransformation.longUnbox(localLong1); Long localLong2 = (Long)DefaultTypeTransformation.box(1319001147656L); __timeStamp = DefaultTypeTransformation.longUnbox(localLong2); } }
This part of the bytecode is interesting:
bool1 = someCall();
val = DefaultTypeTransformation.booleanUnbox((Boolean)ScriptBytecodeAdapter.castToType(
(Boolean)DefaultTypeTransformation.box(bool1), $get$$class$java$lang$Boolean()));
bool1 and val are both already booleans. It goes through many unnecessary layers before assigning val to bool1.
What is also quite interesting is that the someCall method has 2 return statements in the bytecode
(output produced by Eclipse Bytecode outline plugin: http://andrei.gmxhome.de/bytecode/)
decompiled with JD-Gui:
public boolean someCall() { CallSite[] arrayOfCallSite = $getCallSiteArray(); return DefaultTypeTransformation.booleanUnbox(Boolean.TRUE); return DefaultTypeTransformation.booleanUnbox((Integer)DefaultTypeTransformation.box(0)); }This must be a bug.