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