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$1andslot$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
Objectin Java. However, they do have several bytecodes reserved just for them, such asarraylength,xaloadandxastore. Unfortunately, unlike with primitive set and get operations (xloadandxstore), 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!