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 |