A few JRuby techniques to reduce argument boxing:
* We have specific-arity call paths for up to three arguments and with
or without a block. The compiler calls one of those when it can do so,
and calls the default [] version otherwise. This means that from the
call site down, there's 10 paths straight through to the eventual code.
* We generate method handles (about 1700 of them) for all Java-based
core class methods, wiring up the specific-arity path and default paths
to call the target Java method directly, and all others to raise arity
errors. This made managing those ten paths significantly easier. Handles
are generated based of the method signature and an annotation like this:
@JRubyMethod(name = "+") // name is optional if it matches method
public IRubyObject op_plus(IRubyObject other) { ...
More recently, the handle generation has been made "smarter", splitting
optional argument counts into separate methods. So if a method can take
one or two arguments, you can do this:
@JRubyMethod(name = "foo", required = 1, optional = 1)
public IRubyObject foo(IRubyObject[] args) { ...
but you generally would want to "arity split" the method like this:
@JRubyMethod(name = "foo")
public IRubyObject foo(IRubyObject arg) {...
@JRubyMethod(name = "foo")
public IRubyObject foo(IRubyObject arg1, IRubyObject arg2) {
A single handle is generated that dispatches one arg to the first method
and two args to the second. The handle generation is fairly intelligent,
and the generated handle does arity-checking, pre/post-method framing,
and passes through runtime structures like ThreadContext and Block if
the target method "wants" them.
* The interpreter also calls specific-arity paths when possible using a
switch on the number of actual arguments.
The reduction of argument boxing improved performance substantially, and
is largely responsible for JRuby 1.1 beating Ruby 1.9 on many benchmarks
now. We do not yet support specific-arity calling for compiled Ruby
methods or closures, which will both likely represent additional perf
boosts in the future.
On object boxing:
We currently do not do anything to avoid object boxing for primitives,
largely because of the complexity it would introduce into the entire
pipeline. We are however going to be looking at a fairly large
modification to move JRuby away from requiring all objects to implement
IRubyObject. This will require us to build a second set of call paths
throughout the system, using the IRubyObject paths for now (and in the
future when an object is known to be IRubyObject) and the Object paths
otherwise. Until we're to that point we won't be exploring primitive
boxing improvements. In general, I doubt we (I) will ever work on
keeping primitives unboxed, since the amount of effort required really
wouldn't add up to that much better an experience for Ruby users.
- 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
-~----------~----~----~----~------~----~------~--~---