Browse Source

Support for Java7u79

tags/full-jdk7u79+4^2
Ivan Dubrov 8 years ago
parent
commit
3f9d18a405

+ 1
- 0
build.gradle View File

@@ -78,6 +78,7 @@ project('hotspot') {
exec {
executable 'hg'
args 'qpop', '-a'
ignoreExitValue = true
}
exec {
executable 'hg'

+ 31
- 3
dcevm/src/test/java7/com/github/dcevm/test/methods/MethodHandleTest.java View File

@@ -46,6 +46,11 @@ public class MethodHandleTest {

// Version 0
public static class A {
public int field;
public A(int value) {
field = value;
}

public int method() {
return 1;
}
@@ -65,6 +70,11 @@ public class MethodHandleTest {

// Version 1
public static class A___1 {
public int field;
public A___1(int value) {
field = value * 10;
}

public int method() {
return 2;
}
@@ -95,7 +105,7 @@ public class MethodHandleTest {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle handle = lookup.findVirtual(A.class, "method", MethodType.methodType(int.class));

A a = new A();
A a = new A(3);
assertEquals(1, (int) handle.invokeExact(a));

__toVersion__(1);
@@ -114,7 +124,7 @@ public class MethodHandleTest {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle handle = lookup.findVirtual(A.class, "method", MethodType.methodType(int.class));

A a = new A();
A a = new A(3);
MethodHandle boundHandle = handle.bindTo(a);
assertEquals(1, (int) boundHandle.invokeExact());

@@ -144,6 +154,24 @@ public class MethodHandleTest {
assert __version__() == 0;
}

@Test
public void testConstructorMethodHandleUpdated() throws Throwable {

assert __version__() == 0;

MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle handle = lookup.findConstructor(A.class, MethodType.methodType(void.class, int.class));

assertEquals(12, ((A) handle.invoke(12)).field);

__toVersion__(1);

assertEquals(120, ((A) handle.invoke(12)).field);

__toVersion__(0);
assert __version__() == 0;
}

@Test
public void testComplexMethodHandleUpdated() throws Throwable {

@@ -154,7 +182,7 @@ public class MethodHandleTest {
MethodHandle filter = lookup.findVirtual(A.class, "filter", MethodType.methodType(int.class, int.class));
MethodHandle staticFilter = lookup.findStatic(A.class, "staticFilter", MethodType.methodType(int.class, int.class));

A a = new A();
A a = new A(3);
MethodHandle boundFilter = filter.bindTo(a);
handle = MethodHandles.filterReturnValue(handle, staticFilter);
handle = MethodHandles.filterReturnValue(handle, boundFilter);

+ 1
- 1
gradle.properties View File

@@ -31,7 +31,7 @@ targetJre=build/jre
#hotspotTag=jdk7u55-b13
#hotspotTag=jdk7u60-b09
#hotspotTag=jdk7u71-b01
#hotspotTag=jdk7u79-b02
#hotspotTag=jdk7u79-b15

#hotspotTag=jdk8u31-b13
#hotspotTag=jdk8u20-b22

+ 328
- 0
hotspot/.hg/patches/full-jdk7u79-b15-method-handles.patch View File

@@ -0,0 +1,328 @@
# HG changeset patch
# Parent 2ffb90b422e20ff948d25b96bfb9be923c130734

diff -r 2ffb90b422e2 src/share/vm/classfile/javaClasses.cpp
--- a/src/share/vm/classfile/javaClasses.cpp Fri Jul 10 10:19:24 2015 -0700
+++ b/src/share/vm/classfile/javaClasses.cpp Fri Jul 10 10:19:37 2015 -0700
@@ -2409,6 +2409,52 @@
}
}
+// 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;
@@ -3028,6 +3074,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 2ffb90b422e2 src/share/vm/classfile/javaClasses.hpp
--- a/src/share/vm/classfile/javaClasses.hpp Fri Jul 10 10:19:24 2015 -0700
+++ b/src/share/vm/classfile/javaClasses.hpp Fri Jul 10 10:19:37 2015 -0700
@@ -940,6 +940,54 @@
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 2ffb90b422e2 src/share/vm/classfile/systemDictionary.hpp
--- a/src/share/vm/classfile/systemDictionary.hpp Fri Jul 10 10:19:24 2015 -0700
+++ b/src/share/vm/classfile/systemDictionary.hpp Fri Jul 10 10:19:37 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 2ffb90b422e2 src/share/vm/classfile/vmSymbols.hpp
--- a/src/share/vm/classfile/vmSymbols.hpp Fri Jul 10 10:19:24 2015 -0700
+++ b/src/share/vm/classfile/vmSymbols.hpp Fri Jul 10 10:19:37 2015 -0700
@@ -248,6 +248,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") \
@@ -485,6 +487,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 2ffb90b422e2 src/share/vm/prims/jvmtiRedefineClasses.cpp
--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Jul 10 10:19:24 2015 -0700
+++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Jul 10 10:19:37 2015 -0700
@@ -2110,6 +2110,120 @@
}
+// 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;
+}
+
template <class T> void VM_RedefineClasses::do_oop_work(T* p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
@@ -2148,6 +2262,18 @@
}
}
}
+ } else {
+ // JSR 292 support, uptade java.lang.invoke.MemberName instances
+ if (java_lang_invoke_MemberName::is_instance(obj)) {
+ update_member_name(obj);
+ } else if (java_lang_invoke_DirectMethodHandle::is_instance(obj)) {
+ if (!update_direct_method_handle(obj)) {
+ // DMH is no longer valid, replace it with null reference.
+ // See note above. We probably want to replace this with something more meaningful.
+ oopDesc::encode_store_heap_oop_not_null(p, NULL);
+ //S::oop_store(p, NULL);
+ }
+ }
}
}
}
@@ -2822,6 +2948,11 @@
// TODO:
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 2ffb90b422e2 src/share/vm/runtime/mutexLocker.cpp
--- a/src/share/vm/runtime/mutexLocker.cpp Fri Jul 10 10:19:24 2015 -0700
+++ b/src/share/vm/runtime/mutexLocker.cpp Fri Jul 10 10:19:37 2015 -0700
@@ -267,7 +267,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 );

hotspot/.hg/patches/full-jdk7u79-b15.patch
File diff suppressed because it is too large
View File


+ 3
- 2
hotspot/.hg/patches/series View File

@@ -35,8 +35,9 @@ light-jdk7u79-b02.patch #+light-jdk7u79-b02
light-jdk7u60-deopt-cp.patch #+light-jdk7u60-b09 #+light-jdk7u71-b01 #+light-jdk7u79-b02
full-jdk7u60-b09.patch #+full-jdk7u60-b09
full-jdk7u71-b01.patch #+full-jdk7u71-b01
full-jdk7u79-b02.patch #+full-jdk7u79-b02
full-jdk7u60-deopt-cp.patch #+full-jdk7u60-b09 #+full-jdk7u71-b01 #+full-jdk7u79-b02
full-jdk7u79-b15.patch #+full-jdk7u79-b15
full-jdk7u60-deopt-cp.patch #+full-jdk7u60-b09 #+full-jdk7u71-b01 #+full-jdk7u79-b15
full-jdk7u79-b15-method-handles.patch #+full-jdk7u79-b15

light-jdk8u5-b13.patch #+light-jdk8u5-b13


Loading…
Cancel
Save