John Rose schrieb:
> On Sep 9, 2008, at 3:33 PM, Jochen Theodorou wrote:
> 
>> On further thought I have some questions here... is it possible to  
>> have
>> custom MethodHandles? Custom in the sense of extending MethodHandle...
> 
> The answer is surprisingly simple:  Use a bound method handle.  That  
> is, use MethodHandles.insertArgument to give a plain method handle a  
> "hidden" receiver argument.

the insert I have is:

> public static MethodHandle insertArgument(MethodHandle mh,
>                                           java.lang.Object value,
>                                           int pos)
> 
> Produce a method handle which calls the original method handle, after
> inserting the given argument at the given position. The type of the new
> method handle will drop the corresponding argument type from the
> original handle's type.
> 
> The given argument object must match the dropped argument type. If
> the dropped argument type is a primitive, the argument object must be a
> wrapper, and is unboxed to produce the primitive.
> 
> The pos may range between zero and N (inclusively), where N is the
> number of argument types in mh, meaning to insert the new argument as
> the first or last (respectively), or somewhere in between.
> 
> Parameters: mh    - the method handle to invoke after the argument is
>                     inserted 
>             value - the argument to insert 
>             pos   - where to insert the argument (zero for the first) 
> Returns: a new method handle which inserts an additional argument, before
>          calling the original method handle

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. That means I can have different GStrings or the GString can 
have diferent toString representations (due to changes in referenced 
objects). So if I create a MethodHandle like this, then I would have to 
invalidate the cache as soon as the toString representation changes. 
That means the call site becomes megamorphic without changes to the 
types. This does not fell like a good solution.

> This is the way that a Runnable (or any other closure-like object,  
> including the proposed Java closures) can be converted to a method  
> handle.

hmm... I think saying closures here is openeing a can of worms that we 
should keep closed for now. I see MethodHanldes as function pointer and 
if they have some closure like functionality or not is not really 
important. I see that this insert can be used to insert constants, which 
allows a kind of currying. But I don't want to curry for each call anew...

To illustrate the problem:

static Object coerceToStringAndCall(Object receiver, Object argument, 
MethodHandle mh) {
   String string = argument.toString();
   return mh.call(receiver,string);
}

Then I can reference this by a MethodHandle and insert the MethodHandle 
I got from my method selection... but this has several problems... first 
I have one such method for only one argument, but the transformation 
might be needed for one out of n arguments at different positions. 
Meaning this won't do in general. And second... is this ok for HotSpot? 
This method is most probably used from many places with different 
MethodHandles... so this is kind of megamorphic, or not? At last 
inlining whatever mh referes must be undone very soon... only if 
coerceToStringAndCall is inlined there is a chance that the function mh 
points to can be inlined as well. And there is a third too... the return 
value. For example if I have

int foo(String x) {return x.size()}
def y=1
int x = foo("$y")

then foo would return an int and I would like to avoid boxing if 
possible. but that means mh can't return Object, that means also 
coerceToStringAndCall can't return Object. It sure isn't as problematic 
as the GString before, since there is only a limited set of primitives, 
but it increases the number of such stupid functions.

>  From there you are back to the usual game of creating lots of little  
> adapter classes.

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?

>> In fact I do not really find ways for my basic problems with the  
>> current
>> version of jsr292 I have. This is efficient single argument
>> transformation (GString to String for example), group argument
>> transformation 1->n (spreading an data structure of unknown length),
>> group argument transformation n->1 (collecting the arguments into a  
>> data structure; used for vargs calls).
> 
> Right.  The way forward for that is tricky, because the question is  
> how to divide the labor between language runtime and JVM (and their  
> respective implementors).  Current design has minimal impact on the  
> JVM, but it pushes adapter generation back onto the language  
> implementor.

letting the implementor write the adapter is ok for me, but it should be 
possible to write the adapter code as methods, not as classes and 
without having to make calls on the method handle.

[...]
> There are certain kinds of adapters (like the fancy ones you want)  
> which the JVM could help make faster and simpler, if it provided a  
> little more support.  I call a couple of them "flyby" and "ricochet"  
> adapters; haven't blogged or implemented them yet, but the idea is to  
> reify the arglist and present it to a closure for reformatting,  
> during the call.  Such a closure would be fully generic across  
> signatures, so there wouldn't be as many signature-customized  
> adapters in the system.  In any case, my goal is to push the  
> generation of calling sequence adapters under the MethodHandles  
> class, where they will in turn by handled by JVM-specific code or the  
> JVM itself.

