Lambda translation

Rémi Forax forax at univ-mlv.fr
Sun Apr 22 14:58:15 PDT 2012


On 04/22/2012 11:05 PM, Brian Goetz wrote:
> Thanks for the corrections.  More inline.
>
>> In section "varargs", there is no need for a bridge
>> because if the strategy is "inner classes", the bridge code
>> can be inserted in the generated method of the proxy
>> and if the strategy uses method handle you can use
>> regular combiners.
>
> Right, at first I thought this argument was a slam-dunk for "do all 
> the work in the metafactory" (given that MethodHandle.asType can do a 
> varargs transformation.)  But as I worked through the details on when 
> a call is a varargs call and when it is not, I realized that there is 
> information the compiler has that is harder to reconstruct at runtime.

Methodhandle.asFixedArity() is what you are looking for.

> I think this one is one which will look warty either way, whether we 
> do some/all/none of the work in the compiler and the remaining 
> some/none/all in the runtime.

It's always better to do adaptation at runtime.
The runtime will not be able to know the the real intent if the compiler 
do adaptation
so you loose information. The VM does adaptation better than the compiler
(because it can teach the JIT, the information can be carried on to the 
JIT).
So adaptation you only be done at runtime or you lost optimization 
opportunity.

>
>> For method reference, it's more complex because the compiler can't add
>> the ACC_LAMBDA after the fact, perhaps only public method of public 
>> class
>> can be serialized.
>
> Yep, this is one of the considerations that drove me to prefer the 
> proposed approach -- it doesn't result in weird restrictions on what 
> the user can do, nor does it result in strange sometimes-public, 
> sometimes-private desugarings.

The other solution is to let the compiler generates an accessor method 
(flagged with ACC_LAMBDA)
exactly like it generates one when you access to a private field of an 
enclosing method.

[...]
>
> And, all of this will have to be thoroughly explored by the security 
> experts.

And performance experts ...
At least, the references to the SAM class, SAM method desc, etc, can be 
encoded into
one unique string (and btw you don't have to test the method handle ref 
kind because
you can't encode in the same class two methods with the same name + same 
descriptor
but one static and the other non static).

|     private static Object $deserialize$(SerializableLambda lambda) {
         switch(lambda.getMangled) {
         case "||com/foo/SerializableComparator.compare(LObject;)I||;com/foo/Foo.lambda$1(LString;LString)I":
                      return indy(MH(serializableMetafactory),
                                  MH(invokeVirtual SerializableComparator.compare),
                                  MH(invokeStatic lambda$1))(lambda.getCapturedArgs()));
             break;

         ...
         }
         throw new ...;
     }|

There is also another problem because classes are checked by their name,
moving an abstract method of an interface into a super-interface will be
no more binary compatible.

Rémi



More information about the lambda-dev mailing list