# HG changeset patch # User bharadwaj # Date 1367002223 14400 # Node ID fd49109d0d88514e84607d04f7849d7949ad13fe # Parent 93b8272814cf7dfbf8ea51cf74b728e85424f445# Parent 0b55a78c6be5faa83e4fdb8d31c4394db44638fb Merge diff -r 93b8272814cf -r fd49109d0d88 .hgtags --- a/.hgtags Fri Apr 26 08:33:39 2013 -0700 +++ b/.hgtags Fri Apr 26 14:50:23 2013 -0400 @@ -334,4 +334,6 @@ 09b0d3e9ba6cdf7da07d4010d2d1df14596f6864 hs25-b27 6d88a566d369f6a1f86912cad7d0912686b2fda1 hs25-b28 86db4847f195c0ecceea646431f1ff22d56282e8 jdk8-b86 +d4c2667846607042370760e23f64c3ab9350e60d jdk8-b87 01d5f04e64dc2d64625b2db2056f5ed4de918a45 hs25-b29 +c4af77d2045476c56fbf3f914b336bb1b7cd18af hs25-b30 diff -r 93b8272814cf -r fd49109d0d88 make/hotspot_version --- a/make/hotspot_version Fri Apr 26 08:33:39 2013 -0700 +++ b/make/hotspot_version Fri Apr 26 14:50:23 2013 -0400 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=30 +HS_BUILD_NUMBER=31 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r 93b8272814cf -r fd49109d0d88 src/cpu/sparc/vm/interp_masm_sparc.cpp --- a/src/cpu/sparc/vm/interp_masm_sparc.cpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/cpu/sparc/vm/interp_masm_sparc.cpp Fri Apr 26 14:50:23 2013 -0400 @@ -2097,7 +2097,8 @@ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters), method); ld_ptr(method_counters, Rcounters); - br_null_short(Rcounters, Assembler::pn, skip); // No MethodCounters, OutOfMemory + br_null(Rcounters, false, Assembler::pn, skip); // No MethodCounters, OutOfMemory + delayed()->nop(); bind(has_counters); } diff -r 93b8272814cf -r fd49109d0d88 src/os/windows/vm/os_windows.cpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/classfile/altHashing.cpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/classfile/classFileParser.cpp Fri Apr 26 14:50:23 2013 -0400 @@ -436,14 +436,19 @@ ref_index, CHECK_(nullHandle)); break; case JVM_REF_invokeVirtual: - case JVM_REF_invokeStatic: - case JVM_REF_invokeSpecial: case JVM_REF_newInvokeSpecial: check_property( tag.is_method(), "Invalid constant pool index %u in class file %s (not a method)", ref_index, CHECK_(nullHandle)); break; + case JVM_REF_invokeStatic: + case JVM_REF_invokeSpecial: + check_property( + tag.is_method() || tag.is_interface_method(), + "Invalid constant pool index %u in class file %s (not a method)", + ref_index, CHECK_(nullHandle)); + break; case JVM_REF_invokeInterface: check_property( tag.is_interface_method(), @@ -3837,7 +3842,7 @@ } if (TraceClassLoadingPreorder) { - tty->print("[Loading %s", name->as_klass_external_name()); + tty->print("[Loading %s", (name != NULL) ? name->as_klass_external_name() : "NoName"); if (cfs->source() != NULL) tty->print(" from %s", cfs->source()); tty->print_cr("]"); } diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/classfile/genericSignatures.cpp --- a/src/share/vm/classfile/genericSignatures.cpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/classfile/genericSignatures.cpp Fri Apr 26 14:50:23 2013 -0400 @@ -268,8 +268,15 @@ Klass* outer = SystemDictionary::find( outer_name, class_loader, protection_domain, CHECK_NULL); if (outer == NULL && !THREAD->is_Compiler_thread()) { - outer = SystemDictionary::resolve_super_or_fail(original_name, - outer_name, class_loader, protection_domain, false, CHECK_NULL); + if (outer_name == ik->super()->name()) { + outer = SystemDictionary::resolve_super_or_fail(original_name, outer_name, + class_loader, protection_domain, + false, CHECK_NULL); + } + else { + outer = SystemDictionary::resolve_or_fail(outer_name, class_loader, + protection_domain, false, CHECK_NULL); + } } InstanceKlass* outer_ik; diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/classfile/javaClasses.cpp Fri Apr 26 14:50:23 2013 -0400 @@ -2625,6 +2625,15 @@ return (Metadata*)mname->address_field(_vmtarget_offset); } +#if INCLUDE_JVMTI +// Can be executed on VM thread only +void java_lang_invoke_MemberName::adjust_vmtarget(oop mname, Metadata* ref) { + assert((is_instance(mname) && (flags(mname) & (MN_IS_METHOD | MN_IS_CONSTRUCTOR)) > 0), "wrong type"); + assert(Thread::current()->is_VM_thread(), "not VM thread"); + mname->address_field_put(_vmtarget_offset, (address)ref); +} +#endif // INCLUDE_JVMTI + void java_lang_invoke_MemberName::set_vmtarget(oop mname, Metadata* ref) { assert(is_instance(mname), "wrong type"); // check the type of the vmtarget diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/classfile/javaClasses.hpp --- a/src/share/vm/classfile/javaClasses.hpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/classfile/javaClasses.hpp Fri Apr 26 14:50:23 2013 -0400 @@ -1036,6 +1036,9 @@ static Metadata* vmtarget(oop mname); static void set_vmtarget(oop mname, Metadata* target); +#if INCLUDE_JVMTI + static void adjust_vmtarget(oop mname, Metadata* target); +#endif // INCLUDE_JVMTI static intptr_t vmindex(oop mname); static void set_vmindex(oop mname, intptr_t index); diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/interpreter/linkResolver.cpp --- a/src/share/vm/interpreter/linkResolver.cpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/interpreter/linkResolver.cpp Fri Apr 26 14:50:23 2013 -0400 @@ -1014,13 +1014,28 @@ resolved_method->name(), resolved_method->signature())); } - // check if public - if (!sel_method->is_public()) { - ResourceMark rm(THREAD); - THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), - Method::name_and_sig_as_C_string(recv_klass(), - sel_method->name(), - sel_method->signature())); + // check access + if (sel_method->method_holder()->is_interface()) { + // Method holder is an interface. Throw Illegal Access Error if sel_method + // is neither public nor private. + if (!(sel_method->is_public() || sel_method->is_private())) { + ResourceMark rm(THREAD); + THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), + Method::name_and_sig_as_C_string(recv_klass(), + sel_method->name(), + sel_method->signature())); + } + } + else { + // Method holder is a class. Throw Illegal Access Error if sel_method + // is not public. + if (!sel_method->is_public()) { + ResourceMark rm(THREAD); + THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), + Method::name_and_sig_as_C_string(recv_klass(), + sel_method->name(), + sel_method->signature())); + } } // check if abstract if (check_null_and_abstract && sel_method->is_abstract()) { diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/memory/allocation.cpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/memory/allocation.hpp --- a/src/share/vm/memory/allocation.hpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/memory/allocation.hpp Fri Apr 26 14:50:23 2013 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, 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 diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/memory/allocation.inline.hpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/memory/cardTableModRefBS.cpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/memory/cardTableModRefBS.hpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/memory/cardTableRS.cpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/memory/cardTableRS.hpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/memory/collectorPolicy.cpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/oops/instanceKlass.cpp Fri Apr 26 14:50:23 2013 -0400 @@ -2329,6 +2329,12 @@ FreeHeap(jmeths); } + MemberNameTable* mnt = member_names(); + if (mnt != NULL) { + delete mnt; + set_member_names(NULL); + } + int* indices = methods_cached_itable_indices_acquire(); if (indices != (int*)NULL) { release_set_methods_cached_itable_indices(NULL); @@ -2757,6 +2763,17 @@ return NULL; } +void InstanceKlass::add_member_name(Handle mem_name) { + jweak mem_name_wref = JNIHandles::make_weak_global(mem_name); + MutexLocker ml(MemberNameTable_lock); + DEBUG_ONLY(No_Safepoint_Verifier nsv); + + if (_member_names == NULL) { + _member_names = new (ResourceObj::C_HEAP, mtClass) MemberNameTable(); + } + _member_names->add_member_name(mem_name_wref); +} + // ----------------------------------------------------------------------------------------------------- // Printing diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/oops/instanceKlass.hpp Fri Apr 26 14:50:23 2013 -0400 @@ -90,6 +90,7 @@ class nmethodBucket; class PreviousVersionNode; class JvmtiCachedClassFieldMap; +class MemberNameTable; // This is used in iterators below. class FieldClosure: public StackObj { @@ -246,6 +247,7 @@ 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 int* _methods_cached_itable_indices; // itable_index cache for JNI invoke corresponding to methods idnum, or NULL @@ -1028,6 +1030,11 @@ // 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(Handle member_name); + public: // JVMTI support jint jvmti_class_status() const; diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/opto/idealGraphPrinter.hpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/opto/library_call.cpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Apr 26 14:50:23 2013 -0400 @@ -3284,6 +3284,16 @@ // that reference methods of the evolved class. SystemDictionary::classes_do(adjust_cpool_cache_and_vtable, THREAD); + // 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); + } + // Fix Resolution Error table also to remove old constant pools SystemDictionary::delete_resolution_error(old_constants); diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/prims/methodHandles.cpp --- a/src/share/vm/prims/methodHandles.cpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/prims/methodHandles.cpp Fri Apr 26 14:50:23 2013 -0400 @@ -29,6 +29,7 @@ #include "interpreter/oopMapCache.hpp" #include "memory/allocation.inline.hpp" #include "memory/oopFactory.hpp" +#include "prims/jvmtiRedefineClassesTrace.hpp" #include "prims/methodHandles.hpp" #include "runtime/compilationPolicy.hpp" #include "runtime/javaCalls.hpp" @@ -124,7 +125,9 @@ return Handle(THREAD, k->allocate_instance(THREAD)); } -oop MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { +oop MethodHandles::init_MemberName(Handle mname, Handle target) { + Thread* thread = Thread::current(); + oop target_oop = target(); Klass* target_klass = target_oop->klass(); if (target_klass == SystemDictionary::reflect_Field_klass()) { oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder() @@ -132,24 +135,24 @@ int mods = java_lang_reflect_Field::modifiers(target_oop); oop type = java_lang_reflect_Field::type(target_oop); oop name = java_lang_reflect_Field::name(target_oop); - Klass* k = java_lang_Class::as_Klass(clazz); - intptr_t offset = InstanceKlass::cast(k)->field_offset(slot); - return init_field_MemberName(mname_oop, k, accessFlags_from(mods), type, name, offset); + KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); + intptr_t offset = InstanceKlass::cast(k())->field_offset(slot); + return init_field_MemberName(mname, k, accessFlags_from(mods), type, name, offset); } else if (target_klass == SystemDictionary::reflect_Method_klass()) { oop clazz = java_lang_reflect_Method::clazz(target_oop); int slot = java_lang_reflect_Method::slot(target_oop); - Klass* k = java_lang_Class::as_Klass(clazz); - if (k != NULL && k->oop_is_instance()) { - Method* m = InstanceKlass::cast(k)->method_with_idnum(slot); - return init_method_MemberName(mname_oop, m, true, k); + KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); + if (!k.is_null() && k->oop_is_instance()) { + Method* m = InstanceKlass::cast(k())->method_with_idnum(slot); + return init_method_MemberName(mname, m, true, k); } } else if (target_klass == SystemDictionary::reflect_Constructor_klass()) { oop clazz = java_lang_reflect_Constructor::clazz(target_oop); int slot = java_lang_reflect_Constructor::slot(target_oop); - Klass* k = java_lang_Class::as_Klass(clazz); - if (k != NULL && k->oop_is_instance()) { - Method* m = InstanceKlass::cast(k)->method_with_idnum(slot); - return init_method_MemberName(mname_oop, m, false, k); + KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); + if (!k.is_null() && k->oop_is_instance()) { + Method* m = InstanceKlass::cast(k())->method_with_idnum(slot); + return init_method_MemberName(mname, m, false, k); } } else if (target_klass == SystemDictionary::MemberName_klass()) { // Note: This only works if the MemberName has already been resolved. @@ -157,17 +160,18 @@ int flags = java_lang_invoke_MemberName::flags(target_oop); Metadata* vmtarget=java_lang_invoke_MemberName::vmtarget(target_oop); intptr_t vmindex = java_lang_invoke_MemberName::vmindex(target_oop); - Klass* k = java_lang_Class::as_Klass(clazz); + KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK; if (vmtarget == NULL) return NULL; // not resolved if ((flags & IS_FIELD) != 0) { assert(vmtarget->is_klass(), "field vmtarget is Klass*"); int basic_mods = (ref_kind_is_static(ref_kind) ? JVM_ACC_STATIC : 0); // FIXME: how does k (receiver_limit) contribute? - return init_field_MemberName(mname_oop, (Klass*)vmtarget, accessFlags_from(basic_mods), NULL, NULL, vmindex); + KlassHandle k_vmtarget(thread, (Klass*)vmtarget); + return init_field_MemberName(mname, k_vmtarget, accessFlags_from(basic_mods), NULL, NULL, vmindex); } else if ((flags & (IS_METHOD | IS_CONSTRUCTOR)) != 0) { assert(vmtarget->is_method(), "method or constructor vmtarget is Method*"); - return init_method_MemberName(mname_oop, (Method*)vmtarget, ref_kind_does_dispatch(ref_kind), k); + return init_method_MemberName(mname, (Method*)vmtarget, ref_kind_does_dispatch(ref_kind), k); } else { return NULL; } @@ -175,8 +179,9 @@ return NULL; } -oop MethodHandles::init_method_MemberName(oop mname_oop, Method* m, bool do_dispatch, - Klass* receiver_limit) { +oop MethodHandles::init_method_MemberName(Handle mname, Method* m, bool do_dispatch, + KlassHandle receiver_limit_h) { + Klass* receiver_limit = receiver_limit_h(); AccessFlags mods = m->access_flags(); int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS ); int vmindex = Method::nonvirtual_vtable_index; // implies never any dispatch @@ -187,6 +192,10 @@ flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT); } else if (mods.is_static()) { flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT); + // Get vindex from itable if method holder is an interface. + if (m->method_holder()->is_interface()) { + vmindex = klassItable::compute_itable_index(m); + } } else if (receiver_limit != mklass && !receiver_limit->is_subtype_of(mklass)) { return NULL; // bad receiver limit @@ -213,6 +222,7 @@ flags |= CALLER_SENSITIVE; } + oop mname_oop = mname(); java_lang_invoke_MemberName::set_flags( mname_oop, flags); java_lang_invoke_MemberName::set_vmtarget(mname_oop, m); java_lang_invoke_MemberName::set_vmindex( mname_oop, vmindex); // vtable/itable index @@ -225,10 +235,11 @@ // This is done eagerly, since it is readily available without // constructing any new objects. // TO DO: maybe intern mname_oop - return mname_oop; + m->method_holder()->add_member_name(mname); + return mname(); } -Handle MethodHandles::init_method_MemberName(oop mname_oop, CallInfo& info, TRAPS) { +Handle MethodHandles::init_method_MemberName(Handle mname, CallInfo& info, TRAPS) { Handle empty; if (info.resolved_appendix().not_null()) { // The resolved MemberName must not be accompanied by an appendix argument, @@ -248,19 +259,20 @@ } else { vmindex = info.vtable_index(); } - oop res = init_method_MemberName(mname_oop, m(), (vmindex >= 0), defc()); + oop res = init_method_MemberName(mname, m(), (vmindex >= 0), defc()); assert(res == NULL || (java_lang_invoke_MemberName::vmindex(res) == vmindex), ""); return Handle(THREAD, res); } -oop MethodHandles::init_field_MemberName(oop mname_oop, Klass* field_holder, +oop MethodHandles::init_field_MemberName(Handle mname, KlassHandle field_holder, AccessFlags mods, oop type, oop name, intptr_t offset, bool is_setter) { int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS ); flags |= IS_FIELD | ((mods.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT); if (is_setter) flags += ((JVM_REF_putField - JVM_REF_getField) << REFERENCE_KIND_SHIFT); - Metadata* vmtarget = field_holder; + Metadata* vmtarget = field_holder(); int vmindex = offset; // determines the field uniquely when combined with static bit + oop mname_oop = mname(); java_lang_invoke_MemberName::set_flags(mname_oop, flags); java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget); java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex); @@ -277,10 +289,11 @@ // Although the fieldDescriptor::_index would also identify the field, // we do not use it, because it is harder to decode. // TO DO: maybe intern mname_oop - return mname_oop; + InstanceKlass::cast(field_holder())->add_member_name(mname); + return mname(); } -Handle MethodHandles::init_field_MemberName(oop mname_oop, FieldAccessInfo& info, TRAPS) { +Handle MethodHandles::init_field_MemberName(Handle mname, FieldAccessInfo& info, TRAPS) { return Handle(); #if 0 // FIXME KlassHandle field_holder = info.klass(); @@ -679,7 +692,7 @@ return empty; } } - return init_method_MemberName(mname(), result, THREAD); + return init_method_MemberName(mname, result, THREAD); } case IS_CONSTRUCTOR: { @@ -697,7 +710,7 @@ } } assert(result.is_statically_bound(), ""); - return init_method_MemberName(mname(), result, THREAD); + return init_method_MemberName(mname, result, THREAD); } case IS_FIELD: { @@ -710,7 +723,7 @@ oop name = field_name_or_null(fd.name()); bool is_setter = (ref_kind_is_valid(ref_kind) && ref_kind_is_setter(ref_kind)); mname = Handle(THREAD, - init_field_MemberName(mname(), sel_klass(), + init_field_MemberName(mname, sel_klass, fd.access_flags(), type, name, fd.offset(), is_setter)); return mname; } @@ -802,16 +815,15 @@ THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format"); } -int MethodHandles::find_MemberNames(Klass* k, +int MethodHandles::find_MemberNames(KlassHandle k, Symbol* name, Symbol* sig, - int mflags, Klass* caller, - int skip, objArrayOop results) { - DEBUG_ONLY(No_Safepoint_Verifier nsv); - // this code contains no safepoints! - + int mflags, KlassHandle caller, + int skip, objArrayHandle results) { // %%% take caller into account! - if (k == NULL || !k->oop_is_instance()) return -1; + Thread* thread = Thread::current(); + + if (k.is_null() || !k->oop_is_instance()) return -1; int rfill = 0, rlimit = results->length(), rskip = skip; // overflow measurement: @@ -839,7 +851,7 @@ } if ((match_flags & IS_FIELD) != 0) { - for (FieldStream st(k, local_only, !search_intfc); !st.eos(); st.next()) { + for (FieldStream st(k(), local_only, !search_intfc); !st.eos(); st.next()) { if (name != NULL && st.name() != name) continue; if (sig != NULL && st.signature() != sig) @@ -848,15 +860,15 @@ if (rskip > 0) { --rskip; } else if (rfill < rlimit) { - oop result = results->obj_at(rfill++); - if (!java_lang_invoke_MemberName::is_instance(result)) + Handle result(thread, results->obj_at(rfill++)); + if (!java_lang_invoke_MemberName::is_instance(result())) return -99; // caller bug! oop type = field_signature_type_or_null(st.signature()); oop name = field_name_or_null(st.name()); - oop saved = MethodHandles::init_field_MemberName(result, st.klass()(), + oop saved = MethodHandles::init_field_MemberName(result, st.klass(), st.access_flags(), type, name, st.offset()); - if (saved != result) + if (saved != result()) results->obj_at_put(rfill-1, saved); // show saved instance to user } else if (++overflow >= overflow_limit) { match_flags = 0; break; // got tired of looking at overflow @@ -889,7 +901,7 @@ } else { // caller will accept either sort; no need to adjust name } - for (MethodStream st(k, local_only, !search_intfc); !st.eos(); st.next()) { + for (MethodStream st(k(), local_only, !search_intfc); !st.eos(); st.next()) { Method* m = st.method(); Symbol* m_name = m->name(); if (m_name == clinit_name) @@ -902,11 +914,11 @@ if (rskip > 0) { --rskip; } else if (rfill < rlimit) { - oop result = results->obj_at(rfill++); - if (!java_lang_invoke_MemberName::is_instance(result)) + Handle result(thread, results->obj_at(rfill++)); + if (!java_lang_invoke_MemberName::is_instance(result())) return -99; // caller bug! oop saved = MethodHandles::init_method_MemberName(result, m, true, NULL); - if (saved != result) + if (saved != result()) results->obj_at_put(rfill-1, saved); // show saved instance to user } else if (++overflow >= overflow_limit) { match_flags = 0; break; // got tired of looking at overflow @@ -917,6 +929,99 @@ // return number of elements we at leasted wanted to initialize return rfill + overflow; } + +//------------------------------------------------------------------------------ +// MemberNameTable +// + +MemberNameTable::MemberNameTable() : GrowableArray(10, 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); + } +} + +// Return entry index if found, return -1 otherwise. +int MemberNameTable::find_member_name(oop mem_name) { + assert_locked_or_safepoint(MemberNameTable_lock); + int len = this->length(); + + for (int idx = 0; idx < len; idx++) { + jweak ref = this->at(idx); + oop entry = JNIHandles::resolve(ref); + if (entry == mem_name) { + return idx; + } + } + return -1; +} + +void MemberNameTable::add_member_name(jweak mem_name_wref) { + assert_locked_or_safepoint(MemberNameTable_lock); + oop mem_name = JNIHandles::resolve(mem_name_wref); + + // Each member name may appear just once: add only if not found + if (find_member_name(mem_name) == -1) { + this->append(mem_name_wref); + } +} + +#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 @@ -1010,8 +1115,8 @@ if (mname_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); } if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); } Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); - oop target_oop = JNIHandles::resolve_non_null(target_jh); - MethodHandles::init_MemberName(mname(), target_oop); + Handle target(THREAD, JNIHandles::resolve_non_null(target_jh)); + MethodHandles::init_MemberName(mname, target); } JVM_END @@ -1118,7 +1223,7 @@ x = ((Klass*) vmtarget)->java_mirror(); } else if (vmtarget->is_method()) { Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL); - x = MethodHandles::init_method_MemberName(mname2(), (Method*)vmtarget, false, NULL); + x = MethodHandles::init_method_MemberName(mname2, (Method*)vmtarget, false, NULL); } result->obj_at_put(1, x); return JNIHandles::make_local(env, result()); @@ -1161,8 +1266,8 @@ // %%% TO DO } - int res = MethodHandles::find_MemberNames(k(), name, sig, mflags, - caller(), skip, results()); + int res = MethodHandles::find_MemberNames(k, name, sig, mflags, + caller, skip, results); // TO DO: expand at least some of the MemberNames, to avoid massive callbacks return res; } diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/prims/methodHandles.hpp --- a/src/share/vm/prims/methodHandles.hpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/prims/methodHandles.hpp Fri Apr 26 14:50:23 2013 -0400 @@ -54,23 +54,23 @@ static Handle resolve_MemberName(Handle mname, TRAPS); // compute vmtarget/vmindex from name/type static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing static Handle new_MemberName(TRAPS); // must be followed by init_MemberName - static oop init_MemberName(oop mname_oop, oop target_oop); // compute vmtarget/vmindex from target - static oop init_method_MemberName(oop mname_oop, Method* m, bool do_dispatch, - Klass* receiver_limit); - static oop init_field_MemberName(oop mname_oop, Klass* field_holder, + static oop init_MemberName(Handle mname_h, Handle target_h); // compute vmtarget/vmindex from target + static oop init_method_MemberName(Handle mname_h, Method* m, bool do_dispatch, + KlassHandle receiver_limit_h); + static oop init_field_MemberName(Handle mname_h, KlassHandle field_holder_h, AccessFlags mods, oop type, oop name, intptr_t offset, bool is_setter = false); - static Handle init_method_MemberName(oop mname_oop, CallInfo& info, TRAPS); - static Handle init_field_MemberName(oop mname_oop, FieldAccessInfo& info, TRAPS); + static Handle init_method_MemberName(Handle mname_h, CallInfo& info, TRAPS); + static Handle init_field_MemberName(Handle mname_h, FieldAccessInfo& info, TRAPS); static int method_ref_kind(Method* m, bool do_dispatch_if_possible = true); - static int find_MemberNames(Klass* k, Symbol* name, Symbol* sig, - int mflags, Klass* caller, - int skip, objArrayOop results); + static int find_MemberNames(KlassHandle k, Symbol* name, Symbol* sig, + int mflags, KlassHandle caller, + int skip, objArrayHandle results); // bit values for suppress argument to expand_MemberName: enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 }; // Generate MethodHandles adapters. - static void generate_adapters(); + static void generate_adapters(); // Called from MethodHandlesAdapterGenerator. static address generate_method_handle_interpreter_entry(MacroAssembler* _masm, vmIntrinsics::ID iid); @@ -230,4 +230,27 @@ void generate(); }; +//------------------------------------------------------------------------------ +// MemberNameTable +// +class MemberNameTable : public GrowableArray { + public: + MemberNameTable(); + ~MemberNameTable(); + void add_member_name(jweak mem_name_ref); + private: + int find_member_name(oop mem_name); + +#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 diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/runtime/arguments.cpp Fri Apr 26 14:50:23 2013 -0400 @@ -1901,7 +1901,7 @@ // Divide by bucket size to prevent a large size from causing rollover when // calculating amount of memory needed to be allocated for the String table. - status = status && verify_interval(StringTableSize, defaultStringTableSize, + status = status && verify_interval(StringTableSize, minimumStringTableSize, (max_uintx / StringTable::bucket_size()), "StringTable size"); if (MinHeapFreeRatio > MaxHeapFreeRatio) { diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/runtime/handles.hpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/runtime/mutexLocker.cpp --- a/src/share/vm/runtime/mutexLocker.cpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/runtime/mutexLocker.cpp Fri Apr 26 14:50:23 2013 -0400 @@ -46,6 +46,7 @@ Mutex* JNIGlobalHandle_lock = NULL; Mutex* JNIHandleBlockFreeList_lock = NULL; Mutex* JNICachedItableIndex_lock = NULL; +Mutex* MemberNameTable_lock = NULL; Mutex* JmethodIdCreation_lock = NULL; Mutex* JfieldIdCreation_lock = NULL; Monitor* JNICritical_lock = NULL; @@ -252,6 +253,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(CompiledIC_lock , Mutex , nonleaf+2, false); // locks VtableStubs_lock, InlineCacheBuffer_lock def(CompileTaskAlloc_lock , Mutex , nonleaf+2, true ); diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/runtime/mutexLocker.hpp --- a/src/share/vm/runtime/mutexLocker.hpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/runtime/mutexLocker.hpp Fri Apr 26 14:50:23 2013 -0400 @@ -51,6 +51,7 @@ 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* JNICachedItableIndex_lock; // a lock on caching an itable index during JNI invoke +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 diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/runtime/reflectionUtils.hpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/runtime/synchronizer.cpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/runtime/thread.cpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/runtime/vmStructs.cpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/services/management.cpp --- a/src/share/vm/services/management.cpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/services/management.cpp Fri Apr 26 14:50:23 2013 -0400 @@ -2126,7 +2126,7 @@ THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "Output file name cannot be null.", -1); } - char* name = java_lang_String::as_utf8_string(on); + char* name = java_lang_String::as_platform_dependent_str(on, CHECK_(-1)); if (name == NULL) { THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "Output file name cannot be null.", -1); diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/services/memBaseline.hpp --- a/src/share/vm/services/memBaseline.hpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/services/memBaseline.hpp Fri Apr 26 14:50:23 2013 -0400 @@ -133,7 +133,7 @@ // This class aggregates malloc'd records by memory type -class MallocMem : public _ValueObj { +class MallocMem VALUE_OBJ_CLASS_SPEC { private: MEMFLAGS _type; @@ -211,7 +211,7 @@ }; // This class aggregates virtual memory by its memory type -class VMMem : public _ValueObj { +class VMMem VALUE_OBJ_CLASS_SPEC { private: MEMFLAGS _type; @@ -296,7 +296,7 @@ * aggregates memory usage by callsites when detail tracking * is on. */ -class MemBaseline : public _ValueObj { +class MemBaseline VALUE_OBJ_CLASS_SPEC { friend class BaselineReporter; friend class BaselineComparisonReporter; diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/services/memPtr.hpp --- a/src/share/vm/services/memPtr.hpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/services/memPtr.hpp Fri Apr 26 14:50:23 2013 -0400 @@ -89,7 +89,7 @@ * the memory pointer either points to a malloc'd * memory block, or a mmap'd memory block */ -class MemPointer : public _ValueObj { +class MemPointer VALUE_OBJ_CLASS_SPEC { public: MemPointer(): _addr(0) { } MemPointer(address addr): _addr(addr) { } diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/services/memSnapshot.hpp --- a/src/share/vm/services/memSnapshot.hpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/services/memSnapshot.hpp Fri Apr 26 14:50:23 2013 -0400 @@ -308,7 +308,7 @@ } }; -class StagingArea : public _ValueObj { +class StagingArea VALUE_OBJ_CLASS_SPEC { private: MemPointerArray* _malloc_data; MemPointerArray* _vm_data; diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/services/memTrackWorker.hpp --- a/src/share/vm/services/memTrackWorker.hpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/services/memTrackWorker.hpp Fri Apr 26 14:50:23 2013 -0400 @@ -32,7 +32,7 @@ // Maximum MAX_GENERATIONS generation data can be tracked. #define MAX_GENERATIONS 512 -class GenerationData : public _ValueObj { +class GenerationData VALUE_OBJ_CLASS_SPEC { private: int _number_of_classes; MemRecorder* _recorder_list; diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/utilities/events.hpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/utilities/globalDefinitions.hpp --- a/src/share/vm/utilities/globalDefinitions.hpp Fri Apr 26 08:33:39 2013 -0700 +++ b/src/share/vm/utilities/globalDefinitions.hpp Fri Apr 26 14:50:23 2013 -0400 @@ -328,9 +328,10 @@ //---------------------------------------------------------------------------------------------------- -// Minimum StringTableSize value +// Default and minimum StringTableSize values -const int defaultStringTableSize=1009; +const int defaultStringTableSize = NOT_LP64(1009) LP64_ONLY(60013); +const int minimumStringTableSize=1009; //---------------------------------------------------------------------------------------------------- diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/utilities/quickSort.cpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/utilities/workgroup.cpp diff -r 93b8272814cf -r fd49109d0d88 src/share/vm/utilities/workgroup.hpp