Le 10/10/2010 20:08, Per Bothner a écrit : > So we've determined that to make use of 292 Kawa should keep its > abstract gnu.mapping.Procedure class, but add a new method: > MethodHandle asMethodHandle() > > I mis-concluded that the compiler should therefore generate code > to call asMethodHandle() and then the MethdHandle#invoke method. > However, that doesn't seem like the right way to do it. >
Why ? > Instead, given a Scheme call to an unknown Procedure f: > > (f 3 x) > > the compiler should generate (the invokedynamic bytecode > corresponding to): > > InvokeDynamic.apply(f, 3, x) > > The minimal generic CallSite support might be: > > static { Linkage.registerBootstrapMethod("kawa.lang.Dynamic", > "linkDynamic"); > > private static CallSite linkDynamic(Class caller, String name, > MethodType type) { > CallSite site = new CallSite(caller, name, type); > MethodType genericHandleType = ...; > MethodHandle genericHandle = MethodHandles.lookup() > .findStatic(Dynamic.class, "genericApply", genericHandleType); > site.setTarget(genericHandle); > return site; > } > > public static Object genericApply(Object function, Object... args) { > if (function instanceof Procedure) { > return ((Procedure) function).applyN(args); > } > else > ... handle array indexing and other "pseudo-function" types ...; > } > > So this seems like it should work and handle the generic case, but > of course there is no performance win so far. > > So the first thing we need is to replace genericApply with one that is > specialized on the actual function argument. I.e. instead of: > > return ((Procedure) function).applyN(args); > > we do: > > MethodHandle mh = ((Procedure) function).asMethodHandle(); > site.setTarget(mh); > > and so we end up doing: > > return mh.invoke(args); > > So we need to register the specialized method instead, and re-try that. > Then we need to check future calls to see if the function has changed, > and if so re-specialize. I haven't been able I haven't been able to find > a tutorial/example for that - Google is not my friend this morning. > Any cook-books out there for how to do this? > guardWithTest is the missing piece. It should be something like that: private static CallSite linkDynamic(Class caller, String name, MethodType type) { CallSite site = new CallSite(caller, name, type); MethodHandle fallback = MethodHandles.insertArguments(#fallback, 0, site); MethodHandle target = MethodHandles.collectArguments(fallback, type); site.setTarget(target); return site; } public static boolean refTest(Object procedure1, Object procedure2) { return procedure1 == procedure2; } public static Object fallback(Callsite callsite, Object procedure, Object[] args) { MethodHandle mh = ((Procedure)procedure).asMethodHandle(); MethodHandle test = MethodHandles.insertArguments(#refTest, 1, procedure); MethodHandle invoker = MethodHandles.genericInvoker(callsite.getTarget().type()); MethodHandle target = MethodHandles.insertArgument(invoker, 0, mh); target = MethodHandles.guardWithTest(test, target, fallback); callsite.setTarget(target); return mh.invokeVarargs(args); } Perhaps you need to add some conversions with convertArguments. But as I said, why do you want to use invokedynamic here ? > After that I need to figure out how to do argument conversions. The Kawa > compiler emits in each generic "apply" method necessary type conversions > before it calls the actual specific method, and the CallSite handler has > to duplicate that. > Rémi _______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev