On May 18, 2010, at 1:18 PM, Charles Oliver Nutter wrote:

> One important question for me is how multi-method interfaces would be
> handled. I had originally tried to use Scala's "Function" interfaces
> in Duby to represent closures, but they all have multiple abstract
> methods that must be handled completely differently.

Right.  Here are the degrees of freedom I see at this point:
 - whether to accept SAM types which are not interfaces (default: yes)
 - whether to allow a query API for recovering a method handle from a proxy 
(default: yes)
 - whether to allow multiple methods to be associated with multiple MHs 
(default: no)
 - whether to allow multiple super types in the proxy object (default: no)
 - whether multiple methods must be individually closed, or can be mutually 
closed over another value

The reason I "stopped at one" is there are more optimization options for the 
simplified case of one-type-one-method.

Also, the query API in point 2 is harder to get right if you accept the other 
points.

But I do agree there should be a mechanism supporting the additional degrees of 
freedom.

It needs to be bulkier, though.  It probably needs multiple phases, like a 
builder.

Also, the various parts (methods, receivers) can appear at various times.

Here's a two-phase version:
   class InstanceBuilder<T,R> {
     InstanceBuilder(List<Class<? extends T>> supers, List<String> names, 
List<MethodType> types);
     InstanceBuilder(List<Class<? extends T>> supers, List<String> names, 
List<MethodType> types, Class<R> receiver);
     InstanceBuilder(List<Class<? extends T>> supers, List<String> names, 
List<MethodHandle> methods);
     T newInstance(R receiver, MethodHandle... methods);
     T newInstance(MethodHandle... methods); // no bound receiver
     T newInstance(R receiver); // previously specified methods
   }

Here's chained multi-phase version:
   class InstanceBuilder<T,R> {
     InstanceBuilder(List<Class<? extends T>> supers, List<String> names, 
List<MethodType> types);
     InstanceBuilder bindReceiver(R receiver);
     InstanceBuilder bindMethod(String name, MethodHandle method);
     T newInstance();
   }

And so on...

> I'd need to
> provide my own superclass with default behavior or have a way to
> stitch together N handles for N abstract methods.
> 
> And I agree about the language bridging...plus in the JRuby case, this
> actually makes Ruby to Ruby bridging easier:
> 
> * We need a codebase that works on Java 6
> * ...so we can't move our entire call path to using MethodHandle
> * ...so we need our own abstract "invoker" supertype
> * ...so being able to use that supertype with either generated impls
> or MethodHandle-provided impls makes it easier for us to support both
> indy and non-indy runtimes in the same implementation.

Wrapping method handles adds layers of indirection and boxing hazards as Remi 
points out.

An unsolved problem with JSR 292 is how to mix method handles in with other 
supertypes.  An excellent solution would allow you to define your own 
supertypes and APIs, and have them more or less directly mapped to method 
handles when method handles were available.  This might increase the number of 
files which could be reused (just by recompilation or relinking) across JRuby 
implementations (indy or classic).

I proposed JavaMethodHandle but as a fixed superclass it doesn't give much 
flexibility (not a mixin!).  And it constrains JVM implementations too much to 
have an inheritable subtype of MethodHandle.

Another possibility is to ask for an implicit conversion from selected 
application types X to MethodHandle.  That in effect invents a new type 
relation: delegation.  So it's no small matter.  It's hard to keep that genie 
confined to a small bottle.

> Perhaps this also helps Java 7 closures work nicer by making it
> possible to have a generic Closure or Function superclass completely
> independent of java.dyn? Or by making it possible to implement
> (faster) Java reflection with fewer generic frames under the covers
> via a single abstract supertype populated by indy?

The best way I know to accelerate Java reflective invocation is this:
        java.lang.reflect.Method foo = ...;
        try { z = MethodHandles.unreflect(foo).invokeGeneric(a, b, c, ...); }
        catch { ... }

For this to be faster, it assumes there is method handle caching on unreflect, 
which I haven't done.  But could be done.

For example, you could preserve source compatibility by making a wrapper method 
to hide MethodHandles.

> Seems like a good addition, in any case, but especially once it's
> faster and more direct than reflect.Proxy :)
> 
> - Charlie
> _______________________________________________
> mlvm-dev mailing list
> mlvm-dev@openjdk.java.net
> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to