another question about megamorphic call sites in combination with MethodHandles

Remi Forax forax at univ-mlv.fr
Sat Mar 23 08:47:38 PDT 2013


On 03/23/2013 04:30 PM, Peter Levart wrote:
>
> On 03/22/2013 11:50 AM, Remi Forax wrote:
>> On 03/22/2013 11:12 AM, Jochen Theodorou wrote:
>>> Am 22.03.2013 10:35, schrieb Remi Forax:
>>>> On 03/22/2013 10:24 AM, Jochen Theodorou wrote:
>>>>> Am 22.03.2013 10:11, schrieb Remi Forax:
>>>>> [...]
>>>>>> I don't think it's a good idea to expose directly method handles to users,
>>>>>> it's better to encapsulate it into a Groovy object corresponding to a
>>>>>> function or a closure so you can add a bunch of invoke overloads.
>>>>> what invoke overloads are you thinking of here?
>>>> traditionnal ones,
>>>> invoke(Object)
>>>> invoke(Object,Object)
>>>> ...
>>>> invoke(Object...)
>>> Well, I would probably use different name, to avoid the problem of
>>> having a call with a single argument being an Object[] but then done
>>> with invoke(Object...), which would use the array elements as arguments
>>> instead of the array itself.
>> the usual trick to fall into that trap is to have two forms:
>>     invoke(Object[]) and invoke(Object, Object...)
>>
>>> We have this problem in Closure#call
>>> already, if done from Java... Which is why the method will go. Our
>>> groovy.lang.Closure will become only a thin wrapper ideally.
>>>
>>> Anyway... so you suggest having a general class we can use for
>>> invocations, then make some method to request the invoker, which will
>>> produce a subclass, with an implementation that can call the target?
>> In my opinion, your closure object should be a wrapper around a
>> MethodHandle.
>> You should keep the call method (and even add several overloads) as a
>> generic call mechanism with no inline optimisation. For the overload
>> like call(Object), the call will be like a function call,
>> so not something too bad.
>>
>> And if a user want a call to a specific closure to be inlined, the user
>> should request a specific SAM implemented using a similar trick that the
>> Java lambda will do (maybe?).
>> The idea is to generate and reuse the same class for all instances of
>> the same SAM interface with that the call of a method of the interface
>> will be usually mono-morphic and inside the method of the generated
>> class an invokedynamic will call the method handle that is inside the
>> SAM proxy.
>> Because it's an invokedynamic, it can cache several method handle in
>> order to inline them with a guardWithTest that test method handle
>> instances instead of checking object class as usual.
>
> Hi Remi,
>
> So how is this going to work? I mean the dispatch. If one SAM class is 
> going to dispatch to several MethodHandle instances, how would that be 
> more optimal then calling an interface method on several 
> implementations (classes implementing the method), each calling it's 
> target method directly or using a constant MethodHandle?

It's not more efficient than a classical inlining cache with one proxy 
class by method handle,
the idea is just to avoid to generate one proxy classes by method handle.
Also, you have a littel more freedom, Hotspot uses a bimorphic cache, 
here you can use a 5-morphic cache if you want.

But it will not solve neither the general problem of megamorphic 
callsite. To solve that the VM or the runtime need to be able to have 
different profiles for one code, this can be done by trace profiling
(like PHP.reboot does), or by code splitting (if a code contains a 
polymorphic callsite and the receiver is a parameter of the method, the 
runtime duplicates the code at each callsite with a fresh profile (the 
result is a kind of backward inlining)).

>
> Regards, Peter

cheers,
Rémi



More information about the mlvm-dev mailing list