# HG changeset patch # User psandoz # Date 1458814909 -3600 # Node ID bca375d368ed8ca4b20829ab763d7f52f1e7188e # Parent b40330c06dea55b9356a485a5b359743ad3afd83 8149644: Integrate VarHandles Reviewed-by: kvn, vlivanov diff -r b40330c06dea -r bca375d368ed hotspot/src/share/vm/ci/ciEnv.cpp --- a/hotspot/src/share/vm/ci/ciEnv.cpp Thu Mar 24 09:09:52 2016 +0100 +++ b/hotspot/src/share/vm/ci/ciEnv.cpp Thu Mar 24 11:21:49 2016 +0100 @@ -773,7 +773,7 @@ Symbol* sig_sym = cpool->signature_ref_at(index); if (cpool->has_preresolution() - || (holder == ciEnv::MethodHandle_klass() && + || ((holder == ciEnv::MethodHandle_klass() || holder == ciEnv::VarHandle_klass()) && MethodHandles::is_signature_polymorphic_name(holder->get_Klass(), name_sym))) { // Short-circuit lookups for JSR 292-related call sites. // That is, do not rely only on name-based lookups, because they may fail diff -r b40330c06dea -r bca375d368ed hotspot/src/share/vm/classfile/systemDictionary.cpp --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Mar 24 09:09:52 2016 +0100 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Mar 24 11:21:49 2016 +0100 @@ -2405,7 +2405,8 @@ return empty; } -methodHandle SystemDictionary::find_method_handle_invoker(Symbol* name, +methodHandle SystemDictionary::find_method_handle_invoker(KlassHandle klass, + Symbol* name, Symbol* signature, KlassHandle accessing_klass, Handle *appendix_result, @@ -2416,7 +2417,6 @@ Handle method_type = SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_(empty)); - KlassHandle mh_klass = SystemDictionary::MethodHandle_klass(); int ref_kind = JVM_REF_invokeVirtual; Handle name_str = StringTable::intern(name, CHECK_(empty)); objArrayHandle appendix_box = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK_(empty)); @@ -2431,7 +2431,7 @@ JavaCallArguments args; args.push_oop(accessing_klass()->java_mirror()); args.push_int(ref_kind); - args.push_oop(mh_klass()->java_mirror()); + args.push_oop(klass()->java_mirror()); args.push_oop(name_str()); args.push_oop(method_type()); args.push_oop(appendix_box()); diff -r b40330c06dea -r bca375d368ed hotspot/src/share/vm/classfile/systemDictionary.hpp --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Mar 24 09:09:52 2016 +0100 +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Mar 24 11:21:49 2016 +0100 @@ -152,6 +152,7 @@ /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ do_klass(DirectMethodHandle_klass, java_lang_invoke_DirectMethodHandle, Opt ) \ do_klass(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre ) \ + do_klass(VarHandle_klass, java_lang_invoke_VarHandle, Pre ) \ do_klass(MemberName_klass, java_lang_invoke_MemberName, Pre ) \ do_klass(MethodHandleNatives_klass, java_lang_invoke_MethodHandleNatives, Pre ) \ do_klass(LambdaForm_klass, java_lang_invoke_LambdaForm, Opt ) \ @@ -515,7 +516,8 @@ // JSR 292 // find a java.lang.invoke.MethodHandle.invoke* method for a given signature // (asks Java to compute it if necessary, except in a compiler thread) - static methodHandle find_method_handle_invoker(Symbol* name, + static methodHandle find_method_handle_invoker(KlassHandle klass, + Symbol* name, Symbol* signature, KlassHandle accessing_klass, Handle *appendix_result, diff -r b40330c06dea -r bca375d368ed hotspot/src/share/vm/classfile/vmSymbols.hpp --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Mar 24 09:09:52 2016 +0100 +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Mar 24 11:21:49 2016 +0100 @@ -279,6 +279,7 @@ template(java_lang_invoke_MutableCallSite, "java/lang/invoke/MutableCallSite") \ template(java_lang_invoke_VolatileCallSite, "java/lang/invoke/VolatileCallSite") \ template(java_lang_invoke_MethodHandle, "java/lang/invoke/MethodHandle") \ + template(java_lang_invoke_VarHandle, "java/lang/invoke/VarHandle") \ template(java_lang_invoke_MethodType, "java/lang/invoke/MethodType") \ template(java_lang_invoke_MethodType_signature, "Ljava/lang/invoke/MethodType;") \ template(java_lang_invoke_MemberName_signature, "Ljava/lang/invoke/MemberName;") \ diff -r b40330c06dea -r bca375d368ed hotspot/src/share/vm/interpreter/linkResolver.cpp --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Thu Mar 24 09:09:52 2016 +0100 +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Thu Mar 24 11:21:49 2016 +0100 @@ -90,10 +90,16 @@ void CallInfo::set_handle(const methodHandle& resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS) { + set_handle(SystemDictionary::MethodHandle_klass(), resolved_method, resolved_appendix, resolved_method_type, CHECK); +} + +void CallInfo::set_handle(KlassHandle resolved_klass, + const methodHandle& resolved_method, + Handle resolved_appendix, + Handle resolved_method_type, TRAPS) { if (resolved_method.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "resolved method is null"); } - KlassHandle resolved_klass = SystemDictionary::MethodHandle_klass(); assert(resolved_method->intrinsic_id() == vmIntrinsics::_invokeBasic || resolved_method->is_compiled_lambda_form(), "linkMethod must return one of these"); @@ -426,7 +432,8 @@ vmIntrinsics::name_at(iid), klass->external_name(), name->as_C_string(), full_signature->as_C_string()); } - if (klass() == SystemDictionary::MethodHandle_klass() && + if ((klass() == SystemDictionary::MethodHandle_klass() || + klass() == SystemDictionary::VarHandle_klass()) && iid != vmIntrinsics::_none) { if (MethodHandles::is_signature_polymorphic_intrinsic(iid)) { // Most of these do not need an up-call to Java to resolve, so can be done anywhere. @@ -475,6 +482,7 @@ Handle appendix; Handle method_type; methodHandle result = SystemDictionary::find_method_handle_invoker( + klass, name, full_signature, link_info.current_klass(), @@ -1554,13 +1562,15 @@ const LinkInfo& link_info, TRAPS) { // JSR 292: this must be an implicitly generated method MethodHandle.invokeExact(*...) or similar - assert(link_info.resolved_klass()() == SystemDictionary::MethodHandle_klass(), ""); + KlassHandle resolved_klass = link_info.resolved_klass(); + assert(resolved_klass() == SystemDictionary::MethodHandle_klass() || + resolved_klass() == SystemDictionary::VarHandle_klass(), ""); assert(MethodHandles::is_signature_polymorphic_name(link_info.name()), ""); Handle resolved_appendix; Handle resolved_method_type; methodHandle resolved_method = lookup_polymorphic_method(link_info, &resolved_appendix, &resolved_method_type, CHECK); - result.set_handle(resolved_method, resolved_appendix, resolved_method_type, CHECK); + result.set_handle(resolved_klass, resolved_method, resolved_appendix, resolved_method_type, CHECK); } static void wrap_invokedynamic_exception(TRAPS) { diff -r b40330c06dea -r bca375d368ed hotspot/src/share/vm/interpreter/linkResolver.hpp --- a/hotspot/src/share/vm/interpreter/linkResolver.hpp Thu Mar 24 09:09:52 2016 +0100 +++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp Thu Mar 24 11:21:49 2016 +0100 @@ -69,6 +69,9 @@ int vtable_index, TRAPS); void set_handle(const methodHandle& resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS); + void set_handle(KlassHandle resolved_klass, + const methodHandle& resolved_method, + Handle resolved_appendix, Handle resolved_method_type, TRAPS); void set_common(KlassHandle resolved_klass, KlassHandle selected_klass, const methodHandle& resolved_method, const methodHandle& selected_method, diff -r b40330c06dea -r bca375d368ed hotspot/src/share/vm/interpreter/rewriter.cpp --- a/hotspot/src/share/vm/interpreter/rewriter.cpp Thu Mar 24 09:09:52 2016 +0100 +++ b/hotspot/src/share/vm/interpreter/rewriter.cpp Thu Mar 24 11:21:49 2016 +0100 @@ -54,8 +54,10 @@ add_resolved_references_entry(i); break; case JVM_CONSTANT_Utf8: - if (_pool->symbol_at(i) == vmSymbols::java_lang_invoke_MethodHandle()) + if (_pool->symbol_at(i) == vmSymbols::java_lang_invoke_MethodHandle() || + _pool->symbol_at(i) == vmSymbols::java_lang_invoke_VarHandle()) { saw_mh_symbol = true; + } break; } } @@ -200,6 +202,12 @@ // we may need a resolved_refs entry for the appendix add_invokedynamic_resolved_references_entries(cp_index, cache_index); status = +1; + } else if (_pool->klass_ref_at_noresolve(cp_index) == vmSymbols::java_lang_invoke_VarHandle() && + MethodHandles::is_signature_polymorphic_name(SystemDictionary::VarHandle_klass(), + _pool->name_ref_at(cp_index))) { + // we may need a resolved_refs entry for the appendix + add_invokedynamic_resolved_references_entries(cp_index, cache_index); + status = +1; } else { status = -1; } diff -r b40330c06dea -r bca375d368ed hotspot/src/share/vm/oops/method.cpp --- a/hotspot/src/share/vm/oops/method.cpp Thu Mar 24 09:09:52 2016 +0100 +++ b/hotspot/src/share/vm/oops/method.cpp Thu Mar 24 11:21:49 2016 +0100 @@ -1351,11 +1351,16 @@ // ditto for method and signature: vmSymbols::SID name_id = vmSymbols::find_sid(name()); if (klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_MethodHandle) - && name_id == vmSymbols::NO_SID) + && klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_VarHandle) + && name_id == vmSymbols::NO_SID) { return; + } vmSymbols::SID sig_id = vmSymbols::find_sid(signature()); if (klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_MethodHandle) - && sig_id == vmSymbols::NO_SID) return; + && klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_VarHandle) + && sig_id == vmSymbols::NO_SID) { + return; + } jshort flags = access_flags().as_short(); vmIntrinsics::ID id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags); @@ -1383,8 +1388,9 @@ } break; - // Signature-polymorphic methods: MethodHandle.invoke*, InvokeDynamic.*. + // Signature-polymorphic methods: MethodHandle.invoke*, InvokeDynamic.*., VarHandle case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_MethodHandle): + case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_VarHandle): if (!is_native()) break; id = MethodHandles::signature_polymorphic_name_id(method_holder(), name()); if (is_static() != MethodHandles::is_signature_polymorphic_static(id)) diff -r b40330c06dea -r bca375d368ed hotspot/src/share/vm/prims/methodHandles.cpp --- a/hotspot/src/share/vm/prims/methodHandles.cpp Thu Mar 24 09:09:52 2016 +0100 +++ b/hotspot/src/share/vm/prims/methodHandles.cpp Thu Mar 24 11:21:49 2016 +0100 @@ -318,9 +318,9 @@ // JVM 2.9 Special Methods: // A method is signature polymorphic if and only if all of the following conditions hold : -// * It is declared in the java.lang.invoke.MethodHandle class. +// * It is declared in the java.lang.invoke.MethodHandle/VarHandle classes. // * It has a single formal parameter of type Object[]. -// * It has a return type of Object. +// * It has a return type of Object for a polymorphic return type, otherwise a fixed return type. // * It has the ACC_VARARGS and ACC_NATIVE flags set. bool MethodHandles::is_method_handle_invoke_name(Klass* klass, Symbol* name) { if (klass == NULL) @@ -328,14 +328,36 @@ // The following test will fail spuriously during bootstrap of MethodHandle itself: // if (klass != SystemDictionary::MethodHandle_klass()) // Test the name instead: - if (klass->name() != vmSymbols::java_lang_invoke_MethodHandle()) + if (klass->name() != vmSymbols::java_lang_invoke_MethodHandle() && + klass->name() != vmSymbols::java_lang_invoke_VarHandle()) { return false; + } + + // Look up signature polymorphic method with polymorphic return type Symbol* poly_sig = vmSymbols::object_array_object_signature(); - Method* m = InstanceKlass::cast(klass)->find_method(name, poly_sig); - if (m == NULL) return false; - int required = JVM_ACC_NATIVE | JVM_ACC_VARARGS; - int flags = m->access_flags().as_int(); - return (flags & required) == required; + InstanceKlass* iklass = InstanceKlass::cast(klass); + Method* m = iklass->find_method(name, poly_sig); + if (m != NULL) { + int required = JVM_ACC_NATIVE | JVM_ACC_VARARGS; + int flags = m->access_flags().as_int(); + if ((flags & required) == required) { + return true; + } + } + + // Look up signature polymorphic method with non-polymorphic (non Object) return type + int me; + int ms = iklass->find_method_by_name(name, &me); + if (ms == -1) return false; + for (; ms < me; ms++) { + Method* m = iklass->methods()->at(ms); + int required = JVM_ACC_NATIVE | JVM_ACC_VARARGS; + int flags = m->access_flags().as_int(); + if ((flags & required) == required && ArgumentCount(m->signature()).size() == 1) { + return true; + } + } + return false; } @@ -395,8 +417,16 @@ // Cover the case of invokeExact and any future variants of invokeFoo. Klass* mh_klass = SystemDictionary::well_known_klass( SystemDictionary::WK_KLASS_ENUM_NAME(MethodHandle_klass) ); - if (mh_klass != NULL && is_method_handle_invoke_name(mh_klass, name)) + if (mh_klass != NULL && is_method_handle_invoke_name(mh_klass, name)) { return vmIntrinsics::_invokeGeneric; + } + + // Cover the case of methods on VarHandle. + Klass* vh_klass = SystemDictionary::well_known_klass( + SystemDictionary::WK_KLASS_ENUM_NAME(VarHandle_klass) ); + if (vh_klass != NULL && is_method_handle_invoke_name(vh_klass, name)) { + return vmIntrinsics::_invokeGeneric; + } // Note: The pseudo-intrinsic _compiledLambdaForm is never linked against. // Instead it is used to mark lambda forms bound to invokehandle or invokedynamic. @@ -405,7 +435,8 @@ vmIntrinsics::ID MethodHandles::signature_polymorphic_name_id(Klass* klass, Symbol* name) { if (klass != NULL && - klass->name() == vmSymbols::java_lang_invoke_MethodHandle()) { + (klass->name() == vmSymbols::java_lang_invoke_MethodHandle() || + klass->name() == vmSymbols::java_lang_invoke_VarHandle())) { vmIntrinsics::ID iid = signature_polymorphic_name_id(name); if (iid != vmIntrinsics::_none) return iid; diff -r b40330c06dea -r bca375d368ed hotspot/src/share/vm/prims/methodHandles.hpp --- a/hotspot/src/share/vm/prims/methodHandles.hpp Thu Mar 24 09:09:52 2016 +0100 +++ b/hotspot/src/share/vm/prims/methodHandles.hpp Thu Mar 24 11:21:49 2016 +0100 @@ -120,7 +120,8 @@ iid <= vmIntrinsics::_linkToInterface); } static bool has_member_arg(Symbol* klass, Symbol* name) { - if ((klass == vmSymbols::java_lang_invoke_MethodHandle()) && + if ((klass == vmSymbols::java_lang_invoke_MethodHandle() || + klass == vmSymbols::java_lang_invoke_VarHandle()) && is_signature_polymorphic_name(name)) { vmIntrinsics::ID iid = signature_polymorphic_name_id(name); return has_member_arg(iid);