Am 15.01.2018 um 10:53 schrieb Daniel Sun:
Hi Jochen,
`ArrayIndexOutOfBoundsException` is fixed. I encounter another
problem(i.e. How to load arguments according to some specified order): I
want to load local variables[1] according to the order in which the local
variables appear in lambda body. For example:
(1)
```
String x = 'x'
Integer y = 2
Stream.of(1, 2, 3).map(e -> '' + x + y + e) // Note the order of `x` and
`y`(`x` is before `y`)
```
I hope load `x`, then load `y` before invokedynamic.
(2)
```
String x = 'x'
Integer y = 2
Stream.of(1, 2, 3).map(e -> '' + y + x + e) // Note the order of `x` and
`y`(`y` is before `x`)
```
I hope load `y`, then load `x` before invokedynamic.
Here is how I try to archieve[2], but I can not get the expected
result[3], i.e. I get `groovy.lang.Reference` instances... not String
instances.
If you use the Closure code, then variables used in Closures are marked
as Reference even if they are only read
The following bytecode is generated for java code[4] by javac. The key
part is shown as follows and is what I want to generate via ASM utilities of
Groovy(e.g. `CompileStack`, `OperandStack`, etc):
what you do is for exmple
Parameter[] lambdaSharedVariableParameters =
syntheticLambdaMethodNode.getNodeMetaData(LAMBDA_SHARED_VARIABLES);
for (int i = 0; i < lambdaSharedVariableParameters.length; i++) {
mv.visitVarInsn(ALOAD, i);
operandStack.doGroovyCast(lambdaSharedVariableParameters[i].getType().redirect());
//
operandStack.push(lambdaSharedVariableParameters[i].getType().redirect());
}
Assuming you manage to not wrap in a Reference, then the shared
parameter might be a primitive. in that case aload is the wrong bytecode
instruction. Please use CompileStack to handle the local variables instead.
[...]
The complete bytecode:
```
// class version 52.0 (52)
// access flags 0x21
public class Test2 {
[...]
// access flags 0x9
public static p()V
L0
LINENUMBER 10 L0
LDC "#"
ASTORE 0
this creates a String and stores it in 0
L1
LINENUMBER 12 L1
ICONST_3
ANEWARRAY java/lang/Integer
DUP
ICONST_0
ICONST_1
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
AASTORE
DUP
ICONST_1
ICONST_2
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
AASTORE
DUP
ICONST_2
ICONST_3
INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
AASTORE
this creates an Integer[]{1,2,3} and leaves that on the operand stack
INVOKESTATIC java/util/stream/Stream.of
([Ljava/lang/Object;)Ljava/util/stream/Stream;
this calls Stream.of with the Integer[], leaving a Stream object on the
operand stack
ALOAD 0
loads back the string from 0, now we have String on top and the Stream
as second operand
INVOKEDYNAMIC apply(Ljava/lang/String;)Ljava/util/function/Function; [
// handle kind 0x6 : INVOKESTATIC >
java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
// arguments:
(Ljava/lang/Object;)Ljava/lang/Object;,
// handle kind 0x6 : INVOKESTATIC
Test2.lambda$p$0(Ljava/lang/String;Ljava/lang/Integer;)Ljava/lang/String;,
(Ljava/lang/Integer;)Ljava/lang/String;
]
hm.... I am not too familiar with the LambdaFactory logic so I cannot
read this all too well. I see in the last two a parameters the constants
for the lambda$p$0 and its minified MethodType. the lambda has a String
and an Integer parameter and return a String. But because the String is
bound through the factory to create the value for x, the resulting
minified/cleanedup reference is (Ljava/lang/Integer;)Ljava/lang/String;
instead.
As of why there is a (Ljava/lang/Object;)Ljava/lang/Object; I do not
know. But the whole construct should take a String and give back a Function.
INVOKEINTERFACE java/util/stream/Stream.map
(Ljava/util/function/Function;)Ljava/util/stream/Stream;
till here we had Stream, Function (the String was consumed by the
lambdafactory call) on the stack, this calls map with the Function as
argument on the Stream.
POP
and here we forget about the return value....
Does this description help you?
bye Jochen