[jvm-l] Re: Small static method marked not entrant, inlining reversed?

John Rose john.r.rose at oracle.com
Wed Sep 8 19:50:36 PDT 2010

On Sep 8, 2010, at 5:43 AM, Charles Oliver Nutter wrote:

> On Wed, Sep 8, 2010 at 2:29 AM, John Rose <john.r.rose at oracle.com> wrote:
>> That's exactly right.  Sounds like CHA (class hierarchy analysis) under interfaces would bail you out, at least until you created too many (>1 or >2) disjoint IRubyObject implementations.
> Yes, it sounds like exactly what I want. I'm guessing this is a "nice
> to have but not currently being worked" sort of problem, but it seems
> like a very generally-applicable improvement to Hotspot, since it's
> probably common (this would be easy to measure) to have an
> invokeinterface that receives multiple types but those types'
> implementations of that interface mostly boil down to the same
> superclass. As far as I understand it, it would help any case where
> you've extended an existing type but pass it around via some
> superclass's interface.
> A simple analysis could be done quickly too: resolve the type profile
> to the actual implementer of the interface, rather than to the exact
> type. Since invokeinterface knows what interface it's looking for, it
> could do a quick hierarchy scan to find the class that first claims to
> implement it. Generally when extending a class that already implements
> an interface, you don't re-add "implements", so this would work in a
> high percentage of cases. Does the type profile at present support
> resolving to a superclass, or does it only support resolving to an
> object's exact class?

No, it only includes exact classes.  To extend the profile would require detecting profile overflow and switching to an "inexact mode", and then teaching the optimizer to do useful stuff with those extra states.  The code generation framework is already pretty good at building the required code shapes; the missing bit is optimization policy.  This would be a good training project for someone that wanted to learn the system thoroughly.  (He said, with a hopeful look.)

>> A related problem may be either (a) the type profile doesn't collect general-enough information or (b) we don't have enough type profile points to collect specific-enough information.  We can fix (a) by collecting ever fancier profile information or (b) by splitting profile points during inlining in early tiers.
> (a) could be the "find real implementer" above as a short-term
> improvement, and later "find common superclass that implements the
> target signature". I assume the latter already works because the
> following also avoids the deopt I saw:
>    public static boolean isGenerationEqual(IRubyObject object, int
> generation) {
>        return ((RubyObject)object).getMetaClass().getCacheToken() ==
> generation;
>    }

That works (I think) because getMetaClass is monomorphic in RubyObject, and CHA is designed to detect such conditions.

If IRubyObject has just one implementor (RubyObject), we could do CHA on that implementor, and issue a dependency against new implementors of IRubyObject getting loaded.  That would be a good starter project.

> Presumably the type profile here is able to handle arbitrarily many
> subclasses of RubyObject. The above code really ought to optimize (at
> least in my case) the same as:

No, the type profile is limited to -XX:TypeProfileWidth=2 distinct classes (with associated frequency counts).  But CHA is not limited, since it doesn't have to record any history.

>    public static boolean isGenerationEqual(IRubyObject object, int
> generation) {
>        return object.getMetaClass().getCacheToken() == generation;
>    }
> I would love to see that happen (and I'm willing to help, after the
> necessary C2 learning period!), but for now I'll have to make some
> hard decisions in the JRuby codebase and compiler :(
>> (Or (c) use an explicitly controlled templating mechanism like anonymous classes.  That may prematurely multiply bytecodes, though.)
> By this you mean using a class template to specialize a piece of code
> to a common superclass *before* passing it to the optimizer?

Yes, and/or inlining at the bytecode level so as to "attract" more profiling information.   Manual inlining is a desperation move, though.

> For what it's worth, the following code is only slightly slower than
> the fastest non-hacked implementation and not subject to the
> deoptimization:
>    public static boolean isGenerationEqual(IRubyObject object, int
> generation) {
>        RubyClass metaClass;
>        if (object instanceof RubyBasicObject) {
>            metaClass = ((RubyBasicObject)object).getMetaClass();
>        } else {
>            metaClass = object.getMetaClass();
>        }
>        return metaClass.getCacheToken() == generation;
>    }

Yes, that's what the JIT might produce if it had inexact profiles.

(As I described before, in the next build or so 6912064 will make that 'instanceof' collect a new type profile.  But it won't help you here, since your 'object' value is strongly polymorphic, even though the type varies under a nice bound of RubyBasicObject.)

> But I may end up having the JRuby compiler do this since in order to
> do a direct (non-dynamic) call it has to cast to a concrete type
> anyway.

I will follow this message up with a suggestion that goes in a different direction for managing metaclasses.

-- John

More information about the hotspot-compiler-dev mailing list