hotspot source code - java method calls

vm/runtime/javaCalls.hpp179行,开始定义JavaCalls::call()系列方法,源码如下:

179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
// All calls to Java have to go via JavaCalls. Sets up the stack frame// and makes sure that the last_Java_frame pointers are chained correctly.//class JavaCalls: AllStatic {  static void call_helper(JavaValue* result, methodHandle* method, JavaCallArguments* args, TRAPS); public:  // Optimized Constuctor call  static void call_default_constructor(JavaThread* thread, methodHandle method, Handle receiver, TRAPS);  // call_special  // ------------  // The receiver must be first oop in argument list  static void call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS);  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); // No args  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS);  static void call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);  // virtual call  // ------------  // The receiver must be first oop in argument list  static void call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS);  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, TRAPS); // No args  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS);  static void call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);  // Static call  // -----------  static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS);  static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);  static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS);  static void call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS);  // Low-level interface  static void call(JavaValue* result, methodHandle method, JavaCallArguments* args, TRAPS);};

vm/runtime/javaCalls.cpp175行,实现JavaCalls::call()系列方法,源码如下:

175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
// ===== object constructor calls =====void JavaCalls::call_default_constructor(JavaThread* thread, methodHandle method, Handle receiver, TRAPS) {  assert(method->name() == vmSymbols::object_initializer_name(),    "Should only be called for default constructor");  assert(method->signature() == vmSymbols::void_method_signature(), "Should only be called for default constructor");  InstanceKlass* ik = method->method_holder();  if (ik->is_initialized() && ik->has_vanilla_constructor()) {    // safe to skip constructor call  } else {    static JavaValue result(T_VOID);    JavaCallArguments args(receiver);    call(&result, method, &args, CHECK);  }}// ============ Virtual calls ============void JavaCalls::call_virtual(JavaValue* result, KlassHandle spec_klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {  CallInfo callinfo;  Handle receiver = args->receiver();  KlassHandle recvrKlass(THREAD, receiver.is_null() ? (Klass*)NULL : receiver->klass());  LinkResolver::resolve_virtual_call(          callinfo, receiver, recvrKlass, spec_klass, name, signature,          KlassHandle(), false, true, CHECK);  methodHandle method = callinfo.selected_method();  assert(method.not_null(), "should have thrown exception");  // Invoke the method  JavaCalls::call(result, method, args, CHECK);}void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, TRAPS) {  JavaCallArguments args(receiver); // One oop argument  call_virtual(result, spec_klass, name, signature, &args, CHECK);}void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) {  JavaCallArguments args(receiver); // One oop argument  args.push_oop(arg1);  call_virtual(result, spec_klass, name, signature, &args, CHECK);}void JavaCalls::call_virtual(JavaValue* result, Handle receiver, KlassHandle spec_klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) {  JavaCallArguments args(receiver); // One oop argument  args.push_oop(arg1);  args.push_oop(arg2);  call_virtual(result, spec_klass, name, signature, &args, CHECK);}// ============ Special calls ============void JavaCalls::call_special(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {  CallInfo callinfo;  LinkResolver::resolve_special_call(callinfo, args->receiver(), klass, name, signature, KlassHandle(), false, CHECK);  methodHandle method = callinfo.selected_method();  assert(method.not_null(), "should have thrown exception");  // Invoke the method  JavaCalls::call(result, method, args, CHECK);}void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {  JavaCallArguments args(receiver); // One oop argument  call_special(result, klass, name, signature, &args, CHECK);}void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) {  JavaCallArguments args(receiver); // One oop argument  args.push_oop(arg1);  call_special(result, klass, name, signature, &args, CHECK);}void JavaCalls::call_special(JavaValue* result, Handle receiver, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) {  JavaCallArguments args(receiver); // One oop argument  args.push_oop(arg1);  args.push_oop(arg2);  call_special(result, klass, name, signature, &args, CHECK);}// ============ Static calls ============void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, JavaCallArguments* args, TRAPS) {  CallInfo callinfo;  LinkResolver::resolve_static_call(callinfo, klass, name, signature, KlassHandle(), false, true, CHECK);  methodHandle method = callinfo.selected_method();  assert(method.not_null(), "should have thrown exception");  // Invoke the method  JavaCalls::call(result, method, args, CHECK);}void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {  JavaCallArguments args; // No argument  call_static(result, klass, name, signature, &args, CHECK);}void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, TRAPS) {  JavaCallArguments args(arg1); // One oop argument  call_static(result, klass, name, signature, &args, CHECK);}void JavaCalls::call_static(JavaValue* result, KlassHandle klass, Symbol* name, Symbol* signature, Handle arg1, Handle arg2, TRAPS) {  JavaCallArguments args; // One oop argument  args.push_oop(arg1);  args.push_oop(arg2);  call_static(result, klass, name, signature, &args, CHECK);}// -------------------------------------------------// Implementation of JavaCalls (low level)void JavaCalls::call(JavaValue* result, methodHandle method, JavaCallArguments* args, TRAPS) {  // Check if we need to wrap a potential OS exception handler around thread  // This is used for e.g. Win32 structured exception handlers  assert(THREAD->is_Java_thread(), "only JavaThreads can make JavaCalls");  // Need to wrap each and everytime, since there might be native code down the  // stack that has installed its own exception handlers  os::os_exception_wrapper(call_helper, result, &method, args, THREAD);}void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArguments* args, TRAPS) {  // During dumping, Java execution environment is not fully initialized. Also, Java execution  // may cause undesirable side-effects in the class metadata.  assert(!DumpSharedSpaces, "must not execute Java bytecodes when dumping");  methodHandle method = *m;  JavaThread* thread = (JavaThread*)THREAD;  assert(thread->is_Java_thread(), "must be called by a java thread");  assert(method.not_null(), "must have a method to call");  assert(!SafepointSynchronize::is_at_safepoint(), "call to Java code during VM operation");  assert(!thread->handle_area()->no_handle_mark_active(), "cannot call out to Java here");  CHECK_UNHANDLED_OOPS_ONLY(thread->clear_unhandled_oops();)  // Verify the arguments  if (CheckJNICalls)  {    args->verify(method, result->get_type(), thread);  }  else debug_only(args->verify(method, result->get_type(), thread));  // Ignore call if method is empty  if (method->is_empty_method()) {    assert(result->get_type() == T_VOID, "an empty method must return a void value");    return;  }#ifdef ASSERT  { InstanceKlass* holder = method->method_holder();    // A klass might not be initialized since JavaCall's might be used during the executing of    // the <clinit>. For example, a Thread.start might start executing on an object that is    // not fully initialized! (bad Java programming style)    assert(holder->is_linked(), "rewritting must have taken place");  }#endif  assert(!thread->is_Compiler_thread(), "cannot compile from the compiler");  if (CompilationPolicy::must_be_compiled(method)) {    CompileBroker::compile_method(method, InvocationEntryBci,                                  CompilationPolicy::policy()->initial_compile_level(),                                  methodHandle(), 0, "must_be_compiled", CHECK);  }  // Since the call stub sets up like the interpreter we call the from_interpreted_entry  // so we can go compiled via a i2c. Otherwise initial entry method will always  // run interpreted.  address entry_point = method->from_interpreted_entry();  if (JvmtiExport::can_post_interpreter_events() && thread->is_interp_only_mode()) {    entry_point = method->interpreter_entry();  }  // Figure out if the result value is an oop or not (Note: This is a different value  // than result_type. result_type will be T_INT of oops. (it is about size)  BasicType result_type = runtime_type_from(result);  bool oop_result_flag = (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY);  // NOTE: if we move the computation of the result_val_address inside  // the call to call_stub, the optimizer produces wrong code.  intptr_t* result_val_address = (intptr_t*)(result->get_value_addr());  // Find receiver  Handle receiver = (!method->is_static()) ? args->receiver() : Handle();  // When we reenter Java, we need to reenable the yellow zone which  // might already be disabled when we are in VM.  if (thread->stack_yellow_zone_disabled()) {    thread->reguard_stack();  }  // Check that there are shadow pages available before changing thread state  // to Java  if (!os::stack_shadow_pages_available(THREAD, method)) {    // Throw stack overflow exception with preinitialized exception.    Exceptions::throw_stack_overflow_exception(THREAD, __FILE__, __LINE__, method);    return;  } else {    // Touch pages checked if the OS needs them to be touched to be mapped.    os::bang_stack_shadow_pages();  }  // do call  { JavaCallWrapper link(method, receiver, result, CHECK);    { HandleMark hm(thread);  // HandleMark used by HandleMarkCleaner      StubRoutines::call_stub()(        (address)&link,        // (intptr_t*)&(result->_value), // see NOTE above (compiler problem)        result_val_address,          // see NOTE above (compiler problem)        result_type,        method(),        entry_point,        args->parameters(),        args->size_of_parameters(),        CHECK      );      result = link.result();  // circumvent MS C++ 5.0 compiler bug (result is clobbered across call)      // Preserve oop return value across possible gc points      if (oop_result_flag) {        thread->set_vm_result((oop) result->get_jobject());      }    }  } // Exit JavaCallWrapper (can block - potential return oop must be preserved)  // Check if a thread stop or suspend should be executed  // The following assert was not realistic.  Thread.stop can set that bit at any moment.  //assert(!thread->has_special_runtime_exit_condition(), "no async. exceptions should be installed");  // Restore possible oop return  if (oop_result_flag) {    result->set_jobject((jobject)thread->vm_result());    thread->set_vm_result(NULL);  }}

References

  1. vm/runtime/javaCalls.hpp
  2. vm/runtime/javaCalls.cpp