Question on HotSpot JIT and invokeinterface

Pekka Enberg penberg at cs.helsinki.fi
Tue Feb 24 23:58:40 PST 2009


Hi all,

I have a question regarding HotSpot JIT and invokeinterface.

There's a nice description of how HotSpot implements JIT'ed invokeinterface
at HotSpot Internals wiki:

  http://wikis.sun.com/display/HotSpotInternals/InterfaceCalls

Unfortunately there are no pointers to the actual code. 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!

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?

---

[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()

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. 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!

Regards,

                        Pekka




More information about the hotspot-dev mailing list