From d616b7126ccf8e7dc93d621035ef568323ac18cc Mon Sep 17 00:00:00 2001 From: Ivan Dubrov Date: Fri, 10 Jul 2015 13:59:53 -0700 Subject: [PATCH] Copying method handles code from full version --- .../light-jdk7u79-b15-method-handles.patch | 345 ++++++++++++++++++ hotspot/.hg/patches/series | 1 + 2 files changed, 346 insertions(+) create mode 100644 hotspot/.hg/patches/light-jdk7u79-b15-method-handles.patch diff --git a/hotspot/.hg/patches/light-jdk7u79-b15-method-handles.patch b/hotspot/.hg/patches/light-jdk7u79-b15-method-handles.patch new file mode 100644 index 00000000..ef7b85ba --- /dev/null +++ b/hotspot/.hg/patches/light-jdk7u79-b15-method-handles.patch @@ -0,0 +1,345 @@ +# HG changeset patch +# Parent 6858a68213bfb26e2a246f0014b921ecab5ac750 + +diff -r 6858a68213bf -r a416f1b672a4 src/share/vm/classfile/javaClasses.cpp +--- a/src/share/vm/classfile/javaClasses.cpp Fri Jul 10 13:18:18 2015 -0700 ++++ b/src/share/vm/classfile/javaClasses.cpp Fri Jul 10 13:59:26 2015 -0700 +@@ -2414,6 +2414,49 @@ + } + } + ++// Support for java_lang_invoke_DirectMethodHandle$StaticAccessor ++ ++int java_lang_invoke_DirectMethodHandle_StaticAccessor::_static_offset_offset; ++ ++long java_lang_invoke_DirectMethodHandle_StaticAccessor::static_offset(oop dmh) { ++ assert(_static_offset_offset != 0, ""); ++ return dmh->long_field(_static_offset_offset); ++} ++ ++void java_lang_invoke_DirectMethodHandle_StaticAccessor::set_static_offset(oop dmh, long static_offset) { ++ assert(_static_offset_offset != 0, ""); ++ dmh->long_field_put(_static_offset_offset, static_offset); ++} ++ ++ ++void java_lang_invoke_DirectMethodHandle_StaticAccessor::compute_offsets() { ++ klassOop klass_oop = SystemDictionary::DirectMethodHandle_StaticAccessor_klass(); ++ if (klass_oop != NULL && EnableInvokeDynamic) { ++ compute_offset(_static_offset_offset, klass_oop, vmSymbols::static_offset_name(), vmSymbols::long_signature()); ++ } ++} ++ ++// Support for java_lang_invoke_DirectMethodHandle$Accessor ++ ++int java_lang_invoke_DirectMethodHandle_Accessor::_field_offset_offset; ++ ++int java_lang_invoke_DirectMethodHandle_Accessor::field_offset(oop dmh) { ++ assert(_field_offset_offset != 0, ""); ++ return dmh->int_field(_field_offset_offset); ++} ++ ++void java_lang_invoke_DirectMethodHandle_Accessor::set_field_offset(oop dmh, int field_offset) { ++ assert(_field_offset_offset != 0, ""); ++ dmh->int_field_put(_field_offset_offset, field_offset); ++} ++ ++void java_lang_invoke_DirectMethodHandle_Accessor::compute_offsets() { ++ klassOop klass_oop = SystemDictionary::DirectMethodHandle_Accessor_klass(); ++ if (klass_oop != NULL && EnableInvokeDynamic) { ++ compute_offset(_field_offset_offset, klass_oop, vmSymbols::field_offset_name(), vmSymbols::int_signature()); ++ } ++} ++ + // Support for java_lang_invoke_MethodHandle + + int java_lang_invoke_MethodHandle::_type_offset; +@@ -3033,6 +3076,8 @@ + if (EnableInvokeDynamic) { + java_lang_invoke_MethodHandle::compute_offsets(); + java_lang_invoke_DirectMethodHandle::compute_offsets(); ++ java_lang_invoke_DirectMethodHandle_StaticAccessor::compute_offsets(); ++ java_lang_invoke_DirectMethodHandle_Accessor::compute_offsets(); + java_lang_invoke_MemberName::compute_offsets(); + java_lang_invoke_LambdaForm::compute_offsets(); + java_lang_invoke_MethodType::compute_offsets(); +diff -r 6858a68213bf -r a416f1b672a4 src/share/vm/classfile/javaClasses.hpp +--- a/src/share/vm/classfile/javaClasses.hpp Fri Jul 10 13:18:18 2015 -0700 ++++ b/src/share/vm/classfile/javaClasses.hpp Fri Jul 10 13:59:26 2015 -0700 +@@ -942,6 +942,55 @@ + static int member_offset_in_bytes() { return _member_offset; } + }; + ++// Interface to java.lang.invoke.DirectMethodHandle$StaticAccessor objects ++ ++class java_lang_invoke_DirectMethodHandle_StaticAccessor: AllStatic { ++ friend class JavaClasses; ++ ++ private: ++ static int _static_offset_offset; // offset to static field ++ ++ static void compute_offsets(); ++ ++ public: ++ // Accessors ++ static long static_offset(oop dmh); ++ static void set_static_offset(oop dmh, long value); ++ ++ // Testers ++ static bool is_subclass(klassOop klass) { ++ return Klass::cast(klass)->is_subclass_of(SystemDictionary::DirectMethodHandle_StaticAccessor_klass()); ++ } ++ static bool is_instance(oop obj) { ++ return obj != NULL && is_subclass(obj->klass()); ++ } ++}; ++ ++// Interface to java.lang.invoke.DirectMethodHandle$Accessor objects ++ ++class java_lang_invoke_DirectMethodHandle_Accessor: AllStatic { ++ friend class JavaClasses; ++ ++ private: ++ static int _field_offset_offset; // offset to field ++ ++ static void compute_offsets(); ++ ++ public: ++ // Accessors ++ static int field_offset(oop dmh); ++ static void set_field_offset(oop dmh, int value); ++ ++ // Testers ++ static bool is_subclass(klassOop klass) { ++ return Klass::cast(klass)->is_subclass_of(SystemDictionary::DirectMethodHandle_Accessor_klass()); ++ } ++ static bool is_instance(oop obj) { ++ return obj != NULL && is_subclass(obj->klass()); ++ } ++}; ++ ++ + // Interface to java.lang.invoke.LambdaForm objects + // (These are a private interface for managing adapter code generation.) + +diff -r 6858a68213bf -r a416f1b672a4 src/share/vm/classfile/systemDictionary.hpp +--- a/src/share/vm/classfile/systemDictionary.hpp Fri Jul 10 13:18:18 2015 -0700 ++++ b/src/share/vm/classfile/systemDictionary.hpp Fri Jul 10 13:59:26 2015 -0700 +@@ -148,6 +148,8 @@ + do_klass(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15 ) \ + \ + /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ ++ do_klass(DirectMethodHandle_StaticAccessor_klass, java_lang_invoke_DirectMethodHandle_StaticAccessor, Opt ) \ ++ do_klass(DirectMethodHandle_Accessor_klass, java_lang_invoke_DirectMethodHandle_Accessor, Opt ) \ + do_klass(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre_JSR292 ) \ + do_klass(MemberName_klass, java_lang_invoke_MemberName, Pre_JSR292 ) \ + do_klass(MethodHandleNatives_klass, java_lang_invoke_MethodHandleNatives, Pre_JSR292 ) \ +diff -r 6858a68213bf -r a416f1b672a4 src/share/vm/classfile/vmSymbols.hpp +--- a/src/share/vm/classfile/vmSymbols.hpp Fri Jul 10 13:18:18 2015 -0700 ++++ b/src/share/vm/classfile/vmSymbols.hpp Fri Jul 10 13:59:26 2015 -0700 +@@ -244,6 +244,8 @@ + /* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \ + template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \ + template(java_lang_invoke_ConstantCallSite, "java/lang/invoke/ConstantCallSite") \ ++ template(java_lang_invoke_DirectMethodHandle_StaticAccessor, "java/lang/invoke/DirectMethodHandle$StaticAccessor") \ ++ template(java_lang_invoke_DirectMethodHandle_Accessor, "java/lang/invoke/DirectMethodHandle$Accessor") \ + template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \ + template(java_lang_invoke_MutableCallSite, "java/lang/invoke/MutableCallSite") \ + template(java_lang_invoke_VolatileCallSite, "java/lang/invoke/VolatileCallSite") \ +@@ -477,6 +479,10 @@ + template(int_StringBuffer_signature, "(I)Ljava/lang/StringBuffer;") \ + template(char_StringBuffer_signature, "(C)Ljava/lang/StringBuffer;") \ + template(int_String_signature, "(I)Ljava/lang/String;") \ ++ template(static_offset_name, "staticOffset") \ ++ template(static_base_name, "staticBase") \ ++ template(field_offset_name, "fieldOffset") \ ++ template(field_type_name, "fieldType") \ + /* signature symbols needed by intrinsics */ \ + VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, VM_SYMBOL_IGNORE, template, VM_ALIAS_IGNORE) \ + \ +diff -r 6858a68213bf -r a416f1b672a4 src/share/vm/prims/jvmtiRedefineClasses.cpp +--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Jul 10 13:18:18 2015 -0700 ++++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Jul 10 13:59:26 2015 -0700 +@@ -1400,6 +1400,120 @@ + + template + class ChangePointersOopClosure : public OopClosureNoHeader { ++ // import java_lang_invoke_MemberName.* ++ enum { ++ REFERENCE_KIND_SHIFT = java_lang_invoke_MemberName::MN_REFERENCE_KIND_SHIFT, ++ REFERENCE_KIND_MASK = java_lang_invoke_MemberName::MN_REFERENCE_KIND_MASK, ++ }; ++ ++ static oop field_name_or_null(Symbol* s) { ++ if (s == NULL) return NULL; ++ return StringTable::lookup(s); ++ } ++ ++ static oop object_java_mirror() { ++ return Klass::cast(SystemDictionary::Object_klass())->java_mirror(); ++ } ++ ++ static oop field_signature_type_or_null(Symbol* s) { ++ if (s == NULL) return NULL; ++ BasicType bt = FieldType::basic_type(s); ++ if (is_java_primitive(bt)) { ++ assert(s->utf8_length() == 1, ""); ++ return java_lang_Class::primitive_mirror(bt); ++ } ++ // Here are some more short cuts for common types. ++ // They are optional, since reference types can be resolved lazily. ++ if (bt == T_OBJECT) { ++ if (s == vmSymbols::object_signature()) { ++ return object_java_mirror(); ++ } else if (s == vmSymbols::class_signature()) { ++ return Klass::cast(SystemDictionary::Class_klass())->java_mirror(); ++ } else if (s == vmSymbols::string_signature()) { ++ return Klass::cast(SystemDictionary::String_klass())->java_mirror(); ++ } ++ } ++ return NULL; ++ } ++ ++ bool update_member_name(oop obj) { ++ int flags = java_lang_invoke_MemberName::flags(obj); ++ int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK; ++ if (MethodHandles::ref_kind_is_method(ref_kind)) { ++ methodOop m = (methodOop) java_lang_invoke_MemberName::vmtarget(obj); ++ if (m != NULL && !instanceKlass::cast(m->method_holder())->is_newest_version()) { ++ // Let's try to re-resolve method ++ KlassHandle newest = instanceKlass::cast(m->method_holder())->newest_version(); ++ methodOop new_method = instanceKlass::cast(newest())->find_method(m->name(), m->signature()); ++ ++ // Note: we might set NULL at this point, which should force AbstractMethodError at runtime ++ bool do_dispatch = (ref_kind != JVM_REF_invokeSpecial); ++ MethodHandles::init_method_MemberName(obj, new_method, do_dispatch, newest); ++ } ++ } else if (MethodHandles::ref_kind_is_field(ref_kind)) { ++ klassOop k = (klassOop) java_lang_invoke_MemberName::vmtarget(obj); ++ if (k == NULL) { ++ return false; // Was cleared before, this MemberName is invalid. ++ } ++ ++ if (k != NULL && !Klass::cast(k)->is_newest_version()) { ++ // Let's try to re-resolve field ++ fieldDescriptor fd; ++ int offset = java_lang_invoke_MemberName::vmindex(obj); ++ bool is_static = MethodHandles::ref_kind_is_static(ref_kind); ++ instanceKlass *ik = instanceKlass::cast(k); ++ if (ik->find_local_field_from_offset(offset, is_static, &fd)) { ++ KlassHandle newest = Klass::cast(k)->newest_version(); ++ fieldDescriptor fd_new; ++ if (instanceKlass::cast(newest())->find_local_field(fd.name(), fd.signature(), &fd_new)) { ++ bool is_setter = MethodHandles::ref_kind_is_setter(ref_kind); ++ oop type = field_signature_type_or_null(fd_new.signature()); ++ oop name = field_name_or_null(fd_new.name()); ++ MethodHandles::init_field_MemberName(obj, newest, fd_new.access_flags(), type, name, fd_new.offset(), is_setter); ++ } else { ++ // Matching field is not found in new version, not much we can do here. ++ // JVM will crash once faulty MH is invoked. ++ // However, to avoid that all DMH's using this faulty MH are cleared (set to NULL) ++ // Eventually, we probably want to replace them with something more meaningful, ++ // like instance throwing NoSuchFieldError or DMH that will resort to dynamic ++ // field resolution (with possibility of type conversion) ++ java_lang_invoke_MemberName::set_vmtarget(obj, NULL); ++ java_lang_invoke_MemberName::set_vmindex(obj, 0); ++ return false; ++ } ++ } ++ } ++ } ++ return true; ++ } ++ ++ bool update_direct_method_handle(oop obj) { ++ // Always update member name first. ++ oop mem_name = java_lang_invoke_DirectMethodHandle::member(obj); ++ if (!update_member_name(mem_name)) { ++ return false; ++ } ++ ++ // Here we rely on DirectMethodHandle implementation. ++ // The current implementation caches field offset in $StaticAccessor/$Accessor ++ int flags = java_lang_invoke_MemberName::flags(mem_name); ++ int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK; ++ if (MethodHandles::ref_kind_is_field(ref_kind)) { ++ // Note: we don't care about staticBase field (which is java.lang.Class) ++ // It should be processed during normal object update. ++ // Update offset in StaticAccessor ++ int offset = java_lang_invoke_MemberName::vmindex(mem_name); ++ if (offset != 0) { // index of 0 means that field no longer exist ++ if (java_lang_invoke_DirectMethodHandle_StaticAccessor::is_instance(obj)) { ++ java_lang_invoke_DirectMethodHandle_StaticAccessor::set_static_offset(obj, offset); ++ } else if (java_lang_invoke_DirectMethodHandle_Accessor::is_instance(obj)) { ++ java_lang_invoke_DirectMethodHandle_Accessor::set_field_offset(obj, offset); ++ } ++ } ++ } ++ return true; ++ } ++ + // Forward pointers to instanceKlass and mirror class to new versions + template + inline void do_oop_work(T* p) { +@@ -1422,6 +1536,14 @@ + S::oop_store(p, oop); + } + } ++ } else if (java_lang_invoke_MemberName::is_instance(oop)) { ++ update_member_name(oop); ++ } else if (java_lang_invoke_DirectMethodHandle::is_instance(oop)) { ++ if (!update_direct_method_handle(oop)) { ++ // DMH is no longer valid, replace it with null reference. ++ // See note above. We probably want to replace this with something more meaningful. ++ S::oop_store(p, NULL); ++ } + } + } + +@@ -1504,22 +1626,6 @@ + obj->oop_iterate(_closure); + } + +- // Update method handles +- // FIXME: should we also update fields? +- if (java_lang_invoke_MemberName::is_instance(obj)) { +- oop target = java_lang_invoke_MemberName::vmtarget(obj); +- if (target != NULL && target->is_method()) { +- methodOop m = (methodOop) target; +- klassOop holder = m->method_holder(); +- if (!holder->klass_part()->is_newest_version()) { +- // Let's try to re-resolve method +- klassOop newest = holder->klass_part()->newest_version(); +- methodOop new_method = instanceKlass::cast(newest)->find_method(m->name(), m->signature()); +- java_lang_invoke_MemberName::set_vmtarget(obj, new_method); +- } +- } +- } +- + if (obj->blueprint()->new_version() != NULL) { + Klass* new_klass = obj->blueprint()->new_version()->klass_part(); + if (obj->is_perm()) { +@@ -1989,6 +2095,11 @@ + transfer_old_native_function_registrations(the_old_class); + + ++ // Swap method handles ++ MemberNameTable* mnt = the_old_class->member_names(); ++ assert(the_new_class->member_names() == NULL, ""); ++ the_new_class->set_member_names(mnt); ++ the_old_class->set_member_names(NULL); + + #ifdef ASSERT + +diff -r 6858a68213bf -r a416f1b672a4 src/share/vm/runtime/mutexLocker.cpp +--- a/src/share/vm/runtime/mutexLocker.cpp Fri Jul 10 13:18:18 2015 -0700 ++++ b/src/share/vm/runtime/mutexLocker.cpp Fri Jul 10 13:59:26 2015 -0700 +@@ -265,7 +265,7 @@ + def(Heap_lock , Monitor, nonleaf+1, false); + def(JfieldIdCreation_lock , Mutex , nonleaf+1, true ); // jfieldID, Used in VM_Operation + def(JNICachedItableIndex_lock , Mutex , nonleaf+1, false); // Used to cache an itable index during JNI invoke +- def(MemberNameTable_lock , Mutex , nonleaf+1, false); // Used to protect MemberNameTable ++ def(MemberNameTable_lock , Mutex , nonleaf+1, true); // Used to protect MemberNameTable + + def(CompiledIC_lock , Mutex , nonleaf+2, false); // locks VtableStubs_lock, InlineCacheBuffer_lock + def(CompileTaskAlloc_lock , Mutex , nonleaf+2, true ); diff --git a/hotspot/.hg/patches/series b/hotspot/.hg/patches/series index 9a41b8af..d433e418 100644 --- a/hotspot/.hg/patches/series +++ b/hotspot/.hg/patches/series @@ -33,6 +33,7 @@ full-jdk7u51-deopt-cp.patch #+full-jdk7u51-b13 light-jdk7u60-b09.patch #+light-jdk7u60-b09 #+light-jdk7u71-b01 light-jdk7u79-b15.patch #+light-jdk7u79-b15 light-jdk7u60-deopt-cp.patch #+light-jdk7u60-b09 #+light-jdk7u71-b01 #+light-jdk7u79-b15 +light-jdk7u79-b15-method-handles.patch full-jdk7u60-b09.patch #+full-jdk7u60-b09 full-jdk7u71-b01.patch #+full-jdk7u71-b01 full-jdk7u79-b15.patch #+full-jdk7u79-b15 -- 2.39.5