OpenJDK / valhalla / valhalla
changeset 52833:0d1ec73b6d87 nestmates
VM support for classData
Summary: store classData in an injected filed of the java.lang.Class instance
Reviewed-by: lfoltan, mchung
line wrap: on
line diff
--- a/src/hotspot/share/classfile/classFileParser.cpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/classfile/classFileParser.cpp Wed Nov 14 04:44:18 2018 -0500 @@ -5512,6 +5512,7 @@ InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook, InstanceKlass* dynamic_nest_host, + Handle classData, TRAPS) { if (_klass != NULL) { return _klass; @@ -5520,7 +5521,7 @@ InstanceKlass* const ik = InstanceKlass::allocate_instance_klass(*this, CHECK_NULL); - fill_instance_klass(ik, changed_by_loadhook, dynamic_nest_host, CHECK_NULL); + fill_instance_klass(ik, changed_by_loadhook, dynamic_nest_host, classData, CHECK_NULL); assert(_klass == ik, "invariant"); @@ -5543,6 +5544,7 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loadhook, InstanceKlass* dynamic_nest_host, + Handle classData, TRAPS) { assert(ik != NULL, "invariant"); @@ -5701,6 +5703,7 @@ Handle(THREAD, _loader_data->class_loader()), module_handle, _protection_domain, + classData, CHECK); assert(_all_mirandas != NULL, "invariant"); @@ -6149,7 +6152,7 @@ if (_requested_name != NULL && _requested_name != _class_name && _is_nonfindable) { - _class_name = (Symbol*)_requested_name; + _class_name = (Symbol*)_requested_name; _class_name->increment_refcount(); cp->symbol_at_put(cp->klass_name_index_at(_this_class_index), _class_name); }
--- a/src/hotspot/share/classfile/classFileParser.hpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/classfile/classFileParser.hpp Wed Nov 14 04:44:18 2018 -0500 @@ -179,7 +179,9 @@ void fix_unsafe_anonymous_class_name(TRAPS); void fill_instance_klass(InstanceKlass* ik, bool cf_changed_in_CFLH, - InstanceKlass* dynamic_nest_host, TRAPS); + InstanceKlass* dynamic_nest_host, + Handle classData, TRAPS); + void set_klass(InstanceKlass* instance); void set_class_bad_constant_seen(short bad_constant); @@ -513,7 +515,7 @@ ~ClassFileParser(); - InstanceKlass* create_instance_klass(bool cf_changed_in_CFLH, InstanceKlass* dynamic_nest_host, TRAPS); + InstanceKlass* create_instance_klass(bool cf_changed_in_CFLH, InstanceKlass* dynamic_nest_host, Handle classData, TRAPS); const ClassFileStream* clone_stream() const;
--- a/src/hotspot/share/classfile/classLoader.cpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/classfile/classLoader.cpp Wed Nov 14 04:44:18 2018 -0500 @@ -1404,6 +1404,7 @@ false, // is_nonfindable false, // can_access_vm_annotations NULL, // dynamic_nest_host + Handle(), // classData THREAD); if (HAS_PENDING_EXCEPTION) { if (DumpSharedSpaces) {
--- a/src/hotspot/share/classfile/classLoaderExt.cpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/classfile/classLoaderExt.cpp Wed Nov 14 04:44:18 2018 -0500 @@ -300,6 +300,7 @@ false, // is_nonfindable false, // can_access_vm_annotations NULL, // dynamic_nest_host + Handle(), // classData THREAD); if (HAS_PENDING_EXCEPTION) {
--- a/src/hotspot/share/classfile/javaClasses.cpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/classfile/javaClasses.cpp Wed Nov 14 04:44:18 2018 -0500 @@ -799,12 +799,13 @@ k->clear_has_raw_archived_mirror(); } } - create_mirror(k, Handle(), Handle(), Handle(), CHECK); + create_mirror(k, Handle(), Handle(), Handle(), Handle(), CHECK); } void java_lang_Class::initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, + Handle classData, TRAPS) { // Allocate a simple java object for a lock. // This needs to be a java object because during class initialization @@ -817,6 +818,9 @@ // Initialize static fields InstanceKlass::cast(k)->do_local_static_fields(&initialize_static_field, mirror, CHECK); + + // Set classData + set_class_data(mirror(), classData()); } // Set the java.lang.Module module field in the java_lang_Class mirror @@ -870,7 +874,8 @@ } void java_lang_Class::create_mirror(Klass* k, Handle class_loader, - Handle module, Handle protection_domain, TRAPS) { + Handle module, Handle protection_domain, + Handle classData, TRAPS) { assert(k != NULL, "Use create_basic_type_mirror for primitive types"); assert(k->java_mirror() == NULL, "should only assign mirror once"); @@ -917,7 +922,7 @@ } else { assert(k->is_instance_klass(), "Must be"); - initialize_mirror_fields(k, mirror, protection_domain, THREAD); + initialize_mirror_fields(k, mirror, protection_domain, classData, THREAD); if (HAS_PENDING_EXCEPTION) { // If any of the fields throws an exception like OOM remove the klass field // from the mirror so GC doesn't follow it after the klass has been deallocated. @@ -1322,6 +1327,15 @@ java_class->obj_field_put(_signers_offset, (oop)signers); } +oop java_lang_Class::class_data(oop java_class) { + assert(_classData_offset != 0, "must be set"); + return java_class->obj_field(_classData_offset); +} +void java_lang_Class::set_class_data(oop java_class, oop class_data) { + assert(_classData_offset != 0, "must be set"); + java_class->obj_field_put(_classData_offset, class_data); +} + void java_lang_Class::set_class_loader(oop java_class, oop loader) { // jdk7 runs Queens in bootstrapping and jdk8-9 has no coordinated pushes yet. @@ -3992,6 +4006,7 @@ 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<Klass*>* java_lang_Class::_fixup_mirror_list = NULL; GrowableArray<Klass*>* java_lang_Class::_fixup_module_field_list = NULL; int java_lang_Throwable::backtrace_offset;
--- a/src/hotspot/share/classfile/javaClasses.hpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/classfile/javaClasses.hpp Wed Nov 14 04:44:18 2018 -0500 @@ -219,7 +219,8 @@ macro(java_lang_Class, oop_size, int_signature, false) \ macro(java_lang_Class, static_oop_field_count, int_signature, false) \ macro(java_lang_Class, protection_domain, object_signature, false) \ - macro(java_lang_Class, signers, object_signature, false) + macro(java_lang_Class, signers, object_signature, false) \ + macro(java_lang_Class, classData, object_signature, false) class java_lang_Class : AllStatic { friend class VMStructs; @@ -240,6 +241,7 @@ static int _class_loader_offset; static int _module_offset; static int _component_mirror_offset; + static int _classData_offset; static bool offsets_computed; static int classRedefinedCount_offset; @@ -251,7 +253,8 @@ static void set_protection_domain(oop java_class, oop protection_domain); static void set_class_loader(oop java_class, oop class_loader); static void set_component_mirror(oop java_class, oop comp_mirror); - static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, TRAPS); + static void initialize_mirror_fields(Klass* k, Handle mirror, Handle protection_domain, + Handle classData, TRAPS); static void set_mirror_module_field(Klass* K, Handle mirror, Handle module, TRAPS); public: static void allocate_fixup_lists(); @@ -259,7 +262,7 @@ // Instance creation static void create_mirror(Klass* k, Handle class_loader, Handle module, - Handle protection_domain, TRAPS); + Handle protection_domain, Handle classData, TRAPS); static void fixup_mirror(Klass* k, TRAPS); static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS); @@ -305,6 +308,8 @@ static oop component_mirror(oop java_class); static objArrayOop signers(oop java_class); static void set_signers(oop java_class, objArrayOop signers); + static oop class_data(oop java_class); + static void set_class_data(oop java_class, oop classData); static oop class_loader(oop java_class); static void set_module(oop java_class, oop module);
--- a/src/hotspot/share/classfile/klassFactory.cpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/classfile/klassFactory.cpp Wed Nov 14 04:44:18 2018 -0500 @@ -107,6 +107,7 @@ CHECK_NULL); InstanceKlass* new_ik = parser.create_instance_klass(true, // changed_by_loadhook NULL, // dynamic_nest_host + Handle(), // classData CHECK_NULL); if (cached_class_file != NULL) { @@ -192,6 +193,7 @@ const bool is_nonfindable, const bool can_access_vm_annotations, InstanceKlass* dynamic_nest_host, + Handle classData, TRAPS) { assert(stream != NULL, "invariant"); assert(loader_data != NULL, "invariant"); @@ -228,8 +230,8 @@ ClassFileParser::BROADCAST, // publicity level CHECK_NULL); - InstanceKlass* result = parser.create_instance_klass(old_stream != stream, dynamic_nest_host, CHECK_NULL); - assert(result == parser.create_instance_klass(old_stream != stream, NULL, THREAD), "invariant"); + InstanceKlass* result = parser.create_instance_klass(old_stream != stream, dynamic_nest_host, classData, CHECK_NULL); + assert(result == parser.create_instance_klass(old_stream != stream, NULL, classData, THREAD), "invariant"); if (result == NULL) { return NULL;
--- a/src/hotspot/share/classfile/klassFactory.hpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/classfile/klassFactory.hpp Wed Nov 14 04:44:18 2018 -0500 @@ -77,6 +77,7 @@ const bool is_nonfindable, const bool can_access_vm_annotations, InstanceKlass* dynamic_nest_host, + Handle classData, TRAPS); public: static InstanceKlass* check_shared_class_file_load_hook(
--- a/src/hotspot/share/classfile/systemDictionary.cpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/classfile/systemDictionary.cpp Wed Nov 14 04:44:18 2018 -0500 @@ -999,6 +999,7 @@ const bool is_weaknonfindable, const bool can_access_vm_annotations, InstanceKlass* dynamic_nest_host, + Handle classData, TRAPS) { EventClassLoad class_load_start_event; @@ -1041,6 +1042,7 @@ is_nonfindable, can_access_vm_annotations, dynamic_nest_host, + classData, CHECK_NULL); if ((is_nonfindable || (unsafe_anonymous_host != NULL)) && k != NULL) { @@ -1070,6 +1072,7 @@ } // Initialize it now, since nobody else will. + // FIXME: why must we eager initialize? It should be initialized upon use. k->eager_initialize(CHECK_NULL); // notify jvmti @@ -1146,6 +1149,7 @@ false, // is_nonfindable false, // can_access_vm_annotations dynamic_nest_host, + Handle(), // classData CHECK_NULL); }
--- a/src/hotspot/share/classfile/systemDictionary.hpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/classfile/systemDictionary.hpp Wed Nov 14 04:44:18 2018 -0500 @@ -289,6 +289,7 @@ false, // is_weaknonfindable false, // can_access_vm_annotations dynamic_nest_host, + Handle(), // classData THREAD); } static InstanceKlass* parse_stream(Symbol* class_name, @@ -301,6 +302,7 @@ const bool is_weaknonfindable, const bool can_access_vm_annotations, InstanceKlass* dynamic_nest_host, + Handle classData, TRAPS); // Resolve from stream (called by jni_DefineClass and JVM_DefineClass)
--- a/src/hotspot/share/classfile/vmSymbols.hpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/classfile/vmSymbols.hpp Wed Nov 14 04:44:18 2018 -0500 @@ -421,6 +421,7 @@ template(static_oop_field_count_name, "static_oop_field_count") \ template(protection_domain_name, "protection_domain") \ template(signers_name, "signers_name") \ + template(classData_name, "classData_name") \ template(loader_data_name, "loader_data") \ template(vmdependencies_name, "vmdependencies") \ template(loader_name, "loader") \
--- a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp Wed Nov 14 04:44:18 2018 -0500 @@ -1474,7 +1474,8 @@ CLEAR_PENDING_EXCEPTION; return NULL; } - InstanceKlass* const new_ik = new_parser.create_instance_klass(false, NULL, THREAD); + InstanceKlass* const new_ik = new_parser.create_instance_klass(false, NULL, + Handle(), THREAD); if (HAS_PENDING_EXCEPTION) { log_pending_exception(PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION;
--- a/src/hotspot/share/oops/arrayKlass.cpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/oops/arrayKlass.cpp Wed Nov 14 04:44:18 2018 -0500 @@ -109,7 +109,7 @@ assert((module_entry != NULL) || ((module_entry == NULL) && !ModuleEntryTable::javabase_defined()), "module entry not available post " JAVA_BASE_NAME " definition"); oop module = (module_entry != NULL) ? module_entry->module() : (oop)NULL; - java_lang_Class::create_mirror(k, Handle(THREAD, k->class_loader()), Handle(THREAD, module), Handle(), CHECK); + java_lang_Class::create_mirror(k, Handle(THREAD, k->class_loader()), Handle(THREAD, module), Handle(), Handle(), CHECK); } GrowableArray<Klass*>* ArrayKlass::compute_secondary_supers(int num_extra_slots,
--- a/src/hotspot/share/oops/klass.cpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/oops/klass.cpp Wed Nov 14 04:44:18 2018 -0500 @@ -562,7 +562,7 @@ // gotten an OOM later but keep the mirror if it was created. if (java_mirror() == NULL) { log_trace(cds, mirror)("Recreate mirror for %s", external_name()); - java_lang_Class::create_mirror(this, loader, module_handle, protection_domain, CHECK); + java_lang_Class::create_mirror(this, loader, module_handle, protection_domain, Handle(), CHECK); } }
--- a/src/hotspot/share/prims/jvm.cpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/prims/jvm.cpp Wed Nov 14 04:44:18 2018 -0500 @@ -1039,6 +1039,7 @@ trace_class_resolution(k); } } else { //nonfindable + Handle classData_h(THREAD, JNIHandles::resolve(classData)); k = SystemDictionary::parse_stream(class_name, class_loader, protection_domain, @@ -1049,6 +1050,7 @@ is_weak, vm_annotations, host_class, + classData_h, CHECK_NULL); if (k == NULL) { THROW_MSG_0(vmSymbols::java_lang_Error(), "Failure to define a nonfindable class");
--- a/src/hotspot/share/prims/methodHandles.cpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/prims/methodHandles.cpp Wed Nov 14 04:44:18 2018 -0500 @@ -1517,6 +1517,17 @@ } JVM_END +/* + * Return the class data from the injected classData field of the given lookup class + */ +JVM_ENTRY(jobject, MHN_classData(JNIEnv *env, jobject igcls, jclass lookup)) + if (lookup == NULL) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Lookup class is null"); + } + oop mirror = JNIHandles::resolve_non_null(lookup); + return (jobject) JNIHandles::make_local(env, java_lang_Class::class_data(mirror)); +JVM_END + /** * Throws a java/lang/UnsupportedOperationException unconditionally. * This is required by the specification of MethodHandle.invoke if @@ -1575,7 +1586,8 @@ {CC "clearCallSiteContext", CC "(" CTX ")V", FN_PTR(MHN_clearCallSiteContext)}, {CC "staticFieldOffset", CC "(" MEM ")J", FN_PTR(MHN_staticFieldOffset)}, {CC "staticFieldBase", CC "(" MEM ")" OBJ, FN_PTR(MHN_staticFieldBase)}, - {CC "getMemberVMInfo", CC "(" MEM ")" OBJ, FN_PTR(MHN_getMemberVMInfo)} + {CC "getMemberVMInfo", CC "(" MEM ")" OBJ, FN_PTR(MHN_getMemberVMInfo)}, + {CC "classData", CC "(" CLS ")" OBJ, FN_PTR(MHN_classData)} }; static JNINativeMethod MH_methods[] = {
--- a/src/hotspot/share/prims/unsafe.cpp Thu Nov 08 16:23:52 2018 -0500 +++ b/src/hotspot/share/prims/unsafe.cpp Wed Nov 14 04:44:18 2018 -0500 @@ -823,6 +823,7 @@ false, // is_weak false, // can_access_vm_annotations NULL, // dynamic_nest_host + Handle(), // classData CHECK_NULL); if (anonk == NULL) { return NULL;
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java Thu Nov 08 16:23:52 2018 -0500 +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java Wed Nov 14 04:44:18 2018 -0500 @@ -72,6 +72,9 @@ boolean resolve, Object ifNotAvailable); + /// ClassData support + static native Object classData(Class<?> lookupClass); + /** Represents a context to track nmethod dependencies on CallSite instance target. */ static class CallSiteContext implements Runnable { //@Injected JVM_nmethodBucket* vmdependencies;
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Thu Nov 08 16:23:52 2018 -0500 +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Wed Nov 14 04:44:18 2018 -0500 @@ -1212,7 +1212,7 @@ } // should we allow clearing? getAndClearClassData - return CLASS_DATA_MAP.get(lookupClass); + return MethodHandleNatives.classData(lookupClass); } // package-private @@ -1265,11 +1265,6 @@ assert clazz.getClassLoader() == lookupClass.getClassLoader() && clazz.getPackageName().equals(lookupClass.getPackageName()); - // ## TBD what if multiple threads defining this same class?? - // may need VM to inject the classData in a Class itself at define class time - if (classData != null) { - CLASS_DATA_MAP.putIfAbsent(clazz, classData); - } return clazz; } @@ -1286,9 +1281,6 @@ // cached protection domain private volatile ProtectionDomain cachedProtectionDomain; - // don't see the need to use ClassValue - private static final WeakHashMap<Class<?>, Object> CLASS_DATA_MAP = new WeakHashMap<>(); - // Make sure outer class is initialized first. static { IMPL_NAMES.getClass(); }