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())); |