Thank you everybody for the explanations; they've helped a lot.  And
I'm glad you were stuck in the airport Rémi. :|

Rob


On Aug 5, 4:27 pm, Rémi Forax <fo...@univ-mlv.fr> wrote:
> On 08/05/2012 04:54 PM, Rob N wrote:
>
> > Thanks.  It will take me a while to understand that code.  Once I do,
> > maybe I can write a performance test.  I'd like to see a comparison
> > between invokedynamic with guarded/chained method handles, as you
> > described, vs calling the dispatch logic the old fashioned way.
>
> > Rob
>
> Hi Rob,
> I'm the guy that write this piece of code an because I'm stuck in Salt
> Lake City airport for the next three hours,
> I suppose I can write something about this code.
>
> The implementation is based on two papers, [1] and [2] and
> yes, I've written my Phd thesis on multi-method in Java a long time ago.
>
> The first paper describes a way to do the multi-dispatch using a table
> based approach
> (like a vtable dispatch but more complex), so it provides a way to
> 'cover your ass', i.e.
> a way to have if no optimization tricks work to fallback to a dispatch
> algorithm which is linear to the number of parameter
> (so it doesn't depend on the number of implementations of the
> multi-method which is something important).
>
> It works like this, let say we have two methods with B extends A,
>    void foo(A a, A a2) { ... }  // impl1
>    void foo(A a, B b) { ... }   // impl2
>
> the algorithm first sort the methods using their types, here because B
> is more specific that A,
> impl2 is more specific than impl1, so the method array is { impl2, impl1 }.
>
> Then for each parameter index, you record in a hashmap for each
> available type,
> if a method implementation is applicable (can be called).
> Here, the hashmap for the first parameter contains only one key, A, and
> the corresponding
> bitset is 11 because impl2 and impl1 can be called if A is the first
> parameter.
> Using the same algorithm for the second parameters you get:
>     hash1 = { A -> 11 },
>     hash2 = { A -> 01, B -> 11 }
>
> now when the multi-dispatch is called, let say with an object of class B
> and another of class A,
>    call.foo(B,A),
> the first hashmap, hash1, doesn't contains B, in that case, follow the
> supertype hierarchy and
> try to find a supertype which is a key, here because B inherits from A,
> B will act as A,
> so you can cache (for the next call) that B -> 11 in hash1.
> the second parameter is A, so the hash entry is A -> 01,
> The result is
>    call.foo(B,A) = {11 } & { 01} = 01, so method implementation at index
> 1 should be called -> impl1
>
> so calling a multi-method should never be slower than accessing to the
> hashmap for each arguments,
> do a bitwise-and and get the lower bit set (the more specific).
>
> The real algorithm is more convoluted because you can have interfaces,
> so you can have more than
> one bitset for a class at runtime, when the array is sorted, you may
> have to introduce new implementation
> by example, for foo(A,B) and foo(B,A) the Java semantics require to
> include a third method foo(B,B)
> that will just throw an exception because foo(A,B) and foo(B,A) are not
> comparable.
>
> Moreover, there is a bunch of special case that can be used to faster
> the algorithm.
> If there is only one implementation, multi-dispatch is not necessary, if
> there is several implementation
> but only one is ever call for a callsite (the callsite is monomorphic) a
> guard with test will be faster,
> (maybe it's also the case for bi-morphic, and so on if only the receiver
> class changed)
>
> Also, if the language you want to implement is object oriented, then the
> number method applicables
> depends on the receiver class, you can use a GuardWithTest for this or
> consider the receiver class
> as a parameter too.
>
> Also, maybe for a parameter, there is only one possible class, for foo
> of our running example,
> the first parameter is always an A, in that case, it's better to not
> process a bitset for it but
> just do an instanceof check (or no check at all if you know that for a
> callsite the first parameter
> is always an A.
>
> Also, if you have only one parameter (one that can changed), in that
> case, it's better to not
> compute the set but directly store the method handle in the hash.
> For foo, it will be
>    hash2 = { A -> impl1, B -> impl2 }
> and to use the result of hashmap.get() with a fold + exactInvoker.
>
> Also, for a specific callsite, you can have primitive type in the
> signature, in that case,
> you can pre-process the bitset that will be used and insert it as a
> constant (with a insertArguments).
>
> Also, depending on your CPU, some provide an instruction for the highest
> bit, some for the number
> of trailing zeroes (latest AMD), so if the corresponding intrinsic
> exists in hotspot
> (I don't think it's true now but it may change) so you may have to sort
> the method in one order or
> in reverse order.
>
> So currently, as far as I remember, I've implemented the bitset
> algorithm but only
> if there is less than 32 implementation, so store the bitset on an int.
> The hash is thread-safe but it use a splay-tree to avoid to consume to
> much memory
> but it may be better for performance to use a hashmap (without a
> volatile access
> if there is no cache miss).
> Note that there is two flavor of the hash, one if there is no interface,
> so calling getSuperclass()
> is enough and a second one works with interfaces.
>
> And I've also implemented all the tricks listed above.
>
> cheers,
> R mi
>
> [1]http://webdocs.cs.ualberta.ca/~paullu/Papers/COOTS2001-HTML/mdj.html
> [2]http://www.jot.fm/issues/issue_2005_12/article3/
>
>
>
>
>
>
>
>
>
> > On Aug 5, 3:18 am, Charles Oliver Nutter <head...@headius.com> wrote:
> >> A simple way to do what you want might be sketched out like this:
>
> >> * The bootstrap method returns a CallSite + handle for your
> >> multi-dispatch logic contained in another method.
> >> * The multi-dispatch logic receives the actual arguments for that first 
> >> call.
> >> * Based on those arguments, you build a guarded chain of method
> >> handles that calls the right target for the incoming types, and falls
> >> back on the multi-dispatch lookup logic again if new types come in.
>
> >>  From here, you can do various combinations of guards, multiple
> >> targets, mechanisms for quickly calculating whether the incoming types
> >> have already been negotiated, and so on.
>
> >> You want to look at the bootstrap as your way to point future calls
> >> toward your own specialized logic; the bootstrap does not necessarily
> >> contain that logic.
>
> >> There's an example implementation of multi-dispatch 
> >> here:http://code.google.com/p/jsr292-cookbook/source/browse/trunk/multi-di...
>
> >> - Charlie
>
> >> On Sat, Aug 4, 2012 at 11:26 PM, Rob N <rob.nikan...@gmail.com> wrote:
> >>> Hi,
> >>> I'm trying to learn about invokedynamic and the supporting classes,
> >>> and I don't yet see how they help implement the dynamically typed
> >>> language I have in mind. From what I've read so far, when you emit an
> >>> invokedynamic instruction, you specify a bootstrap method in your
> >>> language's runtime, but that is only run once, and it must return a
> >>> MethodHandle for the CallSite.  Lets say I wanted to emit something
> >>> for a CLOS-like multiple dispatch method (foo x y), that will select
> >>> an implementation method based on the classes of x and y.  Would I not
> >>> have to return, from the bootstrap method, a handle to a method that
> >>> did that dispatch?  So why not just emit an invokevirtual or
> >>> invokestatic directly to that method?  What is the advantage of
> >>> invokedynamic here?
> >>> thanks,
> >>> Rob
> >>> --
> >>> 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 
> >>> jvm-languages+unsubscr...@googlegroups.com.
> >>> For more options, visit this group 
> >>> athttp://groups.google.com/group/jvm-languages?hl=en.

-- 
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 
jvm-languages+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/jvm-languages?hl=en.

Reply via email to