sounds like I could use it ;)

[...]
>> ...Now the problems I have with this are simple... I need loads of  
>> custom
>> method handles for many types I have to transform. I understand  
>> that the
>> annonymous class loader is probably the idea to handle this. Also I
>> think this here will add a stack frame, or not? that's something I  
>> don't
>> want to have, because of first because of Hotspot and second  
>> because of
>> method like Class.forName(String).
> 
> The JVM will use lots of stack frames for the foreseeable future.
> 
> Consider the case of return-value coercion:  You need a stack frame  
> of some sort to mark where the thread is going to process the return  
> value, between the time the callee returns it and the caller receives  
> it (under a different type).  A simple example: boxing int to  
> Integer.  So you can do lots of *argument* coercions without pushing  
> new stack frames, but return coercions inherently require them.  Not  
> even tailcall can help there.

if you are allowed to have argument transforming "things", that can be 
chained together with the a normal method handle, then those could do 
pre- and post-processing for the MethodHandle... for example:

goal call a method given by MethodHandle mh, which requires a String and 
returns an int, with a GString and box the int after.

arguments on stack:
   Object receiver
   GString gs

code created by chaining method handles:

//flyby?
replace(1,convertGStringToString(gs))  //stack: Object, String

x=invoke mh                            //stack: int

//ricochet?
x=invoke boxInt(x)                     //stack: Integer

boxXY and convertXToY can be simple methods, taking one argument and 
returning one value, which is used to replace an arugment on the stack, 
or to replace a return value. If I could use MethoHandles like this, 
then I would not need to create any class or adapter at runtime, only 
MethodHandles. Also this has a good chance of not being changed

> I think we need a different solution for Class.forName than  
> abolishing stack frames.  There needs to be a way for trusted code to  
> run Class.forName on behalf of another class, or else for a class to  
> create a capability (method handle?) that will run Class.forName for  
> it, and hand it to the semi-trusted code that needs it.

sounds complicated

>> I would have wished for MethodHandles#coerceArguments(int pos,
>> MethodHandle converter, Class[] types):MethodHandle which takes a  
>> number
>> of arguments defined by converter from the argument stack and replaces
>> them with a number of arguments specified in type and amount by types.
> 
> Those can all be built.  One thing we need to do on the JSR 292 EG is  
> decide how many "convenience methods" get into the API, as opposed to  
> an absolutely minimal set.

if it can be build using other methods, then I have no problem with 
it... it is just that in the light of my example with the GString and it 
looks not so good.

>> ...The goal would be to not to have countless small classes and to  
>> not to have additional stack frames.
> 
> Yes.  The flyby adapter would allow a second MH (a closure) to look  
> at the argument list (reified) before the target method gets it,  
> converting and reformatting at will.  It would return before the  
> target method gets control, and so would not contribute stack frames.

yes, this sounds good.

> The ricochet adapter would give control to a second MH *after* the  
> target method gets control, receiving the return value (and possibly  
> a share of the original argument list).  This requires a new kind of  
> stack frame, and some tricky JVM support.  It would then return a  
> value to the original caller.

hmm... I may example with flyby and ricochet (if I used them correctly) 
both use the stack directly without creating new frames. I am no VM 
implementor, so I don't know if that is possible. But given, that "my" 
ricochet is simply like a method executed after mh it does not sound 
extremely complecated... in fact I would have seen more problems for the 
  flyby. Possibly the problem comes from wanting to present the original 
arguments... but that is something that is IMHO not needed or can be 
simulated by DUPing the arguments or maybe we define a predeifined 
MethodHandle which does nothing but double all arguments on the stack, 
so X1,X2,...,Xn becomes X1,X2,...,Xn,X1,X2,...,Xn.

>> I thought I saw things like these on the
>> invokedynamic early draft, but maybe I am wrong... I am not sure now,
>> because there is nothing to be seen in John's javadocs... or do I have
>> an old version?
> 
> I'll go back into spec. mode soon and we can work over the javadocs  
> together.

very good;)

bye blackdrag

-- 
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/
http://www.g2one.com/

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "JVM 
Languages" group.
To post to this group, send email to [email protected]
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