6939196: method handle signatures off the boot class path get linkage errors

Adjust MethodType lookup logic to search off the BCP, but not to cache those results

Reviewed-by: twisti
This commit is contained in:
John R Rose 2010-05-01 21:57:35 -07:00
parent 4eb75c2df3
commit 973b1ef143
7 changed files with 150 additions and 47 deletions

View file

@ -2343,12 +2343,9 @@ char* SystemDictionary::check_signature_loaders(symbolHandle signature,
methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name,
symbolHandle signature,
Handle class_loader,
Handle protection_domain,
KlassHandle accessing_klass,
TRAPS) {
if (!EnableMethodHandles) return NULL;
assert(class_loader.is_null() && protection_domain.is_null(),
"cannot load specialized versions of MethodHandle.invoke");
if (invoke_method_table() == NULL) {
// create this side table lazily
_invoke_method_table = new SymbolPropertyTable(_invoke_method_size);
@ -2358,30 +2355,36 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle 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, name_id);
methodHandle non_cached_result;
if (spe == NULL || spe->property_oop() == NULL) {
spe = 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 = find_method_handle_type(signature(),
class_loader, protection_domain,
CHECK_NULL);
bool found_on_bcp = false;
Handle mt = find_method_handle_type(signature(), accessing_klass, found_on_bcp, CHECK_NULL);
KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass();
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.
{
if (found_on_bcp) {
MutexLocker ml(SystemDictionary_lock, Thread::current());
spe = invoke_method_table()->find_entry(index, hash, signature, name_id);
if (spe == NULL)
spe = invoke_method_table()->add_entry(index, hash, signature, name_id);
if (spe->property_oop() == NULL)
spe->set_property_oop(m());
} else {
non_cached_result = m;
}
}
methodOop m = (methodOop) spe->property_oop();
assert(m->is_method(), "");
return m;
if (spe != NULL && spe->property_oop() != NULL) {
assert(spe->property_oop()->is_method(), "");
return (methodOop) spe->property_oop();
} else {
return non_cached_result();
}
}
// Ask Java code to find or construct a java.dyn.MethodType for the given
@ -2389,30 +2392,50 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name,
// Because of class loader constraints, all method handle usage must be
// consistent with this loader.
Handle SystemDictionary::find_method_handle_type(symbolHandle signature,
Handle class_loader,
Handle protection_domain,
KlassHandle accessing_klass,
bool& return_bcp_flag,
TRAPS) {
Handle class_loader, protection_domain;
bool is_on_bcp = true; // keep this true as long as we can materialize from the boot classloader
Handle empty;
int npts = ArgumentCount(signature()).size();
objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty));
int arg = 0;
Handle rt; // the return type from the signature
for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) {
oop mirror;
if (!ss.is_object()) {
mirror = Universe::java_mirror(ss.type());
} else {
symbolOop name_oop = ss.as_symbol(CHECK_(empty));
symbolHandle name(THREAD, name_oop);
klassOop klass = resolve_or_fail(name,
class_loader, protection_domain,
true, CHECK_(empty));
mirror = Klass::cast(klass)->java_mirror();
oop mirror = NULL;
if (is_on_bcp) {
mirror = ss.as_java_mirror(class_loader, protection_domain,
SignatureStream::ReturnNull, CHECK_(empty));
if (mirror == NULL) {
// fall back from BCP to accessing_klass
if (accessing_klass.not_null()) {
class_loader = Handle(THREAD, instanceKlass::cast(accessing_klass())->class_loader());
protection_domain = Handle(THREAD, instanceKlass::cast(accessing_klass())->protection_domain());
}
is_on_bcp = false;
}
}
if (!is_on_bcp) {
// Resolve, throwing a real error if it doesn't work.
mirror = ss.as_java_mirror(class_loader, protection_domain,
SignatureStream::NCDFError, CHECK_(empty));
}
if (ss.at_return_type())
rt = Handle(THREAD, mirror);
else
pts->obj_at_put(arg++, mirror);
// Check accessibility.
if (ss.is_object() && accessing_klass.not_null()) {
klassOop sel_klass = java_lang_Class::as_klassOop(mirror);
// Emulate constantPoolOopDesc::verify_constant_pool_resolve.
if (Klass::cast(sel_klass)->oop_is_objArray())
sel_klass = objArrayKlass::cast(sel_klass)->bottom_klass();
if (Klass::cast(sel_klass)->oop_is_instance()) {
KlassHandle sel_kh(THREAD, sel_klass);
LinkResolver::check_klass_accessability(accessing_klass, sel_kh, CHECK_(empty));
}
}
}
assert(arg == npts, "");
@ -2425,6 +2448,9 @@ Handle SystemDictionary::find_method_handle_type(symbolHandle signature,
vmSymbols::findMethodHandleType_name(),
vmSymbols::findMethodHandleType_signature(),
&args, CHECK_(empty));
// report back to the caller with the MethodType and the "on_bcp" flag
return_bcp_flag = is_on_bcp;
return Handle(THREAD, (oop) result.get_jobject());
}