Mercurial > hg > graal-jvmci-8
comparison src/share/vm/classfile/systemDictionary.cpp @ 6266:1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
6984705: JSR 292 method handle creation should not go through JNI
Summary: remove assembly code for JDK 7 chained method handles
Reviewed-by: jrose, twisti, kvn, mhaupt
Contributed-by: John Rose <john.r.rose@oracle.com>, Christian Thalinger <christian.thalinger@oracle.com>, Michael Haupt <michael.haupt@oracle.com>
author | twisti |
---|---|
date | Tue, 24 Jul 2012 10:51:00 -0700 |
parents | e74da3c2b827 |
children | 957c266d8bc5 da91efe96a93 |
comparison
equal
deleted
inserted
replaced
6241:aba91a731143 | 6266:1d7922586cf6 |
---|---|
28 #include "classfile/loaderConstraints.hpp" | 28 #include "classfile/loaderConstraints.hpp" |
29 #include "classfile/placeholders.hpp" | 29 #include "classfile/placeholders.hpp" |
30 #include "classfile/resolutionErrors.hpp" | 30 #include "classfile/resolutionErrors.hpp" |
31 #include "classfile/systemDictionary.hpp" | 31 #include "classfile/systemDictionary.hpp" |
32 #include "classfile/vmSymbols.hpp" | 32 #include "classfile/vmSymbols.hpp" |
33 #include "compiler/compileBroker.hpp" | |
33 #include "interpreter/bytecodeStream.hpp" | 34 #include "interpreter/bytecodeStream.hpp" |
34 #include "interpreter/interpreter.hpp" | 35 #include "interpreter/interpreter.hpp" |
35 #include "memory/gcLocker.hpp" | 36 #include "memory/gcLocker.hpp" |
36 #include "memory/oopFactory.hpp" | 37 #include "memory/oopFactory.hpp" |
37 #include "oops/instanceKlass.hpp" | 38 #include "oops/instanceKlass.hpp" |
191 | 192 |
192 | 193 |
193 // Forwards to resolve_instance_class_or_null | 194 // Forwards to resolve_instance_class_or_null |
194 | 195 |
195 klassOop SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) { | 196 klassOop SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) { |
196 assert(!THREAD->is_Compiler_thread(), "Can not load classes with the Compiler thread"); | 197 assert(!THREAD->is_Compiler_thread(), |
198 err_msg("can not load classes with compiler thread: class=%s, classloader=%s", | |
199 class_name->as_C_string(), | |
200 class_loader.is_null() ? "null" : class_loader->klass()->klass_part()->name()->as_C_string())); | |
197 if (FieldType::is_array(class_name)) { | 201 if (FieldType::is_array(class_name)) { |
198 return resolve_array_class_or_null(class_name, class_loader, protection_domain, CHECK_NULL); | 202 return resolve_array_class_or_null(class_name, class_loader, protection_domain, CHECK_NULL); |
199 } else if (FieldType::is_obj(class_name)) { | 203 } else if (FieldType::is_obj(class_name)) { |
200 ResourceMark rm(THREAD); | 204 ResourceMark rm(THREAD); |
201 // Ignore wrapping L and ;. | 205 // Ignore wrapping L and ;. |
2356 } | 2360 } |
2357 return NULL; | 2361 return NULL; |
2358 } | 2362 } |
2359 | 2363 |
2360 | 2364 |
2361 methodOop SystemDictionary::find_method_handle_invoke(Symbol* name, | 2365 methodHandle SystemDictionary::find_method_handle_intrinsic(vmIntrinsics::ID iid, |
2362 Symbol* signature, | 2366 Symbol* signature, |
2363 KlassHandle accessing_klass, | 2367 TRAPS) { |
2364 TRAPS) { | 2368 methodHandle empty; |
2365 if (!EnableInvokeDynamic) return NULL; | 2369 assert(EnableInvokeDynamic, ""); |
2366 vmSymbols::SID name_id = vmSymbols::find_sid(name); | 2370 assert(MethodHandles::is_signature_polymorphic(iid) && |
2367 assert(name_id != vmSymbols::NO_SID, "must be a known name"); | 2371 MethodHandles::is_signature_polymorphic_intrinsic(iid) && |
2368 unsigned int hash = invoke_method_table()->compute_hash(signature, name_id); | 2372 iid != vmIntrinsics::_invokeGeneric, |
2373 err_msg("must be a known MH intrinsic iid=%d: %s", iid, vmIntrinsics::name_at(iid))); | |
2374 | |
2375 unsigned int hash = invoke_method_table()->compute_hash(signature, iid); | |
2369 int index = invoke_method_table()->hash_to_index(hash); | 2376 int index = invoke_method_table()->hash_to_index(hash); |
2370 SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature, name_id); | 2377 SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature, iid); |
2371 methodHandle non_cached_result; | 2378 methodHandle m; |
2372 if (spe == NULL || spe->property_oop() == NULL) { | 2379 if (spe == NULL || spe->property_oop() == NULL) { |
2373 spe = NULL; | 2380 spe = NULL; |
2374 // Must create lots of stuff here, but outside of the SystemDictionary lock. | 2381 // Must create lots of stuff here, but outside of the SystemDictionary lock. |
2375 if (THREAD->is_Compiler_thread()) | 2382 m = methodOopDesc::make_method_handle_intrinsic(iid, signature, CHECK_(empty)); |
2376 return NULL; // do not attempt from within compiler | 2383 CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_highest_tier, |
2377 bool for_invokeGeneric = (name_id != vmSymbols::VM_SYMBOL_ENUM_NAME(invokeExact_name)); | 2384 methodHandle(), CompileThreshold, "MH", CHECK_(empty)); |
2378 bool found_on_bcp = false; | 2385 |
2379 Handle mt = find_method_handle_type(signature, accessing_klass, | |
2380 for_invokeGeneric, | |
2381 found_on_bcp, CHECK_NULL); | |
2382 KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass(); | |
2383 methodHandle m = methodOopDesc::make_invoke_method(mh_klass, name, signature, | |
2384 mt, CHECK_NULL); | |
2385 // Now grab the lock. We might have to throw away the new method, | 2386 // Now grab the lock. We might have to throw away the new method, |
2386 // if a racing thread has managed to install one at the same time. | 2387 // if a racing thread has managed to install one at the same time. |
2387 if (found_on_bcp) { | 2388 { |
2388 MutexLocker ml(SystemDictionary_lock, Thread::current()); | 2389 MutexLocker ml(SystemDictionary_lock, THREAD); |
2389 spe = invoke_method_table()->find_entry(index, hash, signature, name_id); | 2390 spe = invoke_method_table()->find_entry(index, hash, signature, iid); |
2390 if (spe == NULL) | 2391 if (spe == NULL) |
2391 spe = invoke_method_table()->add_entry(index, hash, signature, name_id); | 2392 spe = invoke_method_table()->add_entry(index, hash, signature, iid); |
2392 if (spe->property_oop() == NULL) { | 2393 if (spe->property_oop() == NULL) |
2393 spe->set_property_oop(m()); | 2394 spe->set_property_oop(m()); |
2394 // Link m to his method type, if it is suitably generic. | 2395 } |
2395 oop mtform = java_lang_invoke_MethodType::form(mt()); | 2396 } |
2396 if (mtform != NULL && mt() == java_lang_invoke_MethodTypeForm::erasedType(mtform) | 2397 |
2397 // vmlayout must be an invokeExact: | 2398 assert(spe != NULL && spe->property_oop() != NULL, ""); |
2398 && name_id == vmSymbols::VM_SYMBOL_ENUM_NAME(invokeExact_name) | 2399 m = methodOop(spe->property_oop()); |
2399 && java_lang_invoke_MethodTypeForm::vmlayout_offset_in_bytes() > 0) { | 2400 assert(m->is_method(), ""); |
2400 java_lang_invoke_MethodTypeForm::init_vmlayout(mtform, m()); | 2401 |
2401 } | 2402 return m; |
2403 } | |
2404 | |
2405 // Helper for unpacking the return value from linkMethod and linkCallSite. | |
2406 static methodHandle unpack_method_and_appendix(Handle mname, | |
2407 objArrayHandle appendix_box, | |
2408 Handle* appendix_result, | |
2409 TRAPS) { | |
2410 methodHandle empty; | |
2411 if (mname.not_null()) { | |
2412 oop vmtarget = java_lang_invoke_MemberName::vmtarget(mname()); | |
2413 if (vmtarget != NULL && vmtarget->is_method()) { | |
2414 methodOop m = methodOop(vmtarget); | |
2415 oop appendix = appendix_box->obj_at(0); | |
2416 if (TraceMethodHandles) { | |
2417 #ifndef PRODUCT | |
2418 tty->print("Linked method="INTPTR_FORMAT": ", m); | |
2419 m->print(); | |
2420 if (appendix != NULL) { tty->print("appendix = "); appendix->print(); } | |
2421 tty->cr(); | |
2422 #endif //PRODUCT | |
2402 } | 2423 } |
2403 } else { | 2424 (*appendix_result) = Handle(THREAD, appendix); |
2404 non_cached_result = m; | 2425 return methodHandle(THREAD, m); |
2405 } | 2426 } |
2406 } | 2427 } |
2407 if (spe != NULL && spe->property_oop() != NULL) { | 2428 THROW_MSG_(vmSymbols::java_lang_LinkageError(), "bad value from MethodHandleNatives", empty); |
2408 assert(spe->property_oop()->is_method(), ""); | 2429 return empty; |
2409 return (methodOop) spe->property_oop(); | 2430 } |
2410 } else { | 2431 |
2411 return non_cached_result(); | 2432 methodHandle SystemDictionary::find_method_handle_invoker(Symbol* name, |
2412 } | 2433 Symbol* signature, |
2413 } | 2434 KlassHandle accessing_klass, |
2435 Handle* appendix_result, | |
2436 TRAPS) { | |
2437 methodHandle empty; | |
2438 assert(EnableInvokeDynamic, ""); | |
2439 assert(!THREAD->is_Compiler_thread(), ""); | |
2440 Handle method_type = | |
2441 SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_(empty)); | |
2442 if (false) { // FIXME: Decide if the Java upcall should resolve signatures. | |
2443 method_type = java_lang_String::create_from_symbol(signature, CHECK_(empty)); | |
2444 } | |
2445 | |
2446 KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass(); | |
2447 int ref_kind = JVM_REF_invokeVirtual; | |
2448 Handle name_str = StringTable::intern(name, CHECK_(empty)); | |
2449 objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty)); | |
2450 assert(appendix_box->obj_at(0) == NULL, ""); | |
2451 | |
2452 // call java.lang.invoke.MethodHandleNatives::linkMethod(... String, MethodType) -> MemberName | |
2453 JavaCallArguments args; | |
2454 args.push_oop(accessing_klass()->java_mirror()); | |
2455 args.push_int(ref_kind); | |
2456 args.push_oop(mh_klass()->java_mirror()); | |
2457 args.push_oop(name_str()); | |
2458 args.push_oop(method_type()); | |
2459 args.push_oop(appendix_box()); | |
2460 JavaValue result(T_OBJECT); | |
2461 JavaCalls::call_static(&result, | |
2462 SystemDictionary::MethodHandleNatives_klass(), | |
2463 vmSymbols::linkMethod_name(), | |
2464 vmSymbols::linkMethod_signature(), | |
2465 &args, CHECK_(empty)); | |
2466 Handle mname(THREAD, (oop) result.get_jobject()); | |
2467 return unpack_method_and_appendix(mname, appendix_box, appendix_result, THREAD); | |
2468 } | |
2469 | |
2414 | 2470 |
2415 // Ask Java code to find or construct a java.lang.invoke.MethodType for the given | 2471 // Ask Java code to find or construct a java.lang.invoke.MethodType for the given |
2416 // signature, as interpreted relative to the given class loader. | 2472 // signature, as interpreted relative to the given class loader. |
2417 // Because of class loader constraints, all method handle usage must be | 2473 // Because of class loader constraints, all method handle usage must be |
2418 // consistent with this loader. | 2474 // consistent with this loader. |
2419 Handle SystemDictionary::find_method_handle_type(Symbol* signature, | 2475 Handle SystemDictionary::find_method_handle_type(Symbol* signature, |
2420 KlassHandle accessing_klass, | 2476 KlassHandle accessing_klass, |
2421 bool for_invokeGeneric, | |
2422 bool& return_bcp_flag, | |
2423 TRAPS) { | 2477 TRAPS) { |
2478 Handle empty; | |
2479 vmIntrinsics::ID null_iid = vmIntrinsics::_none; // distinct from all method handle invoker intrinsics | |
2480 unsigned int hash = invoke_method_table()->compute_hash(signature, null_iid); | |
2481 int index = invoke_method_table()->hash_to_index(hash); | |
2482 SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature, null_iid); | |
2483 if (spe != NULL && spe->property_oop() != NULL) { | |
2484 assert(java_lang_invoke_MethodType::is_instance(spe->property_oop()), ""); | |
2485 return Handle(THREAD, spe->property_oop()); | |
2486 } else if (THREAD->is_Compiler_thread()) { | |
2487 warning("SystemDictionary::find_method_handle_type called from compiler thread"); // FIXME | |
2488 return Handle(); // do not attempt from within compiler, unless it was cached | |
2489 } | |
2490 | |
2424 Handle class_loader, protection_domain; | 2491 Handle class_loader, protection_domain; |
2425 bool is_on_bcp = true; // keep this true as long as we can materialize from the boot classloader | 2492 bool is_on_bcp = true; // keep this true as long as we can materialize from the boot classloader |
2426 Handle empty; | |
2427 int npts = ArgumentCount(signature).size(); | 2493 int npts = ArgumentCount(signature).size(); |
2428 objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty)); | 2494 objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty)); |
2429 int arg = 0; | 2495 int arg = 0; |
2430 Handle rt; // the return type from the signature | 2496 Handle rt; // the return type from the signature |
2431 ResourceMark rm(THREAD); | 2497 ResourceMark rm(THREAD); |
2432 for (SignatureStream ss(signature); !ss.is_done(); ss.next()) { | 2498 for (SignatureStream ss(signature); !ss.is_done(); ss.next()) { |
2433 oop mirror = NULL; | 2499 oop mirror = NULL; |
2434 if (is_on_bcp) { | 2500 if (is_on_bcp) { |
2501 // Note: class_loader & protection_domain are both null at this point. | |
2435 mirror = ss.as_java_mirror(class_loader, protection_domain, | 2502 mirror = ss.as_java_mirror(class_loader, protection_domain, |
2436 SignatureStream::ReturnNull, CHECK_(empty)); | 2503 SignatureStream::ReturnNull, CHECK_(empty)); |
2437 if (mirror == NULL) { | 2504 if (mirror == NULL) { |
2438 // fall back from BCP to accessing_klass | 2505 // fall back from BCP to accessing_klass |
2439 if (accessing_klass.not_null()) { | 2506 if (accessing_klass.not_null()) { |
2450 } | 2517 } |
2451 if (ss.at_return_type()) | 2518 if (ss.at_return_type()) |
2452 rt = Handle(THREAD, mirror); | 2519 rt = Handle(THREAD, mirror); |
2453 else | 2520 else |
2454 pts->obj_at_put(arg++, mirror); | 2521 pts->obj_at_put(arg++, mirror); |
2522 | |
2455 // Check accessibility. | 2523 // Check accessibility. |
2456 if (ss.is_object() && accessing_klass.not_null()) { | 2524 if (ss.is_object() && accessing_klass.not_null()) { |
2457 klassOop sel_klass = java_lang_Class::as_klassOop(mirror); | 2525 klassOop sel_klass = java_lang_Class::as_klassOop(mirror); |
2526 mirror = NULL; // safety | |
2458 // Emulate constantPoolOopDesc::verify_constant_pool_resolve. | 2527 // Emulate constantPoolOopDesc::verify_constant_pool_resolve. |
2459 if (Klass::cast(sel_klass)->oop_is_objArray()) | 2528 if (Klass::cast(sel_klass)->oop_is_objArray()) |
2460 sel_klass = objArrayKlass::cast(sel_klass)->bottom_klass(); | 2529 sel_klass = objArrayKlass::cast(sel_klass)->bottom_klass(); |
2461 if (Klass::cast(sel_klass)->oop_is_instance()) { | 2530 if (Klass::cast(sel_klass)->oop_is_instance()) { |
2462 KlassHandle sel_kh(THREAD, sel_klass); | 2531 KlassHandle sel_kh(THREAD, sel_klass); |
2475 vmSymbols::findMethodHandleType_name(), | 2544 vmSymbols::findMethodHandleType_name(), |
2476 vmSymbols::findMethodHandleType_signature(), | 2545 vmSymbols::findMethodHandleType_signature(), |
2477 &args, CHECK_(empty)); | 2546 &args, CHECK_(empty)); |
2478 Handle method_type(THREAD, (oop) result.get_jobject()); | 2547 Handle method_type(THREAD, (oop) result.get_jobject()); |
2479 | 2548 |
2480 if (for_invokeGeneric) { | 2549 if (is_on_bcp) { |
2481 // call java.lang.invoke.MethodHandleNatives::notifyGenericMethodType(MethodType) -> void | 2550 // We can cache this MethodType inside the JVM. |
2482 JavaCallArguments args(Handle(THREAD, method_type())); | 2551 MutexLocker ml(SystemDictionary_lock, THREAD); |
2483 JavaValue no_result(T_VOID); | 2552 spe = invoke_method_table()->find_entry(index, hash, signature, null_iid); |
2484 JavaCalls::call_static(&no_result, | 2553 if (spe == NULL) |
2485 SystemDictionary::MethodHandleNatives_klass(), | 2554 spe = invoke_method_table()->add_entry(index, hash, signature, null_iid); |
2486 vmSymbols::notifyGenericMethodType_name(), | 2555 if (spe->property_oop() == NULL) { |
2487 vmSymbols::notifyGenericMethodType_signature(), | 2556 spe->set_property_oop(method_type()); |
2488 &args, THREAD); | 2557 } |
2489 if (HAS_PENDING_EXCEPTION) { | 2558 } |
2490 // If the notification fails, just kill it. | 2559 |
2491 CLEAR_PENDING_EXCEPTION; | 2560 // report back to the caller with the MethodType |
2492 } | |
2493 } | |
2494 | |
2495 // report back to the caller with the MethodType and the "on_bcp" flag | |
2496 return_bcp_flag = is_on_bcp; | |
2497 return method_type; | 2561 return method_type; |
2498 } | 2562 } |
2499 | 2563 |
2500 // Ask Java code to find or construct a method handle constant. | 2564 // Ask Java code to find or construct a method handle constant. |
2501 Handle SystemDictionary::link_method_handle_constant(KlassHandle caller, | 2565 Handle SystemDictionary::link_method_handle_constant(KlassHandle caller, |
2506 TRAPS) { | 2570 TRAPS) { |
2507 Handle empty; | 2571 Handle empty; |
2508 Handle name = java_lang_String::create_from_symbol(name_sym, CHECK_(empty)); | 2572 Handle name = java_lang_String::create_from_symbol(name_sym, CHECK_(empty)); |
2509 Handle type; | 2573 Handle type; |
2510 if (signature->utf8_length() > 0 && signature->byte_at(0) == '(') { | 2574 if (signature->utf8_length() > 0 && signature->byte_at(0) == '(') { |
2511 bool ignore_is_on_bcp = false; | 2575 type = find_method_handle_type(signature, caller, CHECK_(empty)); |
2512 type = find_method_handle_type(signature, caller, false, ignore_is_on_bcp, CHECK_(empty)); | |
2513 } else { | 2576 } else { |
2514 ResourceMark rm(THREAD); | 2577 ResourceMark rm(THREAD); |
2515 SignatureStream ss(signature, false); | 2578 SignatureStream ss(signature, false); |
2516 if (!ss.is_done()) { | 2579 if (!ss.is_done()) { |
2517 oop mirror = ss.as_java_mirror(caller->class_loader(), caller->protection_domain(), | 2580 oop mirror = ss.as_java_mirror(caller->class_loader(), caller->protection_domain(), |
2541 return Handle(THREAD, (oop) result.get_jobject()); | 2604 return Handle(THREAD, (oop) result.get_jobject()); |
2542 } | 2605 } |
2543 | 2606 |
2544 // Ask Java code to find or construct a java.lang.invoke.CallSite for the given | 2607 // Ask Java code to find or construct a java.lang.invoke.CallSite for the given |
2545 // name and signature, as interpreted relative to the given class loader. | 2608 // name and signature, as interpreted relative to the given class loader. |
2546 Handle SystemDictionary::make_dynamic_call_site(Handle bootstrap_method, | 2609 methodHandle SystemDictionary::find_dynamic_call_site_invoker(KlassHandle caller, |
2547 Symbol* name, | 2610 Handle bootstrap_specifier, |
2548 methodHandle signature_invoker, | 2611 Symbol* name, |
2549 Handle info, | 2612 Symbol* type, |
2550 methodHandle caller_method, | 2613 Handle* appendix_result, |
2551 int caller_bci, | 2614 TRAPS) { |
2552 TRAPS) { | 2615 methodHandle empty; |
2553 Handle empty; | 2616 Handle bsm, info; |
2554 guarantee(bootstrap_method.not_null() && | 2617 if (java_lang_invoke_MethodHandle::is_instance(bootstrap_specifier())) { |
2555 java_lang_invoke_MethodHandle::is_instance(bootstrap_method()), | 2618 bsm = bootstrap_specifier; |
2619 } else { | |
2620 assert(bootstrap_specifier->is_objArray(), ""); | |
2621 objArrayHandle args(THREAD, (objArrayOop) bootstrap_specifier()); | |
2622 int len = args->length(); | |
2623 assert(len >= 1, ""); | |
2624 bsm = Handle(THREAD, args->obj_at(0)); | |
2625 if (len > 1) { | |
2626 objArrayOop args1 = oopFactory::new_objArray(SystemDictionary::Object_klass(), len-1, CHECK_(empty)); | |
2627 for (int i = 1; i < len; i++) | |
2628 args1->obj_at_put(i-1, args->obj_at(i)); | |
2629 info = Handle(THREAD, args1); | |
2630 } | |
2631 } | |
2632 guarantee(java_lang_invoke_MethodHandle::is_instance(bsm()), | |
2556 "caller must supply a valid BSM"); | 2633 "caller must supply a valid BSM"); |
2557 | 2634 |
2558 Handle caller_mname = MethodHandles::new_MemberName(CHECK_(empty)); | 2635 Handle method_name = java_lang_String::create_from_symbol(name, CHECK_(empty)); |
2559 MethodHandles::init_MemberName(caller_mname(), caller_method()); | 2636 Handle method_type = find_method_handle_type(type, caller, CHECK_(empty)); |
2560 | 2637 |
2561 // call java.lang.invoke.MethodHandleNatives::makeDynamicCallSite(bootm, name, mtype, info, caller_mname, caller_pos) | 2638 objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty)); |
2562 oop name_str_oop = StringTable::intern(name, CHECK_(empty)); // not a handle! | 2639 assert(appendix_box->obj_at(0) == NULL, ""); |
2563 JavaCallArguments args(Handle(THREAD, bootstrap_method())); | 2640 |
2564 args.push_oop(name_str_oop); | 2641 // call java.lang.invoke.MethodHandleNatives::linkCallSite(caller, bsm, name, mtype, info, &appendix) |
2565 args.push_oop(signature_invoker->method_handle_type()); | 2642 JavaCallArguments args; |
2643 args.push_oop(caller->java_mirror()); | |
2644 args.push_oop(bsm()); | |
2645 args.push_oop(method_name()); | |
2646 args.push_oop(method_type()); | |
2566 args.push_oop(info()); | 2647 args.push_oop(info()); |
2567 args.push_oop(caller_mname()); | 2648 args.push_oop(appendix_box); |
2568 args.push_int(caller_bci); | |
2569 JavaValue result(T_OBJECT); | 2649 JavaValue result(T_OBJECT); |
2570 JavaCalls::call_static(&result, | 2650 JavaCalls::call_static(&result, |
2571 SystemDictionary::MethodHandleNatives_klass(), | 2651 SystemDictionary::MethodHandleNatives_klass(), |
2572 vmSymbols::makeDynamicCallSite_name(), | 2652 vmSymbols::linkCallSite_name(), |
2573 vmSymbols::makeDynamicCallSite_signature(), | 2653 vmSymbols::linkCallSite_signature(), |
2574 &args, CHECK_(empty)); | 2654 &args, CHECK_(empty)); |
2575 oop call_site_oop = (oop) result.get_jobject(); | 2655 Handle mname(THREAD, (oop) result.get_jobject()); |
2576 assert(call_site_oop->is_oop() | 2656 return unpack_method_and_appendix(mname, appendix_box, appendix_result, THREAD); |
2577 /*&& java_lang_invoke_CallSite::is_instance(call_site_oop)*/, "must be sane"); | |
2578 if (TraceMethodHandles) { | |
2579 #ifndef PRODUCT | |
2580 tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop); | |
2581 call_site_oop->print(); | |
2582 tty->cr(); | |
2583 #endif //PRODUCT | |
2584 } | |
2585 return call_site_oop; | |
2586 } | |
2587 | |
2588 Handle SystemDictionary::find_bootstrap_method(methodHandle caller_method, int caller_bci, | |
2589 int cache_index, | |
2590 Handle& argument_info_result, | |
2591 TRAPS) { | |
2592 Handle empty; | |
2593 | |
2594 constantPoolHandle pool; | |
2595 { | |
2596 klassOop caller = caller_method->method_holder(); | |
2597 if (!Klass::cast(caller)->oop_is_instance()) return empty; | |
2598 pool = constantPoolHandle(THREAD, instanceKlass::cast(caller)->constants()); | |
2599 } | |
2600 | |
2601 int constant_pool_index = pool->cache()->entry_at(cache_index)->constant_pool_index(); | |
2602 constantTag tag = pool->tag_at(constant_pool_index); | |
2603 | |
2604 if (tag.is_invoke_dynamic()) { | |
2605 // JVM_CONSTANT_InvokeDynamic is an ordered pair of [bootm, name&type], plus optional arguments | |
2606 // The bootm, being a JVM_CONSTANT_MethodHandle, has its own cache entry. | |
2607 int bsm_index = pool->invoke_dynamic_bootstrap_method_ref_index_at(constant_pool_index); | |
2608 if (bsm_index != 0) { | |
2609 int bsm_index_in_cache = pool->cache()->entry_at(cache_index)->bootstrap_method_index_in_cache(); | |
2610 DEBUG_ONLY(int bsm_index_2 = pool->cache()->entry_at(bsm_index_in_cache)->constant_pool_index()); | |
2611 assert(bsm_index == bsm_index_2, "BSM constant lifted to cache"); | |
2612 if (TraceMethodHandles) { | |
2613 tty->print_cr("resolving bootstrap method for "PTR_FORMAT" at %d at cache[%d]CP[%d]...", | |
2614 (intptr_t) caller_method(), caller_bci, cache_index, constant_pool_index); | |
2615 } | |
2616 oop bsm_oop = pool->resolve_cached_constant_at(bsm_index_in_cache, CHECK_(empty)); | |
2617 if (TraceMethodHandles) { | |
2618 tty->print_cr("bootstrap method for "PTR_FORMAT" at %d retrieved as "PTR_FORMAT":", | |
2619 (intptr_t) caller_method(), caller_bci, (intptr_t) bsm_oop); | |
2620 } | |
2621 assert(bsm_oop->is_oop(), "must be sane"); | |
2622 // caller must verify that it is of type MethodHandle | |
2623 Handle bsm(THREAD, bsm_oop); | |
2624 bsm_oop = NULL; // safety | |
2625 | |
2626 // Extract the optional static arguments. | |
2627 Handle argument_info; // either null, or one arg, or Object[]{arg...} | |
2628 int argc = pool->invoke_dynamic_argument_count_at(constant_pool_index); | |
2629 if (TraceInvokeDynamic) { | |
2630 tty->print_cr("find_bootstrap_method: [%d/%d] CONSTANT_InvokeDynamic: %d[%d]", | |
2631 constant_pool_index, cache_index, bsm_index, argc); | |
2632 } | |
2633 if (argc > 0) { | |
2634 objArrayHandle arg_array; | |
2635 if (argc > 1) { | |
2636 objArrayOop arg_array_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), argc, CHECK_(empty)); | |
2637 arg_array = objArrayHandle(THREAD, arg_array_oop); | |
2638 argument_info = arg_array; | |
2639 } | |
2640 for (int arg_i = 0; arg_i < argc; arg_i++) { | |
2641 int arg_index = pool->invoke_dynamic_argument_index_at(constant_pool_index, arg_i); | |
2642 oop arg_oop = pool->resolve_possibly_cached_constant_at(arg_index, CHECK_(empty)); | |
2643 if (arg_array.is_null()) { | |
2644 argument_info = Handle(THREAD, arg_oop); | |
2645 } else { | |
2646 arg_array->obj_at_put(arg_i, arg_oop); | |
2647 } | |
2648 } | |
2649 } | |
2650 | |
2651 argument_info_result = argument_info; // return argument_info to caller | |
2652 return bsm; | |
2653 } | |
2654 } else { | |
2655 ShouldNotReachHere(); // verifier does not allow this | |
2656 } | |
2657 | |
2658 return empty; | |
2659 } | 2657 } |
2660 | 2658 |
2661 // Since the identity hash code for symbols changes when the symbols are | 2659 // Since the identity hash code for symbols changes when the symbols are |
2662 // moved from the regular perm gen (hash in the mark word) to the shared | 2660 // moved from the regular perm gen (hash in the mark word) to the shared |
2663 // spaces (hash is the address), the classes loaded into the dictionary | 2661 // spaces (hash is the address), the classes loaded into the dictionary |