On Mon, Nov 2, 2009 at 11:40 AM, John Wilson <[email protected]> wrote:
>
> 2009/11/2 Charles Oliver Nutter <[email protected]>:
>> Won't this break existing behavior? Currently, even if you declare a
>> type, it will still dispatch based on the runtime set of methods for
>> that type. So in your example, if I have replaced the foo() method on
>> Foo with some other piece of code, will statically declaring my
>> variables as type Foo dispatch to the original foo() method or the one
>> I've replaced? This is the conundrum I face in Ruby, where we already
...
> It's a good question!
>
> It's virtually impossible to do effective type inferencing with Groovy
> semantics. E.G. with
>
> int a = 1
> int b = 2
> def x = a + b
>
> you have no idea of the type of x. Indeed if this code is executed at
> the same time in two different threads x can end up being two
> different types (because of Categories).

Categories should be abolished, in my opinion, because they seem to be
the final sticking point for many potential improvements in Groovy.
But that's just me :)

In JRuby we don't have categories to contend with, but we do need to
be mindful of core class modifications. It is *possible* to modify the
numeric operator methods on Fixnum, but it is done so rarely in
practice that we usually don't check for it. JRuby also has an
advantage over Groovy in that we do not compile everything ahead of
time, so we can (and soon will) use profile-driven optimizations to
improve these cases, but we'll still need to have guards somewhere and
we'll still have to be fairly conservative since we can't fix-up a
currently-executing method if necessary.

> It's, at least theoretically, possible to do speculative execution of
> some classes of Groovy expression and, if you can do a cheap test to
> ensure that the operators have not been overloaded, you can get
> execution speeds within an order of magnitude of straight Java.

That's essentially what we do in JRuby now, and when running in our
fastest mode we are easily within an order of magnitude of Java for
fully-boxed math. We are nowhere close to comparing to primitive math,
which will require our newer compiler and likely also require
profile-driven optz.

> I have never seen any way of doing unguarded direct method calls in
> Groovy. It is possible to generate synthetic helper methods on a
> compiled Groovy class which can be safely called directly but these
> helper methods need to do checks before they can pass the call on to
> the target method; so you are, in effect, doing guarded calls.

JRuby essentially does this right now for math operators, checking
whether the type of the receive is Fixnum and directly dispatching.
But it's not a good general-purpose solution.

> The method dispatch problem is really difficult in Groovy because of
> the need to implement Java style method selection based on the type of
> the actual parameters (In Groovy it's based on the type of the actual
> parameter not the declared type of the variable holding the actual
> parameter - but that makes it even more difficult).

Ahh yes, this is a detail I had forgotten. Because Groovy supports
method overloading, dispatch is a much harder problem than in Ruby,
and may always be slower (at least in the presence of overloads).

For ruby-to-ruby calls in JRuby, I need only to look up a method of a
given name to find the method object I dispatch to. There's no
inspection of the parameters during dispatch at all. Generally this
means that user code needs to either check the types of incoming
arguments (using kind_of? or === or similar), or check whether they
support certain operations (using respond_to? or just calling
directly), but it does make dispatch, caching, and inlining much
simpler. As a result, ruby-to-ruby calls are generally faster than
ruby-to-java, even when the java invocations don't require coercing
any objects. Of course, all ruby-to-ruby calls avoid argument boxing,
which is impossible if you use reflection (as I believe Groovy does
for a substantial number of calls right now).

For ruby-to-java calls in JRuby, we maintain a table of incoming
arguments types and the correct target method to dispatch for those
types. The table is keyed off an aggregate hash value of the actual
argument types. This currently happens within the method object we
cache at the call site, but in the future we will actually maintain a
PIC at the call site that can quickly choose one of the most
recently-dispatched method objects.

My hope with gradual typing in JRuby is that we could start explicitly
compiling optimized and non-optimized versions of method bodies with
only trivial guards at the top. The assumption would be that if you're
explicitly typing a method, you expect the behavior at the start of
the method to match the behavior at the end of the method, and so you
don't check whether things like Fixnum#+ are changing during the
execution of the method body. That would allow us to compile numeric
logic down to primitive logic in many cases. But I expect the bulk of
these optimizations are only going to help numeric algorithms, since
our object-to-object dispatch in Ruby is only a bit slower than
non-inlined Java object-to-object dispatch right now.

- Charlie

--~--~---------~--~----~------------~-------~--~----~
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