Small static method marked not entrant, inlining reversed?

Tom Rodriguez tom.rodriguez at
Tue Sep 7 17:04:43 PDT 2010

Did you run with -XX:+PrintInlining?  That will report why we didn't inline.


On Sep 7, 2010, at 2:44 PM, Charles Oliver Nutter wrote:

> I've been working on JRuby performance lately and ran into a peculiar situation.
> I have a static utility method in JRuby that checks whether a given
> object's class is the same as the when the compiler optimized it. So
> for a snippit of code like this:
> def foo
>  bar
> end
> def bar
>  # whatever
> end
> After running for some time, the "foo" call will be compiled, the
> compiler will see that the "bar" call has a cached method handle, and
> it will emit both a dynamic call and a static-typed call plus guard.
> The static-typed call looks like this:
>    ALOAD 8
>    LDC 446
> org/jruby/javasupport/util/RuntimeHelpers.isGenerationEqual
> (Lorg/jruby/runtime/builtin/IRubyObject;I)Z
>    IFNE L2
>    ALOAD 8
>    CHECKCAST org/jruby/RubyFixnum
>    ALOAD 1
>    LDC 1
>    INVOKEVIRTUAL org/jruby/RubyFixnum.op_plus
> (Lorg/jruby/runtime/ThreadContext;J)Lorg/jruby/runtime/builtin/IRubyObject;
> And the isGenerationEqual method looks like this:
>    public static boolean isGenerationEqual(IRubyObject object, int
> generation) {
>        return object.getMetaClass().getCacheToken() == generation;
>    }
> While running benchmarks, I noticed a peculiar thing happening. For
> "fib", the method JITs in JRuby very quickly and is soon after JITed
> by Hotspot. But later compiles cause "fib" to get deoptimized and
> marked not-entrant. Around the same time, isGenerationEqual gets
> marked not entrant. Unfortunately, when fib re-optimizes, it does so
> without inlining the isGenerationEqual call, and I can see that where
> it was inlined before, it now actually does a CALL in assembly.
> Manually inlining the same bytecode everywhere isGenerationEqual would
> be called does not seem to be subject to the same effect.
> Any thoughts? The only theory I have is that early in optimization
> Hotspot sees that the target object type (IRubyObject object in the
> method def) is the same, and so it optimizes based on that. Later, as
> other compiled methods start to hit this code, the tyoe of "object"
> changes. But the logic behind the scenes should be identical in every
> case... IRubyObject.getMetaClass() only has one final implementation
> on org.jruby.RubyBasicObject, and getCacheToken() has only one final
> implementation on org.jruby.RubyModule, which simply returns an int
> field.
> So I'm stumped why at least isGenerationEqual would not inline in all cases.
> - Charlie

More information about the hotspot-compiler-dev mailing list