Mercurial > hg > truffle
comparison src/share/vm/classfile/systemDictionary.cpp @ 1507:cd5dbf694d45
6939134: JSR 292 adjustments to method handle invocation
Summary: split MethodHandle.invoke into invokeExact and invokeGeneric; also clean up JVM-to-Java interfaces
Reviewed-by: twisti
author | jrose |
---|---|
date | Sat, 01 May 2010 02:42:18 -0700 |
parents | 09ac706c2623 |
children | 2ffde6cfe049 |
comparison
equal
deleted
inserted
replaced
1506:2338d41fbd81 | 1507:cd5dbf694d45 |
---|---|
2339 } | 2339 } |
2340 return NULL; | 2340 return NULL; |
2341 } | 2341 } |
2342 | 2342 |
2343 | 2343 |
2344 methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature, | 2344 methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name, |
2345 symbolHandle signature, | |
2345 Handle class_loader, | 2346 Handle class_loader, |
2346 Handle protection_domain, | 2347 Handle protection_domain, |
2347 TRAPS) { | 2348 TRAPS) { |
2348 if (!EnableMethodHandles) return NULL; | 2349 if (!EnableMethodHandles) return NULL; |
2349 assert(class_loader.is_null() && protection_domain.is_null(), | 2350 assert(class_loader.is_null() && protection_domain.is_null(), |
2350 "cannot load specialized versions of MethodHandle.invoke"); | 2351 "cannot load specialized versions of MethodHandle.invoke"); |
2351 if (invoke_method_table() == NULL) { | 2352 if (invoke_method_table() == NULL) { |
2352 // create this side table lazily | 2353 // create this side table lazily |
2353 _invoke_method_table = new SymbolPropertyTable(_invoke_method_size); | 2354 _invoke_method_table = new SymbolPropertyTable(_invoke_method_size); |
2354 } | 2355 } |
2355 unsigned int hash = invoke_method_table()->compute_hash(signature); | 2356 vmSymbols::SID name_id = vmSymbols::find_sid(name()); |
2357 assert(name_id != vmSymbols::NO_SID, "must be a known name"); | |
2358 unsigned int hash = invoke_method_table()->compute_hash(signature, name_id); | |
2356 int index = invoke_method_table()->hash_to_index(hash); | 2359 int index = invoke_method_table()->hash_to_index(hash); |
2357 SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature); | 2360 SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature, name_id); |
2358 if (spe == NULL || spe->property_oop() == NULL) { | 2361 if (spe == NULL || spe->property_oop() == NULL) { |
2359 // Must create lots of stuff here, but outside of the SystemDictionary lock. | 2362 // Must create lots of stuff here, but outside of the SystemDictionary lock. |
2360 if (THREAD->is_Compiler_thread()) | 2363 if (THREAD->is_Compiler_thread()) |
2361 return NULL; // do not attempt from within compiler | 2364 return NULL; // do not attempt from within compiler |
2362 Handle mt = compute_method_handle_type(signature(), | 2365 Handle mt = find_method_handle_type(signature(), |
2363 class_loader, protection_domain, | 2366 class_loader, protection_domain, |
2364 CHECK_NULL); | 2367 CHECK_NULL); |
2365 KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass(); | 2368 KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass(); |
2366 methodHandle m = methodOopDesc::make_invoke_method(mh_klass, signature, | 2369 methodHandle m = methodOopDesc::make_invoke_method(mh_klass, name, signature, |
2367 mt, CHECK_NULL); | 2370 mt, CHECK_NULL); |
2368 // Now grab the lock. We might have to throw away the new method, | 2371 // Now grab the lock. We might have to throw away the new method, |
2369 // if a racing thread has managed to install one at the same time. | 2372 // if a racing thread has managed to install one at the same time. |
2370 { | 2373 { |
2371 MutexLocker ml(SystemDictionary_lock, Thread::current()); | 2374 MutexLocker ml(SystemDictionary_lock, Thread::current()); |
2372 spe = invoke_method_table()->find_entry(index, hash, signature); | 2375 spe = invoke_method_table()->find_entry(index, hash, signature, name_id); |
2373 if (spe == NULL) | 2376 if (spe == NULL) |
2374 spe = invoke_method_table()->add_entry(index, hash, signature); | 2377 spe = invoke_method_table()->add_entry(index, hash, signature, name_id); |
2375 if (spe->property_oop() == NULL) | 2378 if (spe->property_oop() == NULL) |
2376 spe->set_property_oop(m()); | 2379 spe->set_property_oop(m()); |
2377 } | 2380 } |
2378 } | 2381 } |
2379 methodOop m = (methodOop) spe->property_oop(); | 2382 methodOop m = (methodOop) spe->property_oop(); |
2383 | 2386 |
2384 // Ask Java code to find or construct a java.dyn.MethodType for the given | 2387 // Ask Java code to find or construct a java.dyn.MethodType for the given |
2385 // signature, as interpreted relative to the given class loader. | 2388 // signature, as interpreted relative to the given class loader. |
2386 // Because of class loader constraints, all method handle usage must be | 2389 // Because of class loader constraints, all method handle usage must be |
2387 // consistent with this loader. | 2390 // consistent with this loader. |
2388 Handle SystemDictionary::compute_method_handle_type(symbolHandle signature, | 2391 Handle SystemDictionary::find_method_handle_type(symbolHandle signature, |
2389 Handle class_loader, | 2392 Handle class_loader, |
2390 Handle protection_domain, | 2393 Handle protection_domain, |
2391 TRAPS) { | 2394 TRAPS) { |
2392 Handle empty; | 2395 Handle empty; |
2393 int npts = ArgumentCount(signature()).size(); | 2396 int npts = ArgumentCount(signature()).size(); |
2394 objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty)); | 2397 objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty)); |
2395 int arg = 0; | 2398 int arg = 0; |
2396 Handle rt; // the return type from the signature | 2399 Handle rt; // the return type from the signature |
2411 else | 2414 else |
2412 pts->obj_at_put(arg++, mirror); | 2415 pts->obj_at_put(arg++, mirror); |
2413 } | 2416 } |
2414 assert(arg == npts, ""); | 2417 assert(arg == npts, ""); |
2415 | 2418 |
2416 // call MethodType java.dyn.MethodType::makeImpl(Class rt, Class[] pts, false, true) | 2419 // call sun.dyn.MethodHandleNatives::findMethodType(Class rt, Class[] pts) -> MethodType |
2417 bool varargs = false, trusted = true; | |
2418 JavaCallArguments args(Handle(THREAD, rt())); | 2420 JavaCallArguments args(Handle(THREAD, rt())); |
2419 args.push_oop(pts()); | 2421 args.push_oop(pts()); |
2420 args.push_int(false); | |
2421 args.push_int(trusted); | |
2422 JavaValue result(T_OBJECT); | 2422 JavaValue result(T_OBJECT); |
2423 JavaCalls::call_static(&result, | 2423 JavaCalls::call_static(&result, |
2424 SystemDictionary::MethodType_klass(), | 2424 SystemDictionary::MethodHandleNatives_klass(), |
2425 vmSymbols::makeImpl_name(), vmSymbols::makeImpl_signature(), | 2425 vmSymbols::findMethodHandleType_name(), |
2426 vmSymbols::findMethodHandleType_signature(), | |
2426 &args, CHECK_(empty)); | 2427 &args, CHECK_(empty)); |
2427 return Handle(THREAD, (oop) result.get_jobject()); | 2428 return Handle(THREAD, (oop) result.get_jobject()); |
2428 } | 2429 } |
2429 | 2430 |
2430 | 2431 |
2431 // Ask Java code to find or construct a java.dyn.CallSite for the given | 2432 // Ask Java code to find or construct a java.dyn.CallSite for the given |
2432 // name and signature, as interpreted relative to the given class loader. | 2433 // name and signature, as interpreted relative to the given class loader. |
2433 Handle SystemDictionary::make_dynamic_call_site(KlassHandle caller, | 2434 Handle SystemDictionary::make_dynamic_call_site(Handle bootstrap_method, |
2434 int caller_method_idnum, | 2435 symbolHandle name, |
2436 methodHandle signature_invoker, | |
2437 Handle info, | |
2438 methodHandle caller_method, | |
2435 int caller_bci, | 2439 int caller_bci, |
2436 symbolHandle name, | |
2437 methodHandle mh_invdyn, | |
2438 TRAPS) { | 2440 TRAPS) { |
2439 Handle empty; | 2441 Handle empty; |
2440 // call java.dyn.CallSite::makeSite(caller, name, mtype, cmid, cbci) | 2442 Handle caller_mname = MethodHandles::new_MemberName(CHECK_(empty)); |
2443 MethodHandles::init_MemberName(caller_mname(), caller_method()); | |
2444 | |
2445 // call sun.dyn.MethodHandleNatives::makeDynamicCallSite(bootm, name, mtype, info, caller_mname, caller_pos) | |
2441 oop name_str_oop = StringTable::intern(name(), CHECK_(empty)); // not a handle! | 2446 oop name_str_oop = StringTable::intern(name(), CHECK_(empty)); // not a handle! |
2442 JavaCallArguments args(Handle(THREAD, caller->java_mirror())); | 2447 JavaCallArguments args(Handle(THREAD, bootstrap_method())); |
2443 args.push_oop(name_str_oop); | 2448 args.push_oop(name_str_oop); |
2444 args.push_oop(mh_invdyn->method_handle_type()); | 2449 args.push_oop(signature_invoker->method_handle_type()); |
2445 args.push_int(caller_method_idnum); | 2450 args.push_oop(info()); |
2451 args.push_oop(caller_mname()); | |
2446 args.push_int(caller_bci); | 2452 args.push_int(caller_bci); |
2447 JavaValue result(T_OBJECT); | 2453 JavaValue result(T_OBJECT); |
2448 JavaCalls::call_static(&result, | 2454 JavaCalls::call_static(&result, |
2449 SystemDictionary::CallSite_klass(), | 2455 SystemDictionary::MethodHandleNatives_klass(), |
2450 vmSymbols::makeSite_name(), vmSymbols::makeSite_signature(), | 2456 vmSymbols::makeDynamicCallSite_name(), |
2457 vmSymbols::makeDynamicCallSite_signature(), | |
2451 &args, CHECK_(empty)); | 2458 &args, CHECK_(empty)); |
2452 oop call_site_oop = (oop) result.get_jobject(); | 2459 oop call_site_oop = (oop) result.get_jobject(); |
2453 assert(call_site_oop->is_oop() | 2460 assert(call_site_oop->is_oop() |
2454 /*&& java_dyn_CallSite::is_instance(call_site_oop)*/, "must be sane"); | 2461 /*&& java_dyn_CallSite::is_instance(call_site_oop)*/, "must be sane"); |
2455 java_dyn_CallSite::set_vmmethod(call_site_oop, mh_invdyn()); | |
2456 if (TraceMethodHandles) { | 2462 if (TraceMethodHandles) { |
2457 #ifndef PRODUCT | 2463 #ifndef PRODUCT |
2458 tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop); | 2464 tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop); |
2459 call_site_oop->print(); | 2465 call_site_oop->print(); |
2460 tty->cr(); | 2466 tty->cr(); |
2461 #endif //PRODUCT | 2467 #endif //PRODUCT |
2462 } | 2468 } |
2463 return call_site_oop; | 2469 return call_site_oop; |
2464 } | 2470 } |
2465 | 2471 |
2466 Handle SystemDictionary::find_bootstrap_method(KlassHandle caller, | 2472 Handle SystemDictionary::find_bootstrap_method(KlassHandle caller, TRAPS) { |
2467 KlassHandle search_bootstrap_klass, | |
2468 TRAPS) { | |
2469 Handle empty; | 2473 Handle empty; |
2470 if (!caller->oop_is_instance()) return empty; | 2474 if (!caller->oop_is_instance()) return empty; |
2471 | 2475 |
2472 instanceKlassHandle ik(THREAD, caller()); | 2476 instanceKlassHandle ik(THREAD, caller()); |
2473 | 2477 |
2474 oop boot_method_oop = ik->bootstrap_method(); | 2478 oop boot_method_oop = ik->bootstrap_method(); |
2475 if (boot_method_oop != NULL) { | 2479 if (boot_method_oop != NULL) { |
2476 if (TraceMethodHandles) { | 2480 if (TraceMethodHandles) { |
2477 tty->print_cr("bootstrap method for "PTR_FORMAT" cached as "PTR_FORMAT":", ik(), boot_method_oop); | 2481 tty->print_cr("bootstrap method for "PTR_FORMAT" cached as "PTR_FORMAT":", ik(), boot_method_oop); |
2478 } | 2482 } |
2479 NOT_PRODUCT(if (!boot_method_oop->is_oop()) { tty->print_cr("*** boot MH of "PTR_FORMAT" = "PTR_FORMAT, ik(), boot_method_oop); ik()->print(); }); | |
2480 assert(boot_method_oop->is_oop() | 2483 assert(boot_method_oop->is_oop() |
2481 && java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane"); | 2484 && java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane"); |
2482 return Handle(THREAD, boot_method_oop); | 2485 return Handle(THREAD, boot_method_oop); |
2483 } | 2486 } |
2484 boot_method_oop = NULL; // GC safety | 2487 |
2485 | 2488 return empty; |
2486 // call java.dyn.Linkage::findBootstrapMethod(caller, sbk) | |
2487 JavaCallArguments args(Handle(THREAD, ik->java_mirror())); | |
2488 if (search_bootstrap_klass.is_null()) | |
2489 args.push_oop(Handle()); | |
2490 else | |
2491 args.push_oop(search_bootstrap_klass->java_mirror()); | |
2492 JavaValue result(T_OBJECT); | |
2493 JavaCalls::call_static(&result, | |
2494 SystemDictionary::Linkage_klass(), | |
2495 vmSymbols::findBootstrapMethod_name(), | |
2496 vmSymbols::findBootstrapMethod_signature(), | |
2497 &args, CHECK_(empty)); | |
2498 boot_method_oop = (oop) result.get_jobject(); | |
2499 | |
2500 if (boot_method_oop != NULL) { | |
2501 if (TraceMethodHandles) { | |
2502 #ifndef PRODUCT | |
2503 tty->print_cr("--------"); | |
2504 tty->print_cr("bootstrap method for "PTR_FORMAT" computed as "PTR_FORMAT":", ik(), boot_method_oop); | |
2505 ik()->print(); | |
2506 boot_method_oop->print(); | |
2507 tty->print_cr("========"); | |
2508 #endif //PRODUCT | |
2509 } | |
2510 assert(boot_method_oop->is_oop() | |
2511 && java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane"); | |
2512 // probably no race conditions, but let's be careful: | |
2513 if (Atomic::cmpxchg_ptr(boot_method_oop, ik->adr_bootstrap_method(), NULL) == NULL) | |
2514 ik->set_bootstrap_method(boot_method_oop); | |
2515 else | |
2516 boot_method_oop = ik->bootstrap_method(); | |
2517 } else { | |
2518 if (TraceMethodHandles) { | |
2519 #ifndef PRODUCT | |
2520 tty->print_cr("--------"); | |
2521 tty->print_cr("bootstrap method for "PTR_FORMAT" computed as NULL:", ik()); | |
2522 ik()->print(); | |
2523 tty->print_cr("========"); | |
2524 #endif //PRODUCT | |
2525 } | |
2526 boot_method_oop = ik->bootstrap_method(); | |
2527 } | |
2528 | |
2529 return Handle(THREAD, boot_method_oop); | |
2530 } | 2489 } |
2531 | 2490 |
2532 // Since the identity hash code for symbols changes when the symbols are | 2491 // Since the identity hash code for symbols changes when the symbols are |
2533 // moved from the regular perm gen (hash in the mark word) to the shared | 2492 // moved from the regular perm gen (hash in the mark word) to the shared |
2534 // spaces (hash is the address), the classes loaded into the dictionary | 2493 // spaces (hash is the address), the classes loaded into the dictionary |