On Sun, Dec 5, 2010 at 9:58 AM, Subbu Sastry <[email protected]> wrote:
> So, while it is true that the runtime of a dynamic language has to
> transform the dynamic language to a typed bytecode, I think it also
> means that the rntime has to implement any optimizations (inlining,
> type guards, unboxing, EA, etc.) in the dynamic language VM which the
> JVM cannot see through.

Yes, I agree. I see the goal of "high performance" for JRuby following
a few paths (which are not mutually exclusive, and feed into one
another:

* Basic static optimization (done in a limited way already, e.g.
eliminating heap scopes when not needed, omitting frames when not
likely to be needed, etc).
* Lift dynamic calls to guard + static call based on runtime
information, to permit JVM optimizations to apply better to Ruby.
* Perform JVM-like optimizations at the bytecode level where the JVM
does not do a good enough job or where Ruby-specific behaviors are
difficult to "explain" to the JVM.

I mention the first path is already underway, in the current (fairly
naïve) static compiler we have today. Method bodies are inspected for
closures, "magic" method names like 'eval', and so on...and based on
that we can reduce the per-call overhead for those methods. More can
be done with this, but dynamic optimization is where the good stuff
comes into place.

"Dynopt", currently experimental on JRuby master, starts to take the
next step, looking at call sites being jitted and emitting both a slow
fully-dynamic path and a fast guard-plus-static-call path. This has,
in small experiments, improved performance many times
over...considerably faster than most other JVM dynlangs that do not
have opportunities to use runtime information for optimization. But
the down side is that bytecode size starts to increase very rapidly
since each dyncall is now significantly more logic.

This is where the third phase starts to come in, which we have to a
limited extent in our IR logic (thanks to Subbu) and which Rémi has
been doing with phpreboot. Here, rather than try to accommodate all
possible paths through a piece of code in the same blob of bytecode,
we can start specializing paths, introducing traced optimizations,
propagating values and types...ultimately distilling down to smaller,
less-complex bytecode as quickly as possible rather than overloading
the JVM JIT with gigantic "all-in-one" method bodies.

Bringing this back to the discussion on numeric operations against Integer...

Without more help from the JVM, the best future for optimizing boxed
math to primitive math almost certainly lies in dynamic optimization.
Only when you know at runtime that calls are being performed against
boxed numerics can you start to consistently lift those operations to
primitive math. You can, as in Groovy or Erjang, provide specialized
call paths to attempt to propagate primitives as far as possible, but
eventually things fall back into Object and you're boxed again. With
dynamic optimizations, especially bytecode-level optimization like
inlining, tracing, etc, you can propagate them as far as you like (and
Rémi has shown how far you can take this...and how powerful a tool
invokedynamic can be for making that easier).

- 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