--- old/src/share/vm/prims/methodHandles.hpp 2014-10-17 13:54:44.249437931 -0400 +++ new/src/share/vm/prims/methodHandles.hpp 2014-10-17 13:54:44.153434535 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -228,27 +228,4 @@ void generate(); }; -//------------------------------------------------------------------------------ -// MemberNameTable -// - -class MemberNameTable : public GrowableArray { - public: - MemberNameTable(int methods_cnt); - ~MemberNameTable(); - void add_member_name(int index, jweak mem_name_ref); - oop get_member_name(int index); - -#if INCLUDE_JVMTI - public: - // RedefineClasses() API support: - // If a MemberName refers to old_method then update it - // to refer to new_method. - void adjust_method_entries(Method** old_methods, Method** new_methods, - int methods_length, bool *trace_name_printed); - private: - oop find_member_name_by_method(Method* old_method); -#endif // INCLUDE_JVMTI -}; - #endif // SHARE_VM_PRIMS_METHODHANDLES_HPP --- old/src/share/vm/prims/methodHandles.cpp 2014-10-17 13:54:44.253438072 -0400 +++ new/src/share/vm/prims/methodHandles.cpp 2014-10-17 13:54:44.149434394 -0400 @@ -270,8 +270,6 @@ // If relevant, the vtable or itable value is stored as vmindex. // This is done eagerly, since it is readily available without // constructing any new objects. - // TO DO: maybe intern mname_oop - m->method_holder()->add_member_name(m->method_idnum(), mname); return mname(); } @@ -927,88 +925,6 @@ return rfill + overflow; } -//------------------------------------------------------------------------------ -// MemberNameTable -// - -MemberNameTable::MemberNameTable(int methods_cnt) - : GrowableArray(methods_cnt, true) { - assert_locked_or_safepoint(MemberNameTable_lock); -} - -MemberNameTable::~MemberNameTable() { - assert_locked_or_safepoint(MemberNameTable_lock); - int len = this->length(); - - for (int idx = 0; idx < len; idx++) { - jweak ref = this->at(idx); - JNIHandles::destroy_weak_global(ref); - } -} - -void MemberNameTable::add_member_name(int index, jweak mem_name_wref) { - assert_locked_or_safepoint(MemberNameTable_lock); - this->at_put_grow(index, mem_name_wref); -} - -// Return a member name oop or NULL. -oop MemberNameTable::get_member_name(int index) { - assert_locked_or_safepoint(MemberNameTable_lock); - - jweak ref = this->at(index); - oop mem_name = JNIHandles::resolve(ref); - return mem_name; -} - -#if INCLUDE_JVMTI -oop MemberNameTable::find_member_name_by_method(Method* old_method) { - assert_locked_or_safepoint(MemberNameTable_lock); - oop found = NULL; - int len = this->length(); - - for (int idx = 0; idx < len; idx++) { - oop mem_name = JNIHandles::resolve(this->at(idx)); - if (mem_name == NULL) { - continue; - } - Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mem_name); - if (method == old_method) { - found = mem_name; - break; - } - } - return found; -} - -// It is called at safepoint only -void MemberNameTable::adjust_method_entries(Method** old_methods, Method** new_methods, - int methods_length, bool *trace_name_printed) { - assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); - // search the MemberNameTable for uses of either obsolete or EMCP methods - for (int j = 0; j < methods_length; j++) { - Method* old_method = old_methods[j]; - Method* new_method = new_methods[j]; - oop mem_name = find_member_name_by_method(old_method); - if (mem_name != NULL) { - java_lang_invoke_MemberName::adjust_vmtarget(mem_name, new_method); - - if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { - if (!(*trace_name_printed)) { - // RC_TRACE_MESG macro has an embedded ResourceMark - RC_TRACE_MESG(("adjust: name=%s", - old_method->method_holder()->external_name())); - *trace_name_printed = true; - } - // RC_TRACE macro has an embedded ResourceMark - RC_TRACE(0x00400000, ("MemberName method update: %s(%s)", - new_method->name()->as_C_string(), - new_method->signature()->as_C_string())); - } - } - } -} -#endif // INCLUDE_JVMTI - // // Here are the native methods in java.lang.invoke.MethodHandleNatives // They are the private interface between this JVM and the HotSpot-specific --- old/src/share/vm/runtime/mutexLocker.cpp 2014-10-17 13:54:44.253438072 -0400 +++ new/src/share/vm/runtime/mutexLocker.cpp 2014-10-17 13:54:44.145434252 -0400 @@ -46,7 +46,6 @@ Mutex* VMStatistic_lock = NULL; Mutex* JNIGlobalHandle_lock = NULL; Mutex* JNIHandleBlockFreeList_lock = NULL; -Mutex* MemberNameTable_lock = NULL; Mutex* JmethodIdCreation_lock = NULL; Mutex* JfieldIdCreation_lock = NULL; Monitor* JNICritical_lock = NULL; @@ -258,7 +257,6 @@ } def(Heap_lock , Monitor, nonleaf+1, false); def(JfieldIdCreation_lock , Mutex , nonleaf+1, true ); // jfieldID, Used in VM_Operation - def(MemberNameTable_lock , Mutex , nonleaf+1, false); // Used to protect MemberNameTable def(CompiledIC_lock , Mutex , nonleaf+2, false); // locks VtableStubs_lock, InlineCacheBuffer_lock def(CompileTaskAlloc_lock , Mutex , nonleaf+2, true ); --- old/src/share/vm/classfile/javaClasses.cpp 2014-10-17 13:54:44.253438072 -0400 +++ new/src/share/vm/classfile/javaClasses.cpp 2014-10-17 13:54:44.145434252 -0400 @@ -115,7 +115,7 @@ InstanceKlass* ik = InstanceKlass::cast(klass_oop); if (!find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) { ResourceMark rm; - tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string()); + tty->print_cr("Invalid layout of %s at %s sig %s", ik->external_name(), name_symbol->as_C_string(), signature_symbol->as_C_string()); #ifndef PRODUCT klass_oop->print(); tty->print_cr("all fields:"); @@ -874,11 +874,12 @@ assert(!offsets_computed, "offsets should be initialized only once"); offsets_computed = true; + Thread* THREAD = Thread::current(); Klass* k = SystemDictionary::Class_klass(); + compute_offset(_classData_offset, k, SymbolTable::new_symbol("classData", THREAD), SymbolTable::new_symbol("Ljava/lang/Class$ClassData;", THREAD)); // The classRedefinedCount field is only present starting in 1.5, // so don't go fatal. - compute_optional_offset(classRedefinedCount_offset, - k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature()); + compute_optional_offset(classRedefinedCount_offset, k, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature()); // Needs to be optional because the old build runs Queens during bootstrapping // and jdk8-9 doesn't have coordinated pushes yet. @@ -898,6 +899,10 @@ CLASS_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET); } +oop java_lang_Class::classData(oop obj) { + return obj->obj_field_volatile(_classData_offset); +} + int java_lang_Class::classRedefinedCount(oop the_class_mirror) { if (classRedefinedCount_offset == -1) { // If we don't have an offset for it then just return -1 as a marker. @@ -916,6 +921,30 @@ the_class_mirror->int_field_put(classRedefinedCount_offset, value); } +int java_lang_Class_ClassData::_elementData_offset; +int java_lang_Class_ClassData::_size_offset; + +void java_lang_Class_ClassData::compute_offsets() { + Thread* THREAD = Thread::current(); + Klass* k = SystemDictionary::Class_ClassData_klass(); + compute_offset(_elementData_offset, k, SymbolTable::new_symbol("elementData", THREAD), SymbolTable::new_symbol("[Ljava/lang/Comparable;", THREAD)); + compute_offset(_size_offset, k, SymbolTable::new_symbol("size", THREAD), vmSymbols::int_signature()); +} + +bool java_lang_Class_ClassData::is_instance(oop obj) { + return obj != NULL && obj->klass() == SystemDictionary::Class_ClassData_klass(); +} + +objArrayOop java_lang_Class_ClassData::elementData(oop obj) { + assert(is_instance(obj), err_msg("%s", obj == NULL ? "null" : obj->klass()->external_name())); + return (objArrayOop) obj->obj_field(_elementData_offset); +} + +int java_lang_Class_ClassData::size(oop obj) { + assert(is_instance(obj), err_msg("%s", obj == NULL ? "null" : obj->klass()->external_name())); + return obj->int_field(_size_offset); +} + // Note: JDK1.1 and before had a privateInfo_offset field which was used for the // platform thread structure, and a eetop offset which was used for thread @@ -3130,13 +3159,18 @@ int java_lang_Class::_component_mirror_offset; int java_lang_Class::_init_lock_offset; int java_lang_Class::_signers_offset; +int java_lang_Class::_classData_offset; + GrowableArray* java_lang_Class::_fixup_mirror_list = NULL; + int java_lang_Throwable::backtrace_offset; int java_lang_Throwable::detailMessage_offset; int java_lang_Throwable::cause_offset; int java_lang_Throwable::stackTrace_offset; int java_lang_Throwable::static_unassigned_stacktrace_offset; + int java_lang_reflect_AccessibleObject::override_offset; + int java_lang_reflect_Method::clazz_offset; int java_lang_reflect_Method::name_offset; int java_lang_reflect_Method::returnType_offset; @@ -3149,6 +3183,7 @@ int java_lang_reflect_Method::parameter_annotations_offset; int java_lang_reflect_Method::annotation_default_offset; int java_lang_reflect_Method::type_annotations_offset; + int java_lang_reflect_Constructor::clazz_offset; int java_lang_reflect_Constructor::parameterTypes_offset; int java_lang_reflect_Constructor::exceptionTypes_offset; @@ -3158,6 +3193,7 @@ int java_lang_reflect_Constructor::annotations_offset; int java_lang_reflect_Constructor::parameter_annotations_offset; int java_lang_reflect_Constructor::type_annotations_offset; + int java_lang_reflect_Field::clazz_offset; int java_lang_reflect_Field::name_offset; int java_lang_reflect_Field::type_offset; @@ -3166,12 +3202,15 @@ int java_lang_reflect_Field::signature_offset; int java_lang_reflect_Field::annotations_offset; int java_lang_reflect_Field::type_annotations_offset; + int java_lang_reflect_Parameter::name_offset; int java_lang_reflect_Parameter::modifiers_offset; int java_lang_reflect_Parameter::index_offset; int java_lang_reflect_Parameter::executable_offset; + int java_lang_boxing_object::value_offset; int java_lang_boxing_object::long_value_offset; + int java_lang_ref_Reference::referent_offset; int java_lang_ref_Reference::queue_offset; int java_lang_ref_Reference::next_offset; @@ -3179,25 +3218,34 @@ int java_lang_ref_Reference::static_lock_offset; int java_lang_ref_Reference::static_pending_offset; int java_lang_ref_Reference::number_of_fake_oop_fields; + int java_lang_ref_SoftReference::timestamp_offset; int java_lang_ref_SoftReference::static_clock_offset; + int java_lang_ClassLoader::parent_offset; + int java_lang_System::static_in_offset; int java_lang_System::static_out_offset; int java_lang_System::static_err_offset; int java_lang_System::static_security_offset; + int java_lang_StackTraceElement::declaringClass_offset; int java_lang_StackTraceElement::methodName_offset; int java_lang_StackTraceElement::fileName_offset; int java_lang_StackTraceElement::lineNumber_offset; + int java_lang_AssertionStatusDirectives::classes_offset; int java_lang_AssertionStatusDirectives::classEnabled_offset; int java_lang_AssertionStatusDirectives::packages_offset; int java_lang_AssertionStatusDirectives::packageEnabled_offset; int java_lang_AssertionStatusDirectives::deflt_offset; + int java_nio_Buffer::_limit_offset; + int java_util_concurrent_locks_AbstractOwnableSynchronizer::_owner_offset = 0; + int sun_reflect_ConstantPool::_oop_offset; + int sun_reflect_UnsafeStaticFieldAccessorImpl::_base_offset; @@ -3329,6 +3377,7 @@ // Compute non-hard-coded field offsets of all the classes in this file void JavaClasses::compute_offsets() { // java_lang_Class::compute_offsets was called earlier in bootstrap + java_lang_Class_ClassData::compute_offsets(); java_lang_ClassLoader::compute_offsets(); java_lang_Thread::compute_offsets(); java_lang_ThreadGroup::compute_offsets(); --- old/src/share/vm/runtime/mutexLocker.hpp 2014-10-17 13:54:44.265438496 -0400 +++ new/src/share/vm/runtime/mutexLocker.hpp 2014-10-17 13:54:44.149434394 -0400 @@ -38,7 +38,6 @@ extern Mutex* VMStatistic_lock; // a lock used to guard statistics count increment extern Mutex* JNIGlobalHandle_lock; // a lock on creating JNI global handles extern Mutex* JNIHandleBlockFreeList_lock; // a lock on the JNI handle block free list -extern Mutex* MemberNameTable_lock; // a lock on the MemberNameTable updates extern Mutex* JmethodIdCreation_lock; // a lock on creating JNI method identifiers extern Mutex* JfieldIdCreation_lock; // a lock on creating JNI static field identifiers extern Monitor* JNICritical_lock; // a lock used while entering and exiting JNI critical regions, allows GC to sometimes get in --- old/src/share/vm/classfile/systemDictionary.hpp 2014-10-17 13:54:44.265438496 -0400 +++ new/src/share/vm/classfile/systemDictionary.hpp 2014-10-17 13:54:44.149434394 -0400 @@ -99,6 +99,7 @@ do_klass(Object_klass, java_lang_Object, Pre ) \ do_klass(String_klass, java_lang_String, Pre ) \ do_klass(Class_klass, java_lang_Class, Pre ) \ + do_klass(Class_ClassData_klass, java_lang_Class_ClassData, Pre ) \ do_klass(Cloneable_klass, java_lang_Cloneable, Pre ) \ do_klass(ClassLoader_klass, java_lang_ClassLoader, Pre ) \ do_klass(Serializable_klass, java_io_Serializable, Pre ) \ --- old/src/share/vm/oops/instanceKlass.cpp 2014-10-17 13:54:44.269438638 -0400 +++ new/src/share/vm/oops/instanceKlass.cpp 2014-10-17 13:54:44.149434394 -0400 @@ -2413,17 +2413,6 @@ FreeHeap(jmeths); } - // Deallocate MemberNameTable - { - Mutex* lock_or_null = SafepointSynchronize::is_at_safepoint() ? NULL : MemberNameTable_lock; - MutexLockerEx ml(lock_or_null, Mutex::_no_safepoint_check_flag); - MemberNameTable* mnt = member_names(); - if (mnt != NULL) { - delete mnt; - set_member_names(NULL); - } - } - // release dependencies nmethodBucket* b = _dependencies; _dependencies = NULL; @@ -2774,6 +2763,59 @@ } } } + +static oop find_member_name_by_method(objArrayOop array, int size, Method* old_method) { + for (int i = 0; i < size; i++) { + oop obj = array->obj_at(i); + assert(obj != NULL, ""); + Method* method = (Method*) java_lang_invoke_MemberName::vmtarget(obj); + if (method == old_method) { + return obj; + } + } + return NULL; +} + +/** + * Adjust the java.lang.invoke.MemberName entries in the member name table in + * java.lang.Class$ClassData.memberNameTable. + * + * NOTE: This is called at a safepoint only! + */ +void InstanceKlass::adjust_member_name_table(Method** old_methods, Method** new_methods, + int methods_length, bool *trace_name_printed) { + assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); + + // Dig out the member name table array. + oop class_data = java_lang_Class::classData(java_mirror()); + if (class_data == NULL) + return; // was never initialized + objArrayOop array = java_lang_Class_ClassData::elementData(class_data); + int size = java_lang_Class_ClassData::size(class_data); + + // Search the MemberNameTable for uses of either obsolete or EMCP methods. + for (int i = 0; i < methods_length; i++) { + Method* old_method = old_methods[i]; + Method* new_method = new_methods[i]; + oop member_name = find_member_name_by_method(array, size, old_method); + if (member_name != NULL) { + java_lang_invoke_MemberName::adjust_vmtarget(member_name, new_method); + + if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { + if (!(*trace_name_printed)) { + // RC_TRACE_MESG macro has an embedded ResourceMark + RC_TRACE_MESG(("adjust: name=%s", + old_method->method_holder()->external_name())); + *trace_name_printed = true; + } + // RC_TRACE macro has an embedded ResourceMark + RC_TRACE(0x00400000, ("MemberName method update: %s(%s)", + new_method->name()->as_C_string(), + new_method->signature()->as_C_string())); + } + } + } +} #endif // INCLUDE_JVMTI // On-stack replacement stuff @@ -2889,30 +2931,6 @@ return NULL; } -void InstanceKlass::add_member_name(int index, Handle mem_name) { - jweak mem_name_wref = JNIHandles::make_weak_global(mem_name); - MutexLocker ml(MemberNameTable_lock); - assert(0 <= index && index < idnum_allocated_count(), "index is out of bounds"); - DEBUG_ONLY(No_Safepoint_Verifier nsv); - - if (_member_names == NULL) { - _member_names = new (ResourceObj::C_HEAP, mtClass) MemberNameTable(idnum_allocated_count()); - } - _member_names->add_member_name(index, mem_name_wref); -} - -oop InstanceKlass::get_member_name(int index) { - MutexLocker ml(MemberNameTable_lock); - assert(0 <= index && index < idnum_allocated_count(), "index is out of bounds"); - DEBUG_ONLY(No_Safepoint_Verifier nsv); - - if (_member_names == NULL) { - return NULL; - } - oop mem_name =_member_names->get_member_name(index); - return mem_name; -} - // ----------------------------------------------------------------------------------------------------- // Printing --- old/src/share/vm/oops/instanceKlass.hpp 2014-10-17 13:54:44.273438779 -0400 +++ new/src/share/vm/oops/instanceKlass.hpp 2014-10-17 13:54:44.145434252 -0400 @@ -214,7 +214,6 @@ int _vtable_len; // length of Java vtable (in words) int _itable_len; // length of Java itable (in words) OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily) - MemberNameTable* _member_names; // Member names JNIid* _jni_ids; // First JNI identifier for static fields in this class jmethodID* _methods_jmethod_ids; // jmethodIDs corresponding to method_idnum, or NULL if none nmethodBucket* _dependencies; // list of dependent nmethods @@ -918,6 +917,8 @@ #if INCLUDE_JVMTI void adjust_default_methods(Method** old_methods, Method** new_methods, int methods_length, bool* trace_name_printed); + void adjust_member_name_table(Method** old_methods, Method** new_methods, + int methods_length, bool* trace_name_printed); #endif // INCLUDE_JVMTI // Garbage collection @@ -1054,12 +1055,6 @@ // jvm support jint compute_modifier_flags(TRAPS) const; - // JSR-292 support - MemberNameTable* member_names() { return _member_names; } - void set_member_names(MemberNameTable* member_names) { _member_names = member_names; } - void add_member_name(int index, Handle member_name); - oop get_member_name(int index); - public: // JVMTI support jint jvmti_class_status() const; --- old/src/share/vm/classfile/vmSymbols.hpp 2014-10-17 13:54:44.281439062 -0400 +++ new/src/share/vm/classfile/vmSymbols.hpp 2014-10-17 13:54:44.173435243 -0400 @@ -52,6 +52,7 @@ template(java_lang_System, "java/lang/System") \ template(java_lang_Object, "java/lang/Object") \ template(java_lang_Class, "java/lang/Class") \ + template(java_lang_Class_ClassData, "java/lang/Class$ClassData") \ template(java_lang_String, "java/lang/String") \ template(java_lang_Thread, "java/lang/Thread") \ template(java_lang_ThreadGroup, "java/lang/ThreadGroup") \ @@ -107,7 +108,6 @@ template(java_io_Serializable, "java/io/Serializable") \ template(java_util_Arrays, "java/util/Arrays") \ template(java_util_Properties, "java/util/Properties") \ - template(java_util_Vector, "java/util/Vector") \ template(java_util_AbstractList, "java/util/AbstractList") \ template(java_util_Hashtable, "java/util/Hashtable") \ template(java_lang_Compiler, "java/lang/Compiler") \ --- old/src/share/vm/classfile/javaClasses.hpp 2014-10-17 13:54:44.285439204 -0400 +++ new/src/share/vm/classfile/javaClasses.hpp 2014-10-17 13:54:44.145434252 -0400 @@ -243,6 +243,7 @@ static int _component_mirror_offset; static bool offsets_computed; + static int _classData_offset; static int classRedefinedCount_offset; static GrowableArray* _fixup_mirror_list; @@ -285,6 +286,9 @@ // compiler support for class operations static int klass_offset_in_bytes() { return _klass_offset; } static int array_klass_offset_in_bytes() { return _array_klass_offset; } + + static oop classData(oop obj); + // Support for classRedefinedCount field static int classRedefinedCount(oop the_class_mirror); static void set_classRedefinedCount(oop the_class_mirror, int value); @@ -315,6 +319,25 @@ friend class ClassFileParser; // access to number_of_fake_fields }; +/** + * java.lang.Class$ClassData + */ +class java_lang_Class_ClassData : AllStatic { + friend class JavaClasses; + + private: + static int _elementData_offset; + static int _size_offset; + + static void compute_offsets(); + + public: + static bool is_instance(oop obj); + static oop memberNameTable(oop obj); + static objArrayOop elementData(oop obj); + static int size(oop obj); +}; + // Interface to java.lang.Thread objects class java_lang_Thread : AllStatic { --- old/src/share/vm/prims/jvmtiRedefineClasses.cpp 2014-10-17 13:54:44.289439346 -0400 +++ new/src/share/vm/prims/jvmtiRedefineClasses.cpp 2014-10-17 13:54:44.169435102 -0400 @@ -3481,13 +3481,9 @@ ClassLoaderDataGraph::classes_do(&adjust_cpool_cache_and_vtable); // JSR-292 support - MemberNameTable* mnt = the_class->member_names(); - if (mnt != NULL) { + { bool trace_name_printed = false; - mnt->adjust_method_entries(_matching_old_methods, - _matching_new_methods, - _matching_methods_length, - &trace_name_printed); + the_class->adjust_member_name_table(_matching_old_methods, _matching_new_methods, _matching_methods_length, &trace_name_printed); } // Fix Resolution Error table also to remove old constant pools