Lambda and JSR 292 method handle

Rémi Forax forax at univ-mlv.fr
Thu Dec 17 08:03:46 PST 2009


Le 17/12/2009 16:43, Peter Levart a écrit :
> I haven read the JSR 292 spec, so please bear with me if I talk rubbish...
>
> Ok, so in your example, the lambda was a function, so the MethodHandle is refering to a static method.
>
> In case the lambda was a closure that just referenced instance fields/methods, the MethodHandle I presume could be refering to an instance method of that instance.
>    

yes, you have a ldc virtual lambda$1(int)int.

> But what about the case where lambda was a closure closing over some local variables. I expect you would have to create a special class and instance holding all this state and refer from MethodHandle to the instance method of that class.

You don't need a class. There is a special operation named insertArguments
that allow to specify the first arguments of a method handle in order to 
create
another method handle. This operation is commonly called currying.

http://download.java.net/jdk7/docs/api/java/dyn/MethodHandles.html#insertArgument%28java.dyn.MethodHandle,%20int,%20java.lang.Object%29

Let's take an example:

class A {
    public static void main(String[] args) {
      #int(void) f = #() ( args.length );
      f();
    }
}

is translated to:

class A {
    public static void main(String[] args) {
      ldc static lambda$1(String)int
      iconst_0
      anewarray java/lang/Object
      dup
      iconst_0
      aload 0     // load args
      invokestatic MethodHandles.insertArguments(java/dyn/MethodHandle,Object[])java/dyn/MethodHandle
      astore 1
      aload 1
      aconst_2
      invokevirtual MethodHandle.invokeLambda()
      pop
    }

    private static int lambda$1(String[] args) {
      return args.length;
    }
}


the method lambda$1 takes a String[] as parameter and in the main,
args is inserted as first argument.

Rémi

>   Still this would eleminate megamorphic call sites because no interfaces would be involved and the generated class/method could be final to enable JIT inlining.
>
> Peter
>
> On Thursday 17 December 2009 15:23:55 Rémi Forax wrote:
>    
>> The function model creates one function by lambda.
>>
>> class A {
>>     public static void main(String[] args) {
>>       #int(int) f = #(int x) (x+x);
>>       f(2);
>>     }
>> }
>>
>> is translated to:
>>
>> class A {
>>     public static void main(String[] args) {
>>       ldc static lambda$1(int)int               // (1)
>>       astore 1                                  // (2)
>>       aload 1
>>       aconst_2
>>       invokevirtual A.invokeLambda(int)int            // (3)
>>       pop
>>     }
>>
>>     private static int lambda$1(int x) {
>>       return x+x;
>>     }
>> }
>>
>> I've written the body of the main in bytecode because there is non
>> equivalent in Java.
>> First, the JSR 292 define a new constant pool constant (see [2])
>> that allow to reference a function (here a static method) using opcode ldc.
>> So instantiating a lambda is just a ldc (1).
>> At runtime, this object is a java.dyn.MethodHandle, so it can be stored
>> as an object (2).
>> To call the lambda, the VM allows to call a magic method (3) named
>> invokeLambda (name may changed).
>> At runtime, the VM checks that the method handle type is compatible with
>> the type of invokeLambda
>> and call the function pointer stored in the method handle.
>>
>> Because a method handle knows its runtime type, it's possible to
>> implement instanceof and
>> cast on a function type.
>> Function type that are parametrized have the same constraint that
>> parameterized type, i.e
>> cast are unsafe.
>>
>> If function type are translated to method handle, megamorphic call site
>> problem can be solved because
>> JIT can recognize the pattern (a method that takes a method handle) and
>> do an aggressive inlining of
>> such method.
>>
>>
>> In summary, JSR 292 method handles was introduced by JSR 292 expert
>> group because it solves
>> common problems encounters when dealing with function pointer encoded
>> using interfaces.
>> It will be stupid to don't eating our own dog food.
>>
>> Rémi
>>
>>      



More information about the lambda-dev mailing list