mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
6939134: JSR 292 adjustments to method handle invocation
Split MethodHandle.invoke into invokeExact and invokeGeneric; also clean up JVM-to-Java interfaces Reviewed-by: twisti
This commit is contained in:
parent
0211f9703a
commit
4eb75c2df3
29 changed files with 413 additions and 233 deletions
|
@ -2341,7 +2341,8 @@ char* SystemDictionary::check_signature_loaders(symbolHandle signature,
|
|||
}
|
||||
|
||||
|
||||
methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature,
|
||||
methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name,
|
||||
symbolHandle signature,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
TRAPS) {
|
||||
|
@ -2352,26 +2353,28 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature,
|
|||
// create this side table lazily
|
||||
_invoke_method_table = new SymbolPropertyTable(_invoke_method_size);
|
||||
}
|
||||
unsigned int hash = invoke_method_table()->compute_hash(signature);
|
||||
vmSymbols::SID name_id = vmSymbols::find_sid(name());
|
||||
assert(name_id != vmSymbols::NO_SID, "must be a known name");
|
||||
unsigned int hash = invoke_method_table()->compute_hash(signature, name_id);
|
||||
int index = invoke_method_table()->hash_to_index(hash);
|
||||
SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature);
|
||||
SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature, name_id);
|
||||
if (spe == NULL || spe->property_oop() == NULL) {
|
||||
// Must create lots of stuff here, but outside of the SystemDictionary lock.
|
||||
if (THREAD->is_Compiler_thread())
|
||||
return NULL; // do not attempt from within compiler
|
||||
Handle mt = compute_method_handle_type(signature(),
|
||||
class_loader, protection_domain,
|
||||
CHECK_NULL);
|
||||
Handle mt = find_method_handle_type(signature(),
|
||||
class_loader, protection_domain,
|
||||
CHECK_NULL);
|
||||
KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass();
|
||||
methodHandle m = methodOopDesc::make_invoke_method(mh_klass, signature,
|
||||
methodHandle m = methodOopDesc::make_invoke_method(mh_klass, name, signature,
|
||||
mt, CHECK_NULL);
|
||||
// Now grab the lock. We might have to throw away the new method,
|
||||
// if a racing thread has managed to install one at the same time.
|
||||
{
|
||||
MutexLocker ml(SystemDictionary_lock, Thread::current());
|
||||
spe = invoke_method_table()->find_entry(index, hash, signature);
|
||||
spe = invoke_method_table()->find_entry(index, hash, signature, name_id);
|
||||
if (spe == NULL)
|
||||
spe = invoke_method_table()->add_entry(index, hash, signature);
|
||||
spe = invoke_method_table()->add_entry(index, hash, signature, name_id);
|
||||
if (spe->property_oop() == NULL)
|
||||
spe->set_property_oop(m());
|
||||
}
|
||||
|
@ -2385,10 +2388,10 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature,
|
|||
// signature, as interpreted relative to the given class loader.
|
||||
// Because of class loader constraints, all method handle usage must be
|
||||
// consistent with this loader.
|
||||
Handle SystemDictionary::compute_method_handle_type(symbolHandle signature,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
TRAPS) {
|
||||
Handle SystemDictionary::find_method_handle_type(symbolHandle signature,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
TRAPS) {
|
||||
Handle empty;
|
||||
int npts = ArgumentCount(signature()).size();
|
||||
objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty));
|
||||
|
@ -2413,16 +2416,14 @@ Handle SystemDictionary::compute_method_handle_type(symbolHandle signature,
|
|||
}
|
||||
assert(arg == npts, "");
|
||||
|
||||
// call MethodType java.dyn.MethodType::makeImpl(Class rt, Class[] pts, false, true)
|
||||
bool varargs = false, trusted = true;
|
||||
// call sun.dyn.MethodHandleNatives::findMethodType(Class rt, Class[] pts) -> MethodType
|
||||
JavaCallArguments args(Handle(THREAD, rt()));
|
||||
args.push_oop(pts());
|
||||
args.push_int(false);
|
||||
args.push_int(trusted);
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_static(&result,
|
||||
SystemDictionary::MethodType_klass(),
|
||||
vmSymbols::makeImpl_name(), vmSymbols::makeImpl_signature(),
|
||||
SystemDictionary::MethodHandleNatives_klass(),
|
||||
vmSymbols::findMethodHandleType_name(),
|
||||
vmSymbols::findMethodHandleType_signature(),
|
||||
&args, CHECK_(empty));
|
||||
return Handle(THREAD, (oop) result.get_jobject());
|
||||
}
|
||||
|
@ -2430,29 +2431,34 @@ Handle SystemDictionary::compute_method_handle_type(symbolHandle signature,
|
|||
|
||||
// Ask Java code to find or construct a java.dyn.CallSite for the given
|
||||
// name and signature, as interpreted relative to the given class loader.
|
||||
Handle SystemDictionary::make_dynamic_call_site(KlassHandle caller,
|
||||
int caller_method_idnum,
|
||||
int caller_bci,
|
||||
Handle SystemDictionary::make_dynamic_call_site(Handle bootstrap_method,
|
||||
symbolHandle name,
|
||||
methodHandle mh_invdyn,
|
||||
methodHandle signature_invoker,
|
||||
Handle info,
|
||||
methodHandle caller_method,
|
||||
int caller_bci,
|
||||
TRAPS) {
|
||||
Handle empty;
|
||||
// call java.dyn.CallSite::makeSite(caller, name, mtype, cmid, cbci)
|
||||
Handle caller_mname = MethodHandles::new_MemberName(CHECK_(empty));
|
||||
MethodHandles::init_MemberName(caller_mname(), caller_method());
|
||||
|
||||
// call sun.dyn.MethodHandleNatives::makeDynamicCallSite(bootm, name, mtype, info, caller_mname, caller_pos)
|
||||
oop name_str_oop = StringTable::intern(name(), CHECK_(empty)); // not a handle!
|
||||
JavaCallArguments args(Handle(THREAD, caller->java_mirror()));
|
||||
JavaCallArguments args(Handle(THREAD, bootstrap_method()));
|
||||
args.push_oop(name_str_oop);
|
||||
args.push_oop(mh_invdyn->method_handle_type());
|
||||
args.push_int(caller_method_idnum);
|
||||
args.push_oop(signature_invoker->method_handle_type());
|
||||
args.push_oop(info());
|
||||
args.push_oop(caller_mname());
|
||||
args.push_int(caller_bci);
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_static(&result,
|
||||
SystemDictionary::CallSite_klass(),
|
||||
vmSymbols::makeSite_name(), vmSymbols::makeSite_signature(),
|
||||
SystemDictionary::MethodHandleNatives_klass(),
|
||||
vmSymbols::makeDynamicCallSite_name(),
|
||||
vmSymbols::makeDynamicCallSite_signature(),
|
||||
&args, CHECK_(empty));
|
||||
oop call_site_oop = (oop) result.get_jobject();
|
||||
assert(call_site_oop->is_oop()
|
||||
/*&& java_dyn_CallSite::is_instance(call_site_oop)*/, "must be sane");
|
||||
java_dyn_CallSite::set_vmmethod(call_site_oop, mh_invdyn());
|
||||
if (TraceMethodHandles) {
|
||||
#ifndef PRODUCT
|
||||
tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop);
|
||||
|
@ -2463,9 +2469,7 @@ Handle SystemDictionary::make_dynamic_call_site(KlassHandle caller,
|
|||
return call_site_oop;
|
||||
}
|
||||
|
||||
Handle SystemDictionary::find_bootstrap_method(KlassHandle caller,
|
||||
KlassHandle search_bootstrap_klass,
|
||||
TRAPS) {
|
||||
Handle SystemDictionary::find_bootstrap_method(KlassHandle caller, TRAPS) {
|
||||
Handle empty;
|
||||
if (!caller->oop_is_instance()) return empty;
|
||||
|
||||
|
@ -2476,57 +2480,12 @@ Handle SystemDictionary::find_bootstrap_method(KlassHandle caller,
|
|||
if (TraceMethodHandles) {
|
||||
tty->print_cr("bootstrap method for "PTR_FORMAT" cached as "PTR_FORMAT":", ik(), boot_method_oop);
|
||||
}
|
||||
NOT_PRODUCT(if (!boot_method_oop->is_oop()) { tty->print_cr("*** boot MH of "PTR_FORMAT" = "PTR_FORMAT, ik(), boot_method_oop); ik()->print(); });
|
||||
assert(boot_method_oop->is_oop()
|
||||
&& java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane");
|
||||
return Handle(THREAD, boot_method_oop);
|
||||
}
|
||||
boot_method_oop = NULL; // GC safety
|
||||
|
||||
// call java.dyn.Linkage::findBootstrapMethod(caller, sbk)
|
||||
JavaCallArguments args(Handle(THREAD, ik->java_mirror()));
|
||||
if (search_bootstrap_klass.is_null())
|
||||
args.push_oop(Handle());
|
||||
else
|
||||
args.push_oop(search_bootstrap_klass->java_mirror());
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_static(&result,
|
||||
SystemDictionary::Linkage_klass(),
|
||||
vmSymbols::findBootstrapMethod_name(),
|
||||
vmSymbols::findBootstrapMethod_signature(),
|
||||
&args, CHECK_(empty));
|
||||
boot_method_oop = (oop) result.get_jobject();
|
||||
|
||||
if (boot_method_oop != NULL) {
|
||||
if (TraceMethodHandles) {
|
||||
#ifndef PRODUCT
|
||||
tty->print_cr("--------");
|
||||
tty->print_cr("bootstrap method for "PTR_FORMAT" computed as "PTR_FORMAT":", ik(), boot_method_oop);
|
||||
ik()->print();
|
||||
boot_method_oop->print();
|
||||
tty->print_cr("========");
|
||||
#endif //PRODUCT
|
||||
}
|
||||
assert(boot_method_oop->is_oop()
|
||||
&& java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane");
|
||||
// probably no race conditions, but let's be careful:
|
||||
if (Atomic::cmpxchg_ptr(boot_method_oop, ik->adr_bootstrap_method(), NULL) == NULL)
|
||||
ik->set_bootstrap_method(boot_method_oop);
|
||||
else
|
||||
boot_method_oop = ik->bootstrap_method();
|
||||
} else {
|
||||
if (TraceMethodHandles) {
|
||||
#ifndef PRODUCT
|
||||
tty->print_cr("--------");
|
||||
tty->print_cr("bootstrap method for "PTR_FORMAT" computed as NULL:", ik());
|
||||
ik()->print();
|
||||
tty->print_cr("========");
|
||||
#endif //PRODUCT
|
||||
}
|
||||
boot_method_oop = ik->bootstrap_method();
|
||||
}
|
||||
|
||||
return Handle(THREAD, boot_method_oop);
|
||||
return empty;
|
||||
}
|
||||
|
||||
// Since the identity hash code for symbols changes when the symbols are
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue