On Fri, Feb 18, 2011 at 7:19 AM, Christian Thalinger <christian.thalin...@oracle.com> wrote: > What I can tell so far is that setting rubyDirect=true inlines a whole lot > more stuff than without. I looks like it wants to inline all recursive calls > of fib_ruby into a single method, which doesn't work very well, hitting two > limits: NodeCountInliningCutoff and DesiredMethodLimit. > > I tried to bump these limits but that is a dead end for the compiler since at > one point it skips the compile because it gets too many nodes: > > 43 COMPILE SKIPPED: out of nodes parsing method (not retryable) > > I don't know why it wants to inline all these recursive calls. Is that > something JRuby tries to do?
Nope, we're not doing anything special there. Here's the basic layout (review for you perhaps): Prior to this work, invokedynamic connected the call sites up to our existing DynamicMethod objects via the "call" method. In most cases, those objects were a unique class per method, to allow things to inline, but ultimately they added one or two intermediate frames to every indy call path. You can see that in my previous email. In between then and now, I worked on "dynopt". Dynopt in JRuby basically takes the last-seen method at a call site while interpreting and inserts a guard, direct call to that method (*really* direct...invokevirtual or invokestatic), and fallback to the old call site logic. This worked for native core methods with fixed arities and no closure, a few "intrinsics", self-recursing calls (fib, tak), and Float and Fixnum dispatches with or without a boxed argument. It also inlined directly any trivial leaf methods (constant return value, simple state lookups, etc). This work improved the performance of small benchmarks substantially, and the largest part of that improvement came from being able to directly make recursive calls. The new indy work in JRuby basically takes the direct-binding part of that work and uses it to patch invokedynamic all the way through, skipping DynamicMethod. It works for the cases I listed in my email to Rémi: basically any fixed-arity, no-block, core class or Ruby-to-Ruby calls. Next I was going to explore patching Ruby to Java calls all the way through as well. At *best* this logic does nothing more than remove as many intermediate frames between the caller and target. We do no manual inlining (except for the trivial leaf cases), and are simply connecting A with B. On the one hand I'm thrilled to see that a lot of stuff is inlining. With only a tiny amount of work, Ruby calls can inline into Ruby calls, with very little intervening overhead. But on the other hand, I'm not sure what I should expect to see from a performance perspective. "dynopt" inlines Ruby into Ruby as well, at the cost of a lot of bytecode in each Ruby method body, eating up that precious budget. I would have expected the Ruby-to-Ruby inlining via invokedynamic to perform as well or better than dynopt. I'm not grousing about performance, mind you :) I think it's just awesome how cleanly this is working so far with not a whole lot of effort. I'm champing at the bit to make all of JRuby invokedynamic-aware. But obviously the perf is not as good as we'd expect it, and I'm standing by to help provide information or experiment to improve it. FWIW, you can specify jruby.compile.dynopt=true to turn on dynopt for benchmarks, if you'd like to compare with indy. It can take longer to ramp up, since it forces 100% JIT (no force-compiling the target script immediately), which is then subject to a hard 50-invocation threshold. - Charlie _______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev