On local variables’ scopes and other problems Use case for Yielder
Aug 30

The latest yielder bug has been fixed, and now compilations without debugging information won’t break.

The differences from the original implementation post relate to the local variable promotion only. The changes are as follows:

  • Added members: The members being added to the Yielder implementation class are no longer according to the original local variables, but instead according to the slots in the method frame. That means that the following code:
    int len = arr.length;
    for (int i = 0; i < len; i++) {
      yieldReturn(arr[i]);
    }
    

    Will result in two members, slot$1 and slot$2.

  • Autoboxing: Since slots are multi-purpose, and can contain different types at different scopes (see previous post for details), all new slot members are of type Object. Because of that, all primitives inserted into slots are to be boxed when written and unboxed when read.
  • Array reflection: Arrays, of primitive types or of objects, are considered to be an Object in Java. However, they do have several bytecodes reserved just for them, such as arraylength, xaload and xastore. Unfortunately, unlike with primitive set and get operations (xload and xstore), there is no way to infer the type of the array from the bytecode operating on it. That is why in order to work with arrays, I am forced to use the reflection utility class, Array.
  • Example of the two previous points: I’ll use the first code example and show what manipulation would make it look like:
    slot$1 = arr;
    slot$2 = Integer.valueOf(Array.getLength(slot$1));
    for (slot$3 = 0; slot$3 < slot$2;
                  slot$3 = Integer.valueOf(((Integer)slot$3).intValue() + 1)) {
    
      yieldReturn(Array.getInt(slot$1, slot$3));
    }
    
  • Future optimization: It is possible with preemptive scanning of the bytecode to infer if a slot is used for only one type of information. If it is so, the generated slot member could be generated with that specific type and not the general Object. This could save on reflection (if the type is an array) or autoboxing (if it is a primitive). This would make the previous code look like the following, after the optimization:

    slot$1 = arr;
    slot$2 = slot$1.length;
    for (slot$3 = 0; slot$3 < slot$2; slot$3++) {
      yieldReturn(slot$1[slot$3]);
    }

     

So, for now, the solution is working even though not as optimized as I’d want it to be. However, I do have ideas on how to improve it. Please, join the group to suggest your own ideas, or post your comments here on the blog. If you haven’t experienced the yielder feature yet, read some about it or download it and give it a try!

  • Share/Bookmark

Leave a Reply

Chaotic Java is Digg proof thanks to caching by WP Super Cache