Spread problem with > 10 arguments

Rémi Forax forax at univ-mlv.fr
Tue Jul 14 06:51:30 PDT 2009


Fredrik Öhrström a écrit :
> Rémi Forax skrev:
>   
>> It's surely a stupid question but I don't understand
>> how the VM knows that such generic method exists.
>>   
>>     
> Hmm, there are no generic methods. :-)
>
> Generic invocation, is simply that the JVM
> will allow a methodhandle callsite to
> successfully call a target where the
> arguments do not match exactly.
> This is actually the case in normal Java.
>  
> For example, if you have the method:
>     void update(long x)
> you can call it with
>     obj.update((int)42);
>     // i2l conversion at callsite
>
> and if you have:
>     void print(Object o)
> you can call it with
>     obj.print("Hello");
>     // upcast (ie no-op) at callsite
> and with:
>     obj.print(42);
>     // autoboxing and upcast
>
> These kind of calls are not possible with the
> current JSR292 proposal, since it requires
> an exact match.
>
> However generic invocation also performs
> downcasts and unboxing before entering
> the target. This makes it possible to
> have the target:
>     void print(String x);
> and call it with:
>     mh.invoke<void>((Object)"Hello");
>     // downcast to String,
>    
> and the target:
>     void update(int 42);
> and call it with:
>     mh.invoke<void>((Object)42);
>
> Obviously, the return value is  equally treated.
>
> You could say that generic invocation makes
> invoke on a methodhandle to behave
> more like a Java programmer would expect it
> to do. :-)
>
> You can also say that it introduces
> covariance/contravariance for the
> return value/arguments. (It might look
> like it introduces multivariance, but since
> anything else than co/contra variance
> will cause a class cast exception. The end
> result is exactly co/contra variance.)
>   

Ok,
generic invocation is not generic at all
(generic => Object) but more a kind of
variant invocation.


>   
>> Moreover, because generic invocation doesn't create a varargs array,
>> Do all adapters need to have 256 methods, because you can have
>> potentially a call with 255 arguments ?
>>
>>   
>>     
> Yes, this is correct. As you can see from my example
> implementations of the transforms like GuardWithTest
> in my second  blog post.
>
> I gave one impl without varargs, will have up to
> 256 methods. The other with varargs, for more
> advanced JVMs has one method.
>   

The problem is that for some adapters (by example collectArguments)
the bytecode size grow following a quadratic curve in relation to
the number of arguments.
This means that if you have more than let say 10 arguments the size of
bytecode for such adapters disable inlining which is the mother of all 
optimisations.


>> I don't agree.
>> If you take a look to adapters in MethodHandles, the code is really simple
>> and apart convert/spread/collect, you don't need this allocation.
>>
>> Furthermore, I can see another problem,
>> because adapters will internaly calls another method handle using 
>> MethodHandle.invoke,
>> there is a real risk of a cascade of boxing/unboxing if by example one 
>> method handle out of two
>> is a convertArgument.
>>   
>>     
> In fact, convertArgument will not be needed since it is,
> in effect generic invocation. But as you say, with long
> enough transform chains, there is a risk of boxing/unboxing.
>
> But I would say that even a very small interpreting
> only JVM would be able to do what you are doing in your
> backport. That is, generate an optimized call chain of
> bytecode with the correct types built in. This would be
> a JVM internal optimization not visible to the outside.
>   

A minor correction. The backport doesn't generate a call chain
but inline the method handles chain into a single block of code
containing only end method calls.

> I believe that generic invocation is backwards
> compatible with the current design. Nothing needs
> to go away except the JavaMethodHandle since it will
> no longer be necessary. It makes JSR292 behave
> more like Java and most importantly. It gives
> the dynamic language runtime programmers the
> ability to create their own transforms!
>   

Let me try to summarize :
- current spec require a == check before calling a sequence
  of adapters  that ends  with a call  to a  Java  method.
- generic invocation (variant invocation) requires
  to check the number of argument at call site and
  to ensure that only a valid method
 (contravariant of parameter types/covariant of return type)
 by inserting cast where needed.

I am not sure, the two proposal are compatible.


> //Fredrik
>   
Rémi



More information about the mlvm-dev mailing list