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