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