Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-5089

Unnecessary unboxing and casting in boolean handling in generated bytecode

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Critical
    • Resolution: Fixed
    • 1.8.3
    • 1.8.4, 2.0-beta-1
    • None
    • None
    • Groovy 1.8.3 + Java 1.6.0_27 on Ubuntu Linux 10.04.3

    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.

      Attachments

        Activity

          People

            blackdrag Jochen Theodorou
            lhotari Lari Hotari
            Votes:
            1 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: