Mercurial > hg > truffle
comparison src/share/vm/classfile/systemDictionary.cpp @ 1508:2ffde6cfe049
6939196: method handle signatures off the boot class path get linkage errors
Summary: Adjust MethodType lookup logic to search off the BCP, but not to cache those results
Reviewed-by: twisti
author | jrose |
---|---|
date | Sat, 01 May 2010 21:57:35 -0700 |
parents | cd5dbf694d45 |
children | c18cbe5936b8 |
comparison
equal
deleted
inserted
replaced
1507:cd5dbf694d45 | 1508:2ffde6cfe049 |
---|---|
2341 } | 2341 } |
2342 | 2342 |
2343 | 2343 |
2344 methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name, | 2344 methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name, |
2345 symbolHandle signature, | 2345 symbolHandle signature, |
2346 Handle class_loader, | 2346 KlassHandle accessing_klass, |
2347 Handle protection_domain, | |
2348 TRAPS) { | 2347 TRAPS) { |
2349 if (!EnableMethodHandles) return NULL; | 2348 if (!EnableMethodHandles) return NULL; |
2350 assert(class_loader.is_null() && protection_domain.is_null(), | |
2351 "cannot load specialized versions of MethodHandle.invoke"); | |
2352 if (invoke_method_table() == NULL) { | 2349 if (invoke_method_table() == NULL) { |
2353 // create this side table lazily | 2350 // create this side table lazily |
2354 _invoke_method_table = new SymbolPropertyTable(_invoke_method_size); | 2351 _invoke_method_table = new SymbolPropertyTable(_invoke_method_size); |
2355 } | 2352 } |
2356 vmSymbols::SID name_id = vmSymbols::find_sid(name()); | 2353 vmSymbols::SID name_id = vmSymbols::find_sid(name()); |
2357 assert(name_id != vmSymbols::NO_SID, "must be a known name"); | 2354 assert(name_id != vmSymbols::NO_SID, "must be a known name"); |
2358 unsigned int hash = invoke_method_table()->compute_hash(signature, name_id); | 2355 unsigned int hash = invoke_method_table()->compute_hash(signature, name_id); |
2359 int index = invoke_method_table()->hash_to_index(hash); | 2356 int index = invoke_method_table()->hash_to_index(hash); |
2360 SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature, name_id); | 2357 SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature, name_id); |
2358 methodHandle non_cached_result; | |
2361 if (spe == NULL || spe->property_oop() == NULL) { | 2359 if (spe == NULL || spe->property_oop() == NULL) { |
2360 spe = NULL; | |
2362 // Must create lots of stuff here, but outside of the SystemDictionary lock. | 2361 // Must create lots of stuff here, but outside of the SystemDictionary lock. |
2363 if (THREAD->is_Compiler_thread()) | 2362 if (THREAD->is_Compiler_thread()) |
2364 return NULL; // do not attempt from within compiler | 2363 return NULL; // do not attempt from within compiler |
2365 Handle mt = find_method_handle_type(signature(), | 2364 bool found_on_bcp = false; |
2366 class_loader, protection_domain, | 2365 Handle mt = find_method_handle_type(signature(), accessing_klass, found_on_bcp, CHECK_NULL); |
2367 CHECK_NULL); | |
2368 KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass(); | 2366 KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass(); |
2369 methodHandle m = methodOopDesc::make_invoke_method(mh_klass, name, signature, | 2367 methodHandle m = methodOopDesc::make_invoke_method(mh_klass, name, signature, |
2370 mt, CHECK_NULL); | 2368 mt, CHECK_NULL); |
2371 // Now grab the lock. We might have to throw away the new method, | 2369 // Now grab the lock. We might have to throw away the new method, |
2372 // if a racing thread has managed to install one at the same time. | 2370 // if a racing thread has managed to install one at the same time. |
2373 { | 2371 if (found_on_bcp) { |
2374 MutexLocker ml(SystemDictionary_lock, Thread::current()); | 2372 MutexLocker ml(SystemDictionary_lock, Thread::current()); |
2375 spe = invoke_method_table()->find_entry(index, hash, signature, name_id); | 2373 spe = invoke_method_table()->find_entry(index, hash, signature, name_id); |
2376 if (spe == NULL) | 2374 if (spe == NULL) |
2377 spe = invoke_method_table()->add_entry(index, hash, signature, name_id); | 2375 spe = invoke_method_table()->add_entry(index, hash, signature, name_id); |
2378 if (spe->property_oop() == NULL) | 2376 if (spe->property_oop() == NULL) |
2379 spe->set_property_oop(m()); | 2377 spe->set_property_oop(m()); |
2380 } | 2378 } else { |
2381 } | 2379 non_cached_result = m; |
2382 methodOop m = (methodOop) spe->property_oop(); | 2380 } |
2383 assert(m->is_method(), ""); | 2381 } |
2384 return m; | 2382 if (spe != NULL && spe->property_oop() != NULL) { |
2383 assert(spe->property_oop()->is_method(), ""); | |
2384 return (methodOop) spe->property_oop(); | |
2385 } else { | |
2386 return non_cached_result(); | |
2387 } | |
2385 } | 2388 } |
2386 | 2389 |
2387 // Ask Java code to find or construct a java.dyn.MethodType for the given | 2390 // Ask Java code to find or construct a java.dyn.MethodType for the given |
2388 // signature, as interpreted relative to the given class loader. | 2391 // signature, as interpreted relative to the given class loader. |
2389 // Because of class loader constraints, all method handle usage must be | 2392 // Because of class loader constraints, all method handle usage must be |
2390 // consistent with this loader. | 2393 // consistent with this loader. |
2391 Handle SystemDictionary::find_method_handle_type(symbolHandle signature, | 2394 Handle SystemDictionary::find_method_handle_type(symbolHandle signature, |
2392 Handle class_loader, | 2395 KlassHandle accessing_klass, |
2393 Handle protection_domain, | 2396 bool& return_bcp_flag, |
2394 TRAPS) { | 2397 TRAPS) { |
2398 Handle class_loader, protection_domain; | |
2399 bool is_on_bcp = true; // keep this true as long as we can materialize from the boot classloader | |
2395 Handle empty; | 2400 Handle empty; |
2396 int npts = ArgumentCount(signature()).size(); | 2401 int npts = ArgumentCount(signature()).size(); |
2397 objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty)); | 2402 objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty)); |
2398 int arg = 0; | 2403 int arg = 0; |
2399 Handle rt; // the return type from the signature | 2404 Handle rt; // the return type from the signature |
2400 for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) { | 2405 for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) { |
2401 oop mirror; | 2406 oop mirror = NULL; |
2402 if (!ss.is_object()) { | 2407 if (is_on_bcp) { |
2403 mirror = Universe::java_mirror(ss.type()); | 2408 mirror = ss.as_java_mirror(class_loader, protection_domain, |
2404 } else { | 2409 SignatureStream::ReturnNull, CHECK_(empty)); |
2405 symbolOop name_oop = ss.as_symbol(CHECK_(empty)); | 2410 if (mirror == NULL) { |
2406 symbolHandle name(THREAD, name_oop); | 2411 // fall back from BCP to accessing_klass |
2407 klassOop klass = resolve_or_fail(name, | 2412 if (accessing_klass.not_null()) { |
2408 class_loader, protection_domain, | 2413 class_loader = Handle(THREAD, instanceKlass::cast(accessing_klass())->class_loader()); |
2409 true, CHECK_(empty)); | 2414 protection_domain = Handle(THREAD, instanceKlass::cast(accessing_klass())->protection_domain()); |
2410 mirror = Klass::cast(klass)->java_mirror(); | 2415 } |
2416 is_on_bcp = false; | |
2417 } | |
2418 } | |
2419 if (!is_on_bcp) { | |
2420 // Resolve, throwing a real error if it doesn't work. | |
2421 mirror = ss.as_java_mirror(class_loader, protection_domain, | |
2422 SignatureStream::NCDFError, CHECK_(empty)); | |
2411 } | 2423 } |
2412 if (ss.at_return_type()) | 2424 if (ss.at_return_type()) |
2413 rt = Handle(THREAD, mirror); | 2425 rt = Handle(THREAD, mirror); |
2414 else | 2426 else |
2415 pts->obj_at_put(arg++, mirror); | 2427 pts->obj_at_put(arg++, mirror); |
2428 // Check accessibility. | |
2429 if (ss.is_object() && accessing_klass.not_null()) { | |
2430 klassOop sel_klass = java_lang_Class::as_klassOop(mirror); | |
2431 // Emulate constantPoolOopDesc::verify_constant_pool_resolve. | |
2432 if (Klass::cast(sel_klass)->oop_is_objArray()) | |
2433 sel_klass = objArrayKlass::cast(sel_klass)->bottom_klass(); | |
2434 if (Klass::cast(sel_klass)->oop_is_instance()) { | |
2435 KlassHandle sel_kh(THREAD, sel_klass); | |
2436 LinkResolver::check_klass_accessability(accessing_klass, sel_kh, CHECK_(empty)); | |
2437 } | |
2438 } | |
2416 } | 2439 } |
2417 assert(arg == npts, ""); | 2440 assert(arg == npts, ""); |
2418 | 2441 |
2419 // call sun.dyn.MethodHandleNatives::findMethodType(Class rt, Class[] pts) -> MethodType | 2442 // call sun.dyn.MethodHandleNatives::findMethodType(Class rt, Class[] pts) -> MethodType |
2420 JavaCallArguments args(Handle(THREAD, rt())); | 2443 JavaCallArguments args(Handle(THREAD, rt())); |
2423 JavaCalls::call_static(&result, | 2446 JavaCalls::call_static(&result, |
2424 SystemDictionary::MethodHandleNatives_klass(), | 2447 SystemDictionary::MethodHandleNatives_klass(), |
2425 vmSymbols::findMethodHandleType_name(), | 2448 vmSymbols::findMethodHandleType_name(), |
2426 vmSymbols::findMethodHandleType_signature(), | 2449 vmSymbols::findMethodHandleType_signature(), |
2427 &args, CHECK_(empty)); | 2450 &args, CHECK_(empty)); |
2451 | |
2452 // report back to the caller with the MethodType and the "on_bcp" flag | |
2453 return_bcp_flag = is_on_bcp; | |
2428 return Handle(THREAD, (oop) result.get_jobject()); | 2454 return Handle(THREAD, (oop) result.get_jobject()); |
2429 } | 2455 } |
2430 | 2456 |
2431 | 2457 |
2432 // Ask Java code to find or construct a java.dyn.CallSite for the given | 2458 // Ask Java code to find or construct a java.dyn.CallSite for the given |