Question on HotSpot JIT and invokeinterface
John Rose
John.Rose at Sun.COM
Thu Feb 26 11:32:34 PST 2009
On Feb 24, 2009, at 11:58 PM, Pekka Enberg wrote:
> There's a nice description of how HotSpot implements JIT'ed
> invokeinterface
> at HotSpot Internals wiki:
>
> http://wikis.sun.com/display/HotSpotInternals/InterfaceCalls
Please add your discoveries to it! Part of the benefit of the wiki is
that people can share their "learning curves", so we don't all have to
rediscover the same things.
> Unfortunately there are no pointers to the actual code.
It's easy enough to make pointers, at least at the file level:
http://hg.openjdk.java.net/jdk7/hotspot/hotspot/file/tip/src/cpu/x86/vm/vtableStubs_x86_32.cpp
(Too bad URLs can't end with tags-like search terms, as **.cpp#/
create_itable_stub.)
> I recently started
> looking at how the interface resolution stubs are generated and
> spent quite
> a lot of time figuring out what was going on!
Yes, it takes a lot of time. The wiki is there to help the second
person in line. :-)
> I think I got it mostly right but thought I thought I'd get a second
> opinion. Maybe this is something that could be added to the wiki as
> well?
It looks good. Please feel free to add it, in some useful form, to
the wiki.
> ---
>
> [Assuming 32-bit x86 here.]
>
> I think it's the VtableStubs::create_itable_stub() function in
> src/cpu/x86/vm/vtableStubs_x86_32.cpp. Tracing trough the the
> callers in
> reverse order, we have:
>
> VtableStubs::create_itable_stub()
> VtableStubs::create_stub()
> CompiledIC::set_to_megamorphic()
> SharedRuntime::handle_ic_miss_helper()
> SharedRuntime::handle_wrong_method_ic_miss()
The megamorphic state is the final catch-all state for a CompiledIC
(compiled inline cache). The header file that documents the (highly
interesting!) state transitions is:
http://hg.openjdk.java.net/jdk7/hotspot/hotspot/file/tip/src/share/vm/code/compiledIC.hpp
States before megamorphic are clean (fresh from compiler) and
monomorphic (common case). An inline cache miss transitions the call
site to megamorphic.
> and in src/cpu/x86/vm/sharedRuntime_x86_32.cpp we have
>
> SharedRuntime::generate_stubs()
>
> that generates a resolve blob that points to
> SharedRuntime::handle_wrong_method_ic_miss():
>
> _ic_miss_blob = generate_resolve_blob(
> CAST_FROM_FN_PTR(
> address, SharedRuntime::handle_wrong_method_ic_miss),
> "ic_miss_stub");
>
> Now the IC miss stub is called if we can't find a method in the
> inline cache.
> The instruction sequence of _ic_miss_blob is returned by:
>
> static address SharedRuntime::get_ic_miss_stub() {
> assert(_ic_miss_blob!= NULL, "oops");
> return _ic_miss_blob->instructions_begin();
> }
>
> Looking at a reverse call-graph:
>
> SharedRuntime::get_ic_miss_stub()
> SharedRuntime::generate_i2c2i_adapters()
> AdapterHandlerLibrary::get_create_adapter_index()
> AdapterHandlerLibrary::get_adapter()
> methodOopDesc::make_adapters()
>
> we can see how a method oop adapter has a pointer to the IC miss stub.
The rest of this is wonderful too, but belongs on a new page or pages,
such as CallsIntoJava and/or CallTransitions.
> To
> complete the explanation, lets look at how HotSpot loads a Java
> class and jumps
> into the main() method:
>
> src/os/linux/launcher/java.c::main()
> src/os/linux/launcher/java.c::CallStaticVoidMethod()
> src/share/vm/prims/jni.cpp::jni_invoke_static()
> src/share/vm/runtime/javaCalls.cpp::JavaCalls::call()
> src/share/vm/runtime/javaCalls.cpp::JavaCalls::call_helper()
>
> Now JavaCalls::call_helper() does:
>
> src/share/vm/runtime/stubRoutines.hpp::StubRoutines::call_stub()
>
> which returns a function pointer to a stub and calls that. The call
> stub in
> turn delegates to is something called the entry point which is
> obtained in JavaCalls::call_helper() as follows:
>
> address entry_point = method->from_interpreted_entry();
>
> Now when a method is compiled into native code, the
>
> src/share/vm/ci/ciEnv.cpp:ciEnv::register_method()
>
> function calls
>
> src/share/vm/oops/methodOop.cpp::methodOopDesc::set_code()
>
> which sets up _from_interpreted_entry like this:
>
> mh->_from_interpreted_entry = mh->get_i2c_entry();
>
> where get_i2_c_entry() looks like this:
>
> address methodOopDesc::get_i2c_entry() {
> assert(_adapter != NULL, "must have");
> return _adapter->get_i2c_entry();
> }
>
> The _adapter of type class AdapterHandlerEntry which are created in
>
> src/cpu/x86/vm/
> sharedRuntime_x86_32.cpp::SharedRuntime::generate_i2c2i_adapters()
>
> which we know already to jump to a stub returned by
> SharedRuntime::get_ic_miss_stub() if a method cannot be found in the
> inline cache.
>
> ---
>
> That's it! Comments and corrections are most appreciated!
Please post!
Best wishes,
-- John
> Regards,
>
> Pekka
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/hotspot-dev/attachments/20090226/24dc5a0e/attachment.html
More information about the hotspot-dev
mailing list