Jochen Theodorou wrote:
> John Rose schrieb:
> [...]
>>> on the operand stack I have the GString, which needs to become a  
>>> String
>>> by calling its toString() method, which can be done by for example
>>> MyRuntime.coerceToString(Object o). And I want to call Foo#foo 
>>> (String).
>>> What this method looks to me like is that if I want to insert a  
>>> constant
>>> argument to the method call, then it is fine, because I know the value
>>> and the value won't change. But my GString is probably no compile time
>>> constant.
>> The constant you insert is a smart adapter object which you have  
>> created to perform the conversion and then invoke the ultimate target  
>> method (as another method handle).
>>
>> Sequence of events:
>>
>>    caller calls indexOf(gs1, gs2)  # two GStrings
>>    call site links to my2argConverter.convert, a bound method handle
>>    BMH calls my2argConverter.invoke(gs1, gs2)
>>    Groovy2ArgConverter.convert(gs1, gs2) does something correct to  
>> its arguments
>>    Groovy2ArgConverter.convert(gs1, gs2) then calls this.target, a  
>> DMH of String.indexOf
>>   String.indexOf(s1, s2) is called (s1 being the receiver)
>>
>> Here, Groovy2ArgConverter is a hypothetical adapter-building class  
>> which takes two arguments, performs conversions, and then calls a  
>> target MH.  The data in this class could be three MH's, one to  
>> convert each of the arguments, and which is the ultimate receiver:
>>    class Groovy2ArgConverter {
>>      MethodHandle arg1conv, arg2conv;  // called to convert the  
>> incoming arguments
>>      MethodHandle target;  // called on the converted arguments
>>      Object invoke(Object a1, Object a2) { return target.invoke 
>> (arg1conv.invoke(a1), arg2conv.invoke(a2)); }
>>    }
> 
> hmm... this way I can have my runtime single argument converter methods, 
> true. That's better already... still it adds a stack frame and if I have 
> to convert target return value, then no tail call will help me getting 
> rid of that frame I guess. I guess a common technique would then be to 
> cache such adapter to be able to reuse them... well depending on class 
> loader issues.

I'd expect you can have a single argument return converter that converts 
the value on the way out. Being able to convert only incoming arguments 
and not outgoing values wouldn't be useful.

>> This example assumes a statically linked (non-dispatching) call.  If  
>> there are multiple possible targets, 
> 
> which is the standard for Groovy, because we have our own dispatching 
> rules, that slightly differ from Java in some cases. For example we 
> allow foo(null) even if there are multiple foo methods with object 
> subclassing argument.

As does JRuby...but I think we are not formal about which method we 
select. The first best match, in reflection order, I guess.

>>    class Groovy2ArgPIC {
>>      Map<Class, MethodHandle> targets;
>>      MethodHandle lookupTarget(Class a1c, Class a2c) { ... }
>>      Object invoke(Object a1, Object a2) { return lookupTarget 
>> (a1.getClass(), a2.getClass()).invoke(a1, a2); }
>>    }
> 
> hmm... if I have a MethodHandle created by unreflect, then this handle 
> does never call another method, does it?

My understanding of an unreflected MethodHandle is that it's just a 
MethodHandle as created directly with a specific set of types. I don't 
think I understand your question...

>> See above an  
>> example which handles all possible conversion scenarios for two  
>> reference arguments; you'd need other ones for 1,3,4... argument  
>> calls.  If we can build flyby adapters that reify the argument lists  
>> into a standard form, we can build an omnibus converter which handles  
>> all kinds of argument lists.  But even if we don't get those, we can  
>> cope by creating N classes (where N<256 is the length of the longest  
>> argument list in the system).
> 
> Object, int, long, double, float... so for 1 argument being one of these 
> and one return value being one of these types I need 25 adapter classes. 
> For 2 arguments it is 125. And with three arguments I break 256 easily.

You can put more than one signature in a given class and invoke through 
it that way. There's no reason to generate a class for every single 
permutation of arity and type. Heck, they could all be in one class with 
MethodHandles to reference them. I'm not sure where the class explosion 
you're talking about comes from.

>>> what do I need these adapter classes for? In Groovy 1.5.x we don't  
>>> have
>>> them. In Groovy 1.6 we create classes at runtime, they are used for  
>>> the
>>> call site caching. But the goal must be to not to need these call site
>>> classes created at runtime. I mean if I need them anyway, why do I
>>> bother with MethodHandles?

Does Groovy still use reflection to invoke arbitrary Java methods? Then 
MethodHandles would improve performance, if nothing else. But beyond 
that if you can compost the call site logic into the handles themselves, 
you'll be able to eliminate them.

I guess I'm a little confused what it is in your call site that you feel 
you'd need to keep under invokedynamic. The prototype invokedynamic 
support already in JRuby bypasses our call site logic entirely, 
dispatching dynamically, bootstrapping, and so on. What is it about 
Groovy's call site you don't think invokedynamic/method handles can help 
with?


> I think they would be really great, but I don't know if they are doable 
> and how muich trouble they give to VM implementor.

I wouldn't worry too much about the VM implementer :)

- Charlie

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "JVM 
Languages" group.
To post to this group, send email to jvm-languages@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/jvm-languages?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to