vm/runtime/javaCalls.hpp 第179行,开始定义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.cpp 第175行,实现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; } { 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"); } 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); }} |