SwitchPoint-based constant lookup in JRuby
Charles Oliver Nutter
headius at headius.com
Thu May 19 11:11:50 PDT 2011
In Ruby, constants...aren't. They're *mostly* constant, but they have
to be looked up dynamically via the lexical scope and self class
hierarchy. They can be changed after the fact, and class modifications
like mixing in a module later will change the scenery, but these sorts
of changes are very rare (and generally don't happen at all once the
app reaches steady state).
So they *usually* aren't modified after first lookup, but they *can* be.
Previously in JRuby, we used a global int to indicate the "generation"
of constants in the system. Any constant modification anywhere in the
system triggers a generation update, and subsequent constant lookups
will re-cache the value. This works great, but obviously incurs the
cost of digging up the current constant generation and comparing it
with the one we cached.
I've just landed a newer SwitchPoint-based constant caching mechanism.
https://github.com/jruby/jruby/commit/90be178c96053d201ea2a869bda7feddeedcfa10
Rather than constantly pinging a generation number, it uses a
SwitchPoint GWT to invalidate all constants in the system. In theory,
if I'm understanding how Hotspot will optimize SwitchPoint, this
should basically be a zero-cost guard. Also, it binds the constant
directly via MethodHandles.constant, so there's minimum indirection to
get at the value.
So far I'm very happy with how easy this has been. I have several
other lazily-looked-up or lazily-initialized values in JRuby that
could be bound via MethodHandles.constant directly into a call site.
I'd show you assembly and perf numbers for this, but I haven't been
able to pull down the upstream fixes for ShouldNotReachHere yet.
Hopefully soon.
Anyway, it might be illustrative for others interested in using
SwitchPoint this way.
- Charlie
More information about the mlvm-dev
mailing list