MethodHandles.constant not inlining?
Charles Oliver Nutter
headius at headius.com
Tue Jun 7 22:44:09 PDT 2011
Simplest way to show it is to show it.
For a simple Fixnum literal, lazily initialized when first encountered:
jruby -e "puts 1"
Bytecode emitted:
ALOAD 1 (this is ThreadContext)
INVOKEDYNAMIC getFixnum
(Lorg/jruby/runtime/ThreadContext;)Lorg/jruby/RubyFixnum;
[org/jruby/runtime/invokedynamic/InvokeDynamicSupport.getFixnumBootstrap(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;J)Ljava/lang/invoke/CallSite;
(6), 1]
ARETURN
The bootstrap method:
public static CallSite getFixnumBootstrap(MethodHandles.Lookup
lookup, String name, MethodType type, long value) {
MutableCallSite site = new MutableCallSite(type);
MethodHandle init = findStatic(
InvokeDynamicSupport.class,
"initFixnum",
MethodType.methodType(RubyFixnum.class,
MutableCallSite.class, ThreadContext.class, long.class));
init = MethodHandles.insertArguments(init, 2, value);
init = MethodHandles.insertArguments(
init,
0,
site);
site.setTarget(init);
return site;
}
The initFixnum method, called once only:
public static RubyFixnum initFixnum(MutableCallSite site,
ThreadContext context, long value) {
RubyFixnum rubyFixnum = context.runtime.newFixnum(value);
site.setTarget(MethodHandles.dropArguments(MethodHandles.constant(RubyFixnum.class,
rubyFixnum), 0, ThreadContext.class));
return rubyFixnum;
}
That's pretty much it. The test I ran looks like this:
def foo
1
end
100_000.times {
foo
}
The body of the block passed to "times" jits (in Hotspot) and appears
to inline the "foo" method just fine, but the body of the inlined
"foo" logic contains that call I gisted in my earlier post.
Looking at the PrintAssemblyOutput at the point of that suspicious callq:
0x0000000102896e97: callq 0x0000000102837820 ; OopMap{[48]=Oop
[72]=Oop [80]=Oop [88]=NarrowOop [112]=Oop [120]=NarrowOop off=924}
;*invokedynamic
; -
test::method__0$RUBY$foo at 1 (line 2)
; -
java.lang.invoke.MethodHandle::invokeExact at 6
; -
java.lang.invoke.MethodHandle::invokeExact at 33
; -
test::block_0$RUBY$__file__ at 23 (line 6)
; -
test$block_0$RUBY$__file__::call at 9 (line 65535)
; -
org.jruby.runtime.CompiledBlock::yield at 49 (line 112)
; -
org.jruby.runtime.CompiledBlock::yield at 9 (line 95)
; {optimized virtual_call}
0x0000000102896e9c: mov %rbp,%rsp ;*invokedynamic
; -
test::method__0$RUBY$foo at 1 (line 2)
; -
java.lang.invoke.MethodHandle::invokeExact at 6
; -
java.lang.invoke.MethodHandle::invokeExact at 33
; -
test::block_0$RUBY$__file__ at 23 (line 6)
; -
test$block_0$RUBY$__file__::call at 9 (line 65535)
; -
org.jruby.runtime.CompiledBlock::yield at 49 (line 112)
; -
org.jruby.runtime.CompiledBlock::yield at 9 (line 95)
0x0000000102896e9f: mov %rax,%r9
0x0000000102896ea2: jmp 0x0000000102896eae
0x0000000102896ea4: movabs $0x7f5a30538,%r9 ;*areturn
; -
test::method__0$RUBY$foo at 6 (line 2)
; -
java.lang.invoke.MethodHandle::invokeExact at 6
; -
java.lang.invoke.MethodHandle::invokeExact at 33
; -
test::block_0$RUBY$__file__ at 23 (line 6)
; -
test$block_0$RUBY$__file__::call at 9 (line 65535)
; -
org.jruby.runtime.CompiledBlock::yield at 49 (line 112)
; -
org.jruby.runtime.CompiledBlock::yield at 9 (line 95)
; {oop(a
'org/jruby/RubyFixnum')}
Note that the output all indicates this is happening on line 2, which
is the invokedynamic-based "getFixnum" logic for the literal "1".
Is there something I'm doing wrong here?
- Charlie
On Wed, Jun 8, 2011 at 12:22 AM, John Rose <john.r.rose at oracle.com> wrote:
> On Jun 7, 2011, at 3:38 PM, Charles Oliver Nutter wrote:
>
>> So I figured I'd check assembly output, and I was surprised to see a
>> callq right where I expect to see the literal. Are
>> MethodHandle.constant handles not inlined right now?
>
> Here is what constant(Object.class, foo) reduces to:
> #wellKnownIdentityFn.bindTo(foo)
>
> This should inline very nicely.
>
> What is the type you pass to MHs.constant? If it's not Object, call it T.
>
> In the case of a type other than Object, we have:
> rawRetype(#wellKnownIdentityFn, methodType(T, T)).bindTo(foo)
>
> where rawRetype is an internal trusted constructor which asserts that the result is trusted to be T, not just Object. This should inline also. There's a potential problem here: The methodHandleWalk module will emit a return of an Object value (from wellKnownIdentityFn, not its real name) from an adapter that returns a value of type T. This bytecode would be rejected by the verifier, but I don't think the verifier runs on MH graphs.
>
> Maybe the methodHandleWalk modules is tripping over some aspect of this MH graph or the resulting bytecode.
>
> -- John
> _______________________________________________
> mlvm-dev mailing list
> mlvm-dev at openjdk.java.net
> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev
>
More information about the mlvm-dev
mailing list