Mercurial > hg > truffle
comparison src/share/vm/prims/methodHandles.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 | 9eba43136cb5 |
children | 2ffde6cfe049 |
comparison
equal
deleted
inserted
replaced
1506:2338d41fbd81 | 1507:cd5dbf694d45 |
---|---|
364 SEARCH_INTERFACES = sun_dyn_MemberName::MN_SEARCH_INTERFACES, | 364 SEARCH_INTERFACES = sun_dyn_MemberName::MN_SEARCH_INTERFACES, |
365 ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE, | 365 ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE, |
366 VM_INDEX_UNINITIALIZED = sun_dyn_MemberName::VM_INDEX_UNINITIALIZED | 366 VM_INDEX_UNINITIALIZED = sun_dyn_MemberName::VM_INDEX_UNINITIALIZED |
367 }; | 367 }; |
368 | 368 |
369 Handle MethodHandles::new_MemberName(TRAPS) { | |
370 Handle empty; | |
371 instanceKlassHandle k(THREAD, SystemDictionary::MemberName_klass()); | |
372 if (!k->is_initialized()) k->initialize(CHECK_(empty)); | |
373 return Handle(THREAD, k->allocate_instance(THREAD)); | |
374 } | |
375 | |
369 void MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { | 376 void MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { |
370 if (target_oop->klass() == SystemDictionary::reflect_Field_klass()) { | 377 if (target_oop->klass() == SystemDictionary::reflect_Field_klass()) { |
371 oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder() | 378 oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder() |
372 int slot = java_lang_reflect_Field::slot(target_oop); // fd.index() | 379 int slot = java_lang_reflect_Field::slot(target_oop); // fd.index() |
373 int mods = java_lang_reflect_Field::modifiers(target_oop); | 380 int mods = java_lang_reflect_Field::modifiers(target_oop); |
392 vmindex = methodOopDesc::nonvirtual_vtable_index; // implies never any dispatch | 399 vmindex = methodOopDesc::nonvirtual_vtable_index; // implies never any dispatch |
393 assert(vmindex != VM_INDEX_UNINITIALIZED, "Java sentinel value"); | 400 assert(vmindex != VM_INDEX_UNINITIALIZED, "Java sentinel value"); |
394 sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget); | 401 sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget); |
395 sun_dyn_MemberName::set_vmindex(mname_oop, vmindex); | 402 sun_dyn_MemberName::set_vmindex(mname_oop, vmindex); |
396 sun_dyn_MemberName::set_flags(mname_oop, flags); | 403 sun_dyn_MemberName::set_flags(mname_oop, flags); |
404 sun_dyn_MemberName::set_clazz(mname_oop, Klass::cast(m->method_holder())->java_mirror()); | |
397 } | 405 } |
398 | 406 |
399 void MethodHandles::init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset) { | 407 void MethodHandles::init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset) { |
400 int flags = (IS_FIELD | (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS )); | 408 int flags = (IS_FIELD | (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS )); |
401 oop vmtarget = field_holder; | 409 oop vmtarget = field_holder; |
402 int vmindex = offset; // implies no info yet | 410 int vmindex = offset; // determines the field uniquely when combined with static bit |
403 assert(vmindex != VM_INDEX_UNINITIALIZED, "bad alias on vmindex"); | 411 assert(vmindex != VM_INDEX_UNINITIALIZED, "bad alias on vmindex"); |
404 sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget); | 412 sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget); |
405 sun_dyn_MemberName::set_vmindex(mname_oop, vmindex); | 413 sun_dyn_MemberName::set_vmindex(mname_oop, vmindex); |
406 sun_dyn_MemberName::set_flags(mname_oop, flags); | 414 sun_dyn_MemberName::set_flags(mname_oop, flags); |
415 sun_dyn_MemberName::set_clazz(mname_oop, Klass::cast(field_holder)->java_mirror()); | |
407 } | 416 } |
408 | 417 |
409 | 418 |
410 methodOop MethodHandles::decode_MemberName(oop mname, klassOop& receiver_limit_result, int& decode_flags_result) { | 419 methodOop MethodHandles::decode_MemberName(oop mname, klassOop& receiver_limit_result, int& decode_flags_result) { |
411 int flags = sun_dyn_MemberName::flags(mname); | 420 int flags = sun_dyn_MemberName::flags(mname); |
465 symbolHandle name(THREAD, java_lang_String::as_symbol_or_null(name_str)); | 474 symbolHandle name(THREAD, java_lang_String::as_symbol_or_null(name_str)); |
466 if (name.is_null()) return; // no such name | 475 if (name.is_null()) return; // no such name |
467 name_str = NULL; // safety | 476 name_str = NULL; // safety |
468 | 477 |
469 // convert the external string or reflective type to an internal signature | 478 // convert the external string or reflective type to an internal signature |
470 bool force_signature = (name() == vmSymbols::invoke_name()); | 479 bool force_signature = methodOopDesc::is_method_handle_invoke_name(name()); |
471 symbolHandle type; { | 480 symbolHandle type; { |
472 symbolOop type_sym = NULL; | 481 symbolOop type_sym = NULL; |
473 if (java_dyn_MethodType::is_instance(type_str)) { | 482 if (java_dyn_MethodType::is_instance(type_str)) { |
474 type_sym = java_dyn_MethodType::as_signature(type_str, force_signature, CHECK); | 483 type_sym = java_dyn_MethodType::as_signature(type_str, force_signature, CHECK); |
475 } else if (java_lang_Class::is_instance(type_str)) { | 484 } else if (java_lang_Class::is_instance(type_str)) { |
772 | 781 |
773 // return number of elements we at leasted wanted to initialize | 782 // return number of elements we at leasted wanted to initialize |
774 return rfill + overflow; | 783 return rfill + overflow; |
775 } | 784 } |
776 | 785 |
786 | |
787 // Decode this java.lang.Class object into an instanceKlass, if possible. | |
788 // Throw IAE if not | |
789 instanceKlassHandle MethodHandles::resolve_instance_klass(oop java_mirror_oop, TRAPS) { | |
790 instanceKlassHandle empty; | |
791 klassOop caller = NULL; | |
792 if (java_lang_Class::is_instance(java_mirror_oop)) { | |
793 caller = java_lang_Class::as_klassOop(java_mirror_oop); | |
794 } | |
795 if (caller == NULL || !Klass::cast(caller)->oop_is_instance()) { | |
796 THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "not a class", empty); | |
797 } | |
798 return instanceKlassHandle(THREAD, caller); | |
799 } | |
777 | 800 |
778 | 801 |
779 | 802 |
780 // Decode the vmtarget field of a method handle. | 803 // Decode the vmtarget field of a method handle. |
781 // Sanitize out methodOops, klassOops, and any other non-Java data. | 804 // Sanitize out methodOops, klassOops, and any other non-Java data. |
2113 // access checks on behalf of the given caller. But, we can verify this. | 2136 // access checks on behalf of the given caller. But, we can verify this. |
2114 if (VerifyMethodHandles && caller_jh != NULL) { | 2137 if (VerifyMethodHandles && caller_jh != NULL) { |
2115 KlassHandle caller(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(caller_jh))); | 2138 KlassHandle caller(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(caller_jh))); |
2116 // If this were a bytecode, the first access check would be against | 2139 // If this were a bytecode, the first access check would be against |
2117 // the "reference class" mentioned in the CONSTANT_Methodref. | 2140 // the "reference class" mentioned in the CONSTANT_Methodref. |
2118 // For that class, we use the defining class of m, | 2141 // We don't know at this point which class that was, and if we |
2119 // or a more specific receiver limit if available. | 2142 // check against m.method_holder we might get the wrong answer. |
2120 klassOop reference_klass = m->method_holder(); // OK approximation | 2143 // So we just make sure to handle this check when the resolution |
2121 if (receiver_limit != NULL && receiver_limit != reference_klass) { | 2144 // happens, when we call resolve_MemberName. |
2122 if (!Klass::cast(receiver_limit)->is_subtype_of(reference_klass)) | 2145 // |
2123 THROW_MSG(vmSymbols::java_lang_InternalError(), "receiver limit out of bounds"); // Java code bug | 2146 // (A public class can inherit public members from private supers, |
2124 reference_klass = receiver_limit; | 2147 // and it would be wrong to check access against the private super |
2125 } | 2148 // if the original symbolic reference was against the public class.) |
2126 // Emulate LinkResolver::check_klass_accessability. | 2149 // |
2127 if (!Reflection::verify_class_access(caller->as_klassOop(), | |
2128 reference_klass, | |
2129 true)) { | |
2130 THROW_MSG(vmSymbols::java_lang_InternalError(), Klass::cast(m->method_holder())->external_name()); | |
2131 } | |
2132 // If there were a bytecode, the next step would be to lookup the method | 2150 // If there were a bytecode, the next step would be to lookup the method |
2133 // in the reference class, then then check the method's access bits. | 2151 // in the reference class, then then check the method's access bits. |
2134 // Emulate LinkResolver::check_method_accessability. | 2152 // Emulate LinkResolver::check_method_accessability. |
2135 klassOop resolved_klass = m->method_holder(); | 2153 klassOop resolved_klass = m->method_holder(); |
2136 if (!Reflection::verify_field_access(caller->as_klassOop(), | 2154 if (!Reflection::verify_field_access(caller->as_klassOop(), |
2137 resolved_klass, reference_klass, | 2155 resolved_klass, resolved_klass, |
2138 m->access_flags(), | 2156 m->access_flags(), |
2139 true)) { | 2157 true)) { |
2140 // %%% following cutout belongs in Reflection::verify_field_access? | 2158 // %%% following cutout belongs in Reflection::verify_field_access? |
2141 bool same_pm = Reflection::is_same_package_member(caller->as_klassOop(), | 2159 bool same_pm = Reflection::is_same_package_member(caller->as_klassOop(), |
2142 reference_klass, THREAD); | 2160 resolved_klass, THREAD); |
2143 if (!same_pm) { | 2161 if (!same_pm) { |
2144 THROW_MSG(vmSymbols::java_lang_InternalError(), m->name_and_sig_as_C_string()); | 2162 THROW_MSG(vmSymbols::java_lang_InternalError(), m->name_and_sig_as_C_string()); |
2145 } | 2163 } |
2146 } | 2164 } |
2147 } | 2165 } |
2242 "MethodHandlePushLimit parameter must be in valid range"); | 2260 "MethodHandlePushLimit parameter must be in valid range"); |
2243 return MethodHandlePushLimit; | 2261 return MethodHandlePushLimit; |
2244 case MethodHandles::GC_JVM_STACK_MOVE_UNIT: | 2262 case MethodHandles::GC_JVM_STACK_MOVE_UNIT: |
2245 // return number of words per slot, signed according to stack direction | 2263 // return number of words per slot, signed according to stack direction |
2246 return MethodHandles::stack_move_unit(); | 2264 return MethodHandles::stack_move_unit(); |
2265 case MethodHandles::GC_CONV_OP_IMPLEMENTED_MASK: | |
2266 return MethodHandles::adapter_conversion_ops_supported_mask(); | |
2247 } | 2267 } |
2248 return 0; | 2268 return 0; |
2249 } | 2269 } |
2250 JVM_END | 2270 JVM_END |
2251 | 2271 |
2340 | 2360 |
2341 // void resolve(MemberName self, Class<?> caller) | 2361 // void resolve(MemberName self, Class<?> caller) |
2342 JVM_ENTRY(void, MHI_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) { | 2362 JVM_ENTRY(void, MHI_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) { |
2343 if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } | 2363 if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } |
2344 Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); | 2364 Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); |
2345 // %%% take caller into account! | 2365 |
2366 // The trusted Java code that calls this method should already have performed | |
2367 // access checks on behalf of the given caller. But, we can verify this. | |
2368 if (VerifyMethodHandles && caller_jh != NULL) { | |
2369 klassOop reference_klass = java_lang_Class::as_klassOop(sun_dyn_MemberName::clazz(mname())); | |
2370 if (reference_klass != NULL) { | |
2371 // Emulate LinkResolver::check_klass_accessability. | |
2372 klassOop caller = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(caller_jh)); | |
2373 if (!Reflection::verify_class_access(caller, | |
2374 reference_klass, | |
2375 true)) { | |
2376 THROW_MSG(vmSymbols::java_lang_InternalError(), Klass::cast(reference_klass)->external_name()); | |
2377 } | |
2378 } | |
2379 } | |
2380 | |
2346 MethodHandles::resolve_MemberName(mname, CHECK); | 2381 MethodHandles::resolve_MemberName(mname, CHECK); |
2347 } | 2382 } |
2348 JVM_END | 2383 JVM_END |
2349 | 2384 |
2350 // static native int getMembers(Class<?> defc, String matchName, String matchSig, | 2385 // static native int getMembers(Class<?> defc, String matchName, String matchSig, |
2385 // TO DO: expand at least some of the MemberNames, to avoid massive callbacks | 2420 // TO DO: expand at least some of the MemberNames, to avoid massive callbacks |
2386 return res; | 2421 return res; |
2387 } | 2422 } |
2388 JVM_END | 2423 JVM_END |
2389 | 2424 |
2390 | 2425 JVM_ENTRY(void, MHI_registerBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh, jobject bsm_jh)) { |
2391 JVM_ENTRY(void, MH_linkCallSite(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) { | 2426 instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD); |
2427 ik->link_class(CHECK); | |
2428 if (!java_dyn_MethodHandle::is_instance(JNIHandles::resolve(bsm_jh))) { | |
2429 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "method handle"); | |
2430 } | |
2431 const char* err = NULL; | |
2432 if (ik->is_initialized() || ik->is_in_error_state()) { | |
2433 err = "too late: class is already initialized"; | |
2434 } else { | |
2435 ObjectLocker ol(ik, THREAD); // note: this should be a recursive lock | |
2436 if (ik->is_not_initialized() || | |
2437 (ik->is_being_initialized() && ik->is_reentrant_initialization(THREAD))) { | |
2438 if (ik->bootstrap_method() != NULL) { | |
2439 err = "class is already equipped with a bootstrap method"; | |
2440 } else { | |
2441 ik->set_bootstrap_method(JNIHandles::resolve_non_null(bsm_jh)); | |
2442 err = NULL; | |
2443 } | |
2444 } else { | |
2445 err = "class is already initialized"; | |
2446 if (ik->is_being_initialized()) | |
2447 err = "class is already being initialized in a different thread"; | |
2448 } | |
2449 } | |
2450 if (err != NULL) { | |
2451 THROW_MSG(vmSymbols::java_lang_IllegalStateException(), err); | |
2452 } | |
2453 } | |
2454 JVM_END | |
2455 | |
2456 JVM_ENTRY(jobject, MHI_getBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh)) { | |
2457 instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD); | |
2458 return JNIHandles::make_local(THREAD, ik->bootstrap_method()); | |
2459 } | |
2460 JVM_END | |
2461 | |
2462 JVM_ENTRY(void, MHI_setCallSiteTarget(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) { | |
2392 // No special action required, yet. | 2463 // No special action required, yet. |
2393 oop site_oop = JNIHandles::resolve(site_jh); | 2464 oop site_oop = JNIHandles::resolve(site_jh); |
2394 if (site_oop == NULL || site_oop->klass() != SystemDictionary::CallSite_klass()) | 2465 if (!java_dyn_CallSite::is_instance(site_oop)) |
2395 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "call site"); | 2466 THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "not a CallSite"); |
2396 java_dyn_CallSite::set_target(site_oop, JNIHandles::resolve(target_jh)); | 2467 java_dyn_CallSite::set_target(site_oop, JNIHandles::resolve(target_jh)); |
2397 } | 2468 } |
2398 JVM_END | 2469 JVM_END |
2399 | 2470 |
2400 | 2471 |
2440 {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHI_getMembers)} | 2511 {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHI_getMembers)} |
2441 }; | 2512 }; |
2442 | 2513 |
2443 // More entry points specifically for EnableInvokeDynamic. | 2514 // More entry points specifically for EnableInvokeDynamic. |
2444 static JNINativeMethod methods2[] = { | 2515 static JNINativeMethod methods2[] = { |
2445 {CC"linkCallSite", CC"("CST MH")V", FN_PTR(MH_linkCallSite)} | 2516 {CC"registerBootstrap", CC"("CLS MH")V", FN_PTR(MHI_registerBootstrap)}, |
2517 {CC"getBootstrap", CC"("CLS")"MH, FN_PTR(MHI_getBootstrap)}, | |
2518 {CC"setCallSiteTarget", CC"("CST MH")V", FN_PTR(MHI_setCallSiteTarget)} | |
2446 }; | 2519 }; |
2447 | 2520 |
2448 | 2521 |
2449 // This one function is exported, used by NativeLookup. | 2522 // This one function is exported, used by NativeLookup. |
2450 | 2523 |