< prev index next >

src/hotspot/share/classfile/systemDictionaryShared.cpp

Print this page

        

*** 34,54 **** #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/systemDictionaryShared.hpp" #include "classfile/verificationType.hpp" #include "classfile/vmSymbols.hpp" #include "logging/log.hpp" #include "memory/allocation.hpp" #include "memory/archiveUtils.hpp" #include "memory/filemap.hpp" #include "memory/heapShared.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" - #include "memory/dynamicArchive.hpp" #include "oops/instanceKlass.hpp" #include "oops/klass.inline.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayOop.inline.hpp" --- 34,55 ---- #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/systemDictionaryShared.hpp" #include "classfile/verificationType.hpp" #include "classfile/vmSymbols.hpp" + #include "jfr/jfrEvents.hpp" #include "logging/log.hpp" #include "memory/allocation.hpp" #include "memory/archiveUtils.hpp" + #include "memory/dynamicArchive.hpp" #include "memory/filemap.hpp" #include "memory/heapShared.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/instanceKlass.hpp" #include "oops/klass.inline.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayOop.inline.hpp"
*** 99,108 **** --- 100,110 ---- int _id; int _clsfile_size; int _clsfile_crc32; GrowableArray<DTVerifierConstraint>* _verifier_constraints; GrowableArray<char>* _verifier_constraint_flags; + bool _is_archived_lambda_proxy; GrowableArray<DTLoaderConstraint>* _loader_constraints; DumpTimeSharedClassInfo() { _klass = NULL; _failed_verification = false;
*** 110,119 **** --- 112,122 ---- _clsfile_size = -1; _clsfile_crc32 = -1; _excluded = false; _verifier_constraints = NULL; _verifier_constraint_flags = NULL; + _is_archived_lambda_proxy = false; _loader_constraints = NULL; } void add_verification_constraint(InstanceKlass* k, Symbol* name, Symbol* from_name, bool from_field_is_protected, bool from_is_array, bool from_is_object);
*** 240,249 **** --- 243,404 ---- return _unregistered_count; } } }; + class LambdaProxyClassKey { + template <typename T> static void original_to_target(T& field) { + if (field != NULL) { + field = DynamicArchive::original_to_target(field); + ArchivePtrMarker::mark_pointer(&field); + } + } + + InstanceKlass* _caller_ik; + Symbol* _invoked_name; + Symbol* _invoked_type; + Symbol* _method_type; + Method* _member_method; + Symbol* _instantiated_method_type; + + public: + LambdaProxyClassKey(InstanceKlass* caller_ik, + Symbol* invoked_name, + Symbol* invoked_type, + Symbol* method_type, + Method* member_method, + Symbol* instantiated_method_type) : + _caller_ik(caller_ik), + _invoked_name(invoked_name), + _invoked_type(invoked_type), + _method_type(method_type), + _member_method(member_method), + _instantiated_method_type(instantiated_method_type) {} + + void original_to_target() { + original_to_target(_caller_ik); + original_to_target(_instantiated_method_type); + original_to_target(_invoked_name); + original_to_target(_invoked_type); + original_to_target(_member_method); + original_to_target(_method_type); + } + + bool equals(LambdaProxyClassKey const& other) const { + return _caller_ik == other._caller_ik && + _invoked_name == other._invoked_name && + _invoked_type == other._invoked_type && + _method_type == other._method_type && + _member_method == other._member_method && + _instantiated_method_type == other._instantiated_method_type; + } + + unsigned int hash() const { + return SystemDictionaryShared::hash_for_shared_dictionary(_caller_ik) + + SystemDictionaryShared::hash_for_shared_dictionary(_invoked_name) + + SystemDictionaryShared::hash_for_shared_dictionary(_invoked_type) + + SystemDictionaryShared::hash_for_shared_dictionary(_method_type) + + SystemDictionaryShared::hash_for_shared_dictionary(_instantiated_method_type); + } + + unsigned int dumptime_hash() const { + return primitive_hash<InstanceKlass*>(_caller_ik) + + primitive_hash<Symbol*>(_invoked_name) + + primitive_hash<Symbol*>(_invoked_type) + + primitive_hash<Symbol*>(_method_type) + + primitive_hash<Symbol*>(_instantiated_method_type); + } + + static inline unsigned int DUMPTIME_HASH(LambdaProxyClassKey const& key) { + return (key.dumptime_hash()); + } + + static inline bool DUMPTIME_EQUALS( + LambdaProxyClassKey const& k1, LambdaProxyClassKey const& k2) { + return (k1.equals(k2)); + } + }; + + + class DumpTimeLambdaProxyClassInfo { + public: + GrowableArray<InstanceKlass*>* _proxy_klass; + DumpTimeLambdaProxyClassInfo() : _proxy_klass(NULL) {} + void add_proxy_klass(InstanceKlass* proxy_klass) { + if (_proxy_klass == NULL) { + _proxy_klass = new (ResourceObj::C_HEAP, mtInternal)GrowableArray<InstanceKlass*>(5, true); + } + assert(_proxy_klass != NULL, "sanity"); + _proxy_klass->append(proxy_klass); + } + }; + + class RunTimeLambdaProxyClassInfo { + LambdaProxyClassKey _key; + InstanceKlass* _proxy_klass; + public: + RunTimeLambdaProxyClassInfo(LambdaProxyClassKey key, InstanceKlass* proxy_klass) : + _key(key), _proxy_klass(proxy_klass) {} + + InstanceKlass* proxy_klass() const { return _proxy_klass; } + + // Used by LambdaProxyClassDictionary to implement OffsetCompactHashtable::EQUALS + static inline bool EQUALS( + const RunTimeLambdaProxyClassInfo* value, LambdaProxyClassKey* key, int len_unused) { + return (value->_key.equals(*key)); + } + void init(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) { + _key = key; + _key.original_to_target(); + _proxy_klass = DynamicArchive::original_to_target(info._proxy_klass->at(0)); + ArchivePtrMarker::mark_pointer(&_proxy_klass); + } + + unsigned int hash() const { + return _key.hash(); + } + }; + + class LambdaProxyClassDictionary : public OffsetCompactHashtable< + LambdaProxyClassKey*, + const RunTimeLambdaProxyClassInfo*, + RunTimeLambdaProxyClassInfo::EQUALS> {}; + + LambdaProxyClassDictionary _lambda_proxy_class_dictionary; + + class DumpTimeLambdaProxyClassDictionary + : public ResourceHashtable<LambdaProxyClassKey, + DumpTimeLambdaProxyClassInfo, + LambdaProxyClassKey::DUMPTIME_HASH, + LambdaProxyClassKey::DUMPTIME_EQUALS, + 137, // prime number + ResourceObj::C_HEAP> { + public: + int _count; + }; + + DumpTimeLambdaProxyClassDictionary* _dumptime_lambda_proxy_class_dictionary = NULL; + + static void add_to_dump_time_lambda_proxy_class_dictionary(LambdaProxyClassKey key, + InstanceKlass* proxy_klass) { + if (_dumptime_lambda_proxy_class_dictionary == NULL) { + _dumptime_lambda_proxy_class_dictionary = + new (ResourceObj::C_HEAP, mtClass)DumpTimeLambdaProxyClassDictionary(); + } + DumpTimeLambdaProxyClassInfo* lambda_info = _dumptime_lambda_proxy_class_dictionary->get(key); + if (lambda_info == NULL) { + DumpTimeLambdaProxyClassInfo info; + info.add_proxy_klass(proxy_klass); + _dumptime_lambda_proxy_class_dictionary->put(key, info); + //lambda_info = _dumptime_lambda_proxy_class_dictionary->get(key); + //assert(lambda_info->_proxy_klass == proxy_klass, "must be"); // debug only -- remove + ++_dumptime_lambda_proxy_class_dictionary->_count; + } else { + lambda_info->add_proxy_klass(proxy_klass); + } + } + class RunTimeSharedClassInfo { public: struct CrcInfo { int _clsfile_size; int _clsfile_crc32;
*** 270,279 **** --- 425,435 ---- InstanceKlass* _klass; int _num_verifier_constraints; int _num_loader_constraints; // optional CrcInfo _crc; (only for UNREGISTERED classes) + // optional InstanceKlass* _nest_host // optional RTLoaderConstraint _loader_constraint_types[_num_loader_constraints] // optional RTVerifierConstraint _verifier_constraints[_num_verifier_constraints] // optional char _verifier_constraint_flags[_num_verifier_constraints] private:
*** 294,321 **** return sizeof(char) * num_verifier_constraints; } static size_t loader_constraints_size(int num_loader_constraints) { return sizeof(RTLoaderConstraint) * num_loader_constraints; } public: static size_t byte_size(InstanceKlass* klass, int num_verifier_constraints, int num_loader_constraints) { return header_size_size() + crc_size(klass) + loader_constraints_size(num_loader_constraints) + verifier_constraints_size(num_verifier_constraints) + verifier_constraint_flags_size(num_verifier_constraints); } private: size_t crc_offset() const { return header_size_size(); } ! size_t loader_constraints_offset() const { return crc_offset() + crc_size(_klass); } size_t verifier_constraints_offset() const { return loader_constraints_offset() + loader_constraints_size(_num_loader_constraints); } size_t verifier_constraint_flags_offset() const { return verifier_constraints_offset() + verifier_constraints_size(_num_verifier_constraints); --- 450,489 ---- return sizeof(char) * num_verifier_constraints; } static size_t loader_constraints_size(int num_loader_constraints) { return sizeof(RTLoaderConstraint) * num_loader_constraints; } + static size_t nest_host_size(InstanceKlass* klass) { + if (klass->is_hidden()) { + return sizeof(InstanceKlass*); + } else { + return 0; + } + } public: static size_t byte_size(InstanceKlass* klass, int num_verifier_constraints, int num_loader_constraints) { return header_size_size() + crc_size(klass) + + nest_host_size(klass) + loader_constraints_size(num_loader_constraints) + verifier_constraints_size(num_verifier_constraints) + verifier_constraint_flags_size(num_verifier_constraints); } private: size_t crc_offset() const { return header_size_size(); } ! size_t nest_host_offset() const { return crc_offset() + crc_size(_klass); } + + size_t loader_constraints_offset() const { + return nest_host_offset() + nest_host_size(_klass); + } size_t verifier_constraints_offset() const { return loader_constraints_offset() + loader_constraints_size(_num_loader_constraints); } size_t verifier_constraint_flags_offset() const { return verifier_constraints_offset() + verifier_constraints_size(_num_verifier_constraints);
*** 346,355 **** --- 514,535 ---- char* verifier_constraint_flags() { assert(_num_verifier_constraints > 0, "sanity"); return (char*)(address(this) + verifier_constraint_flags_offset()); } + InstanceKlass** nest_host_addr() { + assert(_klass->is_hidden(), "sanity"); + return (InstanceKlass**)(address(this) + nest_host_offset()); + } + InstanceKlass* nest_host() { + return *nest_host_addr(); + } + void set_nest_host(InstanceKlass* k) { + *nest_host_addr() = k; + ArchivePtrMarker::mark_pointer((address*)nest_host_addr()); + } + RTLoaderConstraint* loader_constraints() { assert(_num_loader_constraints > 0, "sanity"); return (RTLoaderConstraint*)(address(this) + loader_constraints_offset()); }
*** 394,403 **** --- 574,590 ---- ld_constraints[i]._loader_type1 = info._loader_constraints->at(i)._loader_type1; ld_constraints[i]._loader_type2 = info._loader_constraints->at(i)._loader_type2; } } if (DynamicDumpSharedSpaces) { + if (_klass->is_hidden()) { + Thread* THREAD = Thread::current(); + InstanceKlass* n_h = _klass->nest_host(THREAD); + n_h = DynamicArchive::original_to_target(n_h); + set_nest_host(n_h); + ArchivePtrMarker::mark_pointer(&n_h); + } _klass = DynamicArchive::original_to_target(info._klass); } ArchivePtrMarker::mark_pointer(&_klass); }
*** 424,433 **** --- 611,621 ---- return &((RunTimeSharedClassInfo**)klass)[-1]; } public: static RunTimeSharedClassInfo* get_for(InstanceKlass* klass) { + assert(klass->is_shared(), "don't call for non-shared class"); return *info_pointer_addr(klass); } static void set_for(InstanceKlass* klass, RunTimeSharedClassInfo* record) { if (DynamicDumpSharedSpaces) { klass = DynamicArchive::original_to_buffer(klass);
*** 1149,1177 **** k = k->java_super(); } return false; } void SystemDictionaryShared::warn_excluded(InstanceKlass* k, const char* reason) { ResourceMark rm; log_warning(cds)("Skipping %s: %s", k->name()->as_C_string(), reason); } bool SystemDictionaryShared::should_be_excluded(InstanceKlass* k) { ! if (k->is_hidden() || k->is_unsafe_anonymous()) { ! warn_excluded(k, "Hidden or Unsafe anonymous class"); ! return true; // hidden and unsafe anonymous classes are not archived, skip } if (k->is_in_error_state()) { warn_excluded(k, "In error state"); return true; } if (k->has_been_redefined()) { warn_excluded(k, "Has been redefined"); return true; } ! if (k->shared_classpath_index() < 0 && is_builtin(k)) { // These are classes loaded from unsupported locations (such as those loaded by JVMTI native // agent during dump time). warn_excluded(k, "Unsupported location"); return true; } --- 1337,1392 ---- k = k->java_super(); } return false; } + bool SystemDictionaryShared::is_registered_lambda_proxy_class(InstanceKlass* ik) { + DumpTimeSharedClassInfo* info = _dumptime_table->get(ik); + return (info != NULL) ? info->_is_archived_lambda_proxy && !ik->is_non_strong_hidden() : false; + } + + bool SystemDictionaryShared::is_in_shared_lambda_proxy_table(InstanceKlass* ik) { + assert(!DumpSharedSpaces && UseSharedSpaces, "called at run time with CDS enabled only"); + RunTimeSharedClassInfo* record = RunTimeSharedClassInfo::get_for(ik); + if (record != NULL && record->nest_host() != NULL) { + return true; + } else { + return false; + } + } + + bool SystemDictionaryShared::is_hidden_lambda_proxy(InstanceKlass* ik) { + assert(ik->is_shared(), "applicable to only a shared class"); + if (ik->is_hidden()) { + assert(is_in_shared_lambda_proxy_table(ik), "we don't archive other hidden classes"); + return true; + } else { + return false; + } + } + void SystemDictionaryShared::warn_excluded(InstanceKlass* k, const char* reason) { ResourceMark rm; log_warning(cds)("Skipping %s: %s", k->name()->as_C_string(), reason); } bool SystemDictionaryShared::should_be_excluded(InstanceKlass* k) { ! ! if (k->is_unsafe_anonymous()) { ! warn_excluded(k, "Unsafe anonymous class"); ! return true; // unsafe anonymous classes are not archived, skip } + if (k->is_in_error_state()) { warn_excluded(k, "In error state"); return true; } if (k->has_been_redefined()) { warn_excluded(k, "Has been redefined"); return true; } ! if (!k->is_hidden() && k->shared_classpath_index() < 0 && is_builtin(k)) { // These are classes loaded from unsupported locations (such as those loaded by JVMTI native // agent during dump time). warn_excluded(k, "Unsupported location"); return true; }
*** 1220,1229 **** --- 1435,1449 ---- ResourceMark rm; log_warning(cds)("Skipping %s: super class %s is excluded", k->name()->as_C_string(), super->name()->as_C_string()); return true; } + if (k->is_hidden() && !is_registered_lambda_proxy_class(k)) { + warn_excluded(k, "Hidden class"); + return true; + } + Array<InstanceKlass*>* interfaces = k->local_interfaces(); int len = interfaces->length(); for (int i = 0; i < len; i++) { InstanceKlass* intf = interfaces->at(i); if (should_be_excluded(intf)) {
*** 1242,1253 **** --- 1462,1477 ---- DumpTimeSharedClassInfo* info = _dumptime_table->get(k); assert(_no_class_loading_should_happen, "class loading must be disabled"); guarantee(info != NULL, "Class %s must be entered into _dumptime_table", name); guarantee(!info->is_excluded(), "Should not attempt to archive excluded class %s", name); if (is_builtin(k)) { + if (k->is_hidden()) { + assert(is_registered_lambda_proxy_class(k), "unexpected hidden class %s", name); + } guarantee(!k->is_shared_unregistered_class(), "Class loader type must be set for BUILTIN class %s", name); + } else { guarantee(k->is_shared_unregistered_class(), "Class loader type must not be set for UNREGISTERED class %s", name); } }
*** 1359,1372 **** c |= from_is_object ? SystemDictionaryShared::FROM_IS_OBJECT : 0; vcflags_array->append(c); if (log_is_enabled(Trace, cds, verification)) { ResourceMark rm; ! log_trace(cds, verification)("add_verification_constraint: %s: %s must be subclass of %s [0x%x]", k->external_name(), from_name->as_klass_external_name(), ! name->as_klass_external_name(), c); } } static char get_loader_type_by(oop loader) { assert(SystemDictionary::is_builtin_class_loader(loader), "Must be built-in loader"); if (SystemDictionary::is_boot_class_loader(loader)) { --- 1583,1720 ---- c |= from_is_object ? SystemDictionaryShared::FROM_IS_OBJECT : 0; vcflags_array->append(c); if (log_is_enabled(Trace, cds, verification)) { ResourceMark rm; ! log_trace(cds, verification)("add_verification_constraint: %s: %s must be subclass of %s [0x%x] array len %d flags len %d", k->external_name(), from_name->as_klass_external_name(), ! name->as_klass_external_name(), c, vc_array->length(), vcflags_array->length()); ! } ! } ! ! void SystemDictionaryShared::add_lambda_proxy_class(InstanceKlass* caller_ik, ! InstanceKlass* lambda_ik, ! Symbol* invoked_name, ! Symbol* invoked_type, ! Symbol* method_type, ! Method* member_method, ! Symbol* instantiated_method_type) { ! ! assert(caller_ik->class_loader() == lambda_ik->class_loader(), "mismatched class loader"); ! assert(caller_ik->class_loader_data() == lambda_ik->class_loader_data(), "mismatched class loader data"); ! ! MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag); ! ! lambda_ik->assign_class_loader_type(); ! ! DumpTimeSharedClassInfo* info = _dumptime_table->get(lambda_ik); ! if (info != NULL) { ! // Set _is_archived_lambda_proxy in DumpTimeSharedClassInfo so that the lambda_ik ! // won't be excluded during dumping of shared archive. See ExcludeDumpTimeSharedClasses. ! info->_is_archived_lambda_proxy = true; ! } ! ! LambdaProxyClassKey key(caller_ik, ! invoked_name, ! invoked_type, ! method_type, ! member_method, ! instantiated_method_type); ! add_to_dump_time_lambda_proxy_class_dictionary(key, lambda_ik); ! } ! ! InstanceKlass* SystemDictionaryShared::get_shared_lambda_proxy_class(InstanceKlass* caller_ik, ! Symbol* invoked_name, ! Symbol* invoked_type, ! Symbol* method_type, ! Method* member_method, ! Symbol* instantiated_method_type) { ! MutexLocker ml(CDSLambda_lock, Mutex::_no_safepoint_check_flag); ! LambdaProxyClassKey key(caller_ik, invoked_name, invoked_type, ! method_type, member_method, instantiated_method_type); ! const RunTimeLambdaProxyClassInfo* info = _lambda_proxy_class_dictionary.lookup(&key, key.hash(), 0); ! InstanceKlass* proxy_klass = NULL; ! if (info != NULL) { ! InstanceKlass* curr_klass = info->proxy_klass(); ! InstanceKlass* prev_klass = curr_klass; ! if (curr_klass->lambda_proxy_is_available()) { ! while (curr_klass->next_link() != NULL) { ! prev_klass = curr_klass; ! curr_klass = InstanceKlass::cast(curr_klass->next_link()); ! } ! assert(curr_klass->is_hidden(), "must be"); ! assert(curr_klass->lambda_proxy_is_available(), "must be"); ! ! prev_klass->set_next_link(NULL); ! proxy_klass = curr_klass; ! proxy_klass->clear_lambda_proxy_is_available(); ! if (log_is_enabled(Debug, cds)) { ! ResourceMark rm; ! log_debug(cds)("Loaded lambda proxy: %s", proxy_klass->external_name()); ! } ! } else { ! if (log_is_enabled(Debug, cds)) { ! ResourceMark rm; ! log_debug(cds)("Used all archived lambda proxy classes for: %s %s%s", ! caller_ik->external_name(), invoked_name->as_C_string(), invoked_type->as_C_string()); ! } ! } ! } ! return proxy_klass; ! } ! ! InstanceKlass* SystemDictionaryShared::get_shared_nest_host(InstanceKlass* lambda_ik) { ! assert(!DumpSharedSpaces && UseSharedSpaces, "called at run time with CDS enabled only"); ! RunTimeSharedClassInfo* record = RunTimeSharedClassInfo::get_for(lambda_ik); ! return record->nest_host(); ! } ! ! InstanceKlass* SystemDictionaryShared::prepare_shared_lambda_proxy_class(InstanceKlass* lambda_ik, ! InstanceKlass* caller_ik, ! bool initialize, TRAPS) { ! Handle class_loader(THREAD, caller_ik->class_loader()); ! Handle protection_domain; ! PackageEntry* pkg_entry = get_package_entry_from_class_name(class_loader, caller_ik->name()); ! if (caller_ik->class_loader() != NULL) { ! protection_domain = SystemDictionaryShared::init_security_info(class_loader, caller_ik, pkg_entry, CHECK_NULL); } + + InstanceKlass* shared_nest_host = get_shared_nest_host(lambda_ik); + assert(shared_nest_host != NULL, "unexpected NULL _nest_host"); + + InstanceKlass* loaded_lambda = + SystemDictionary::load_shared_lambda_proxy_class(lambda_ik, class_loader, protection_domain, pkg_entry, CHECK_NULL); + + // Ensures the nest host is the same as the lambda proxy's + // nest host recorded at dump time. + InstanceKlass* nest_host = caller_ik->nest_host(THREAD); + assert(nest_host == shared_nest_host, "mismatched nest host"); + + EventClassLoad class_load_start_event; + { + MutexLocker mu_r(THREAD, Compile_lock); + + // Add to class hierarchy, initialize vtables, and do possible + // deoptimizations. + SystemDictionary::add_to_hierarchy(loaded_lambda, CHECK_NULL); // No exception, but can block + // But, do not add to dictionary. + } + loaded_lambda->link_class(CHECK_NULL); + // notify jvmti + if (JvmtiExport::should_post_class_load()) { + assert(THREAD->is_Java_thread(), "thread->is_Java_thread()"); + JvmtiExport::post_class_load((JavaThread *) THREAD, loaded_lambda); + } + if (class_load_start_event.should_commit()) { + SystemDictionary::post_class_load_event(&class_load_start_event, loaded_lambda, ClassLoaderData::class_loader_data(class_loader())); + } + + if (initialize) { + loaded_lambda->initialize(CHECK_NULL); + } + + return loaded_lambda; } static char get_loader_type_by(oop loader) { assert(SystemDictionary::is_builtin_class_loader(loader), "Must be built-in loader"); if (SystemDictionary::is_boot_class_loader(loader)) {
*** 1595,1609 **** }; size_t SystemDictionaryShared::estimate_size_for_archive() { EstimateSizeForArchive est; _dumptime_table->iterate(&est); ! return est.total() + CompactHashtableWriter::estimate_size(_dumptime_table->count_of(true)) + CompactHashtableWriter::estimate_size(_dumptime_table->count_of(false)); } class CopySharedClassInfoToArchive : StackObj { CompactHashtableWriter* _writer; bool _is_builtin; public: CopySharedClassInfoToArchive(CompactHashtableWriter* writer, --- 1943,2013 ---- }; size_t SystemDictionaryShared::estimate_size_for_archive() { EstimateSizeForArchive est; _dumptime_table->iterate(&est); ! size_t total_size = est.total() + CompactHashtableWriter::estimate_size(_dumptime_table->count_of(true)) + CompactHashtableWriter::estimate_size(_dumptime_table->count_of(false)); + if (_dumptime_lambda_proxy_class_dictionary != NULL) { + total_size += + (sizeof(RunTimeLambdaProxyClassInfo) * _dumptime_lambda_proxy_class_dictionary->_count) + + CompactHashtableWriter::estimate_size(_dumptime_lambda_proxy_class_dictionary->_count); + } else { + total_size += CompactHashtableWriter::estimate_size(0); + } + return total_size; } + class CopyLambdaProxyClassInfoToArchive : StackObj { + CompactHashtableWriter* _writer; + public: + CopyLambdaProxyClassInfoToArchive(CompactHashtableWriter* writer) + : _writer(writer) {} + bool do_entry(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) { + if (SystemDictionaryShared::is_excluded_class(info._proxy_klass->at(0))) { + return true; + } + ResourceMark rm; + log_info(cds,dynamic)("Archiving hidden %s", info._proxy_klass->at(0)->external_name()); + size_t byte_size = sizeof(RunTimeLambdaProxyClassInfo); + RunTimeLambdaProxyClassInfo* runtime_info = + (RunTimeLambdaProxyClassInfo*)MetaspaceShared::read_only_space_alloc(byte_size); + runtime_info->init(key, info); + unsigned int hash = runtime_info->hash(); // Fields in runtime_info->_key already point to target space. + u4 delta = MetaspaceShared::object_delta_u4(DynamicArchive::buffer_to_target(runtime_info)); + _writer->add(hash, delta); + return true; + } + }; + + class AdjustLambdaProxyClassInfo : StackObj { + public: + AdjustLambdaProxyClassInfo() {} + bool do_entry(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) { + if (SystemDictionaryShared::is_excluded_class(info._proxy_klass->at(0))) { + return true; + } + int len = info._proxy_klass->length(); + if (len > 1) { + for (int i = 0; i < len-1; i++) { + InstanceKlass* ok0 = info._proxy_klass->at(i+0); // this is original klass + InstanceKlass* ok1 = info._proxy_klass->at(i+1); // this is original klass + InstanceKlass* bk0 = DynamicArchive::original_to_buffer(ok0); + InstanceKlass* bk1 = DynamicArchive::original_to_buffer(ok1); + assert(bk0->next_link() == 0, "must be called after Klass::remove_unshareable_info()"); + assert(bk1->next_link() == 0, "must be called after Klass::remove_unshareable_info()"); + bk0->set_next_link(bk1); + bk1->set_lambda_proxy_is_available(); + ArchivePtrMarker::mark_pointer(bk0->next_link_addr()); + } + } + DynamicArchive::original_to_buffer(info._proxy_klass->at(0))->set_lambda_proxy_is_available(); + return true; + } + }; + class CopySharedClassInfoToArchive : StackObj { CompactHashtableWriter* _writer; bool _is_builtin; public: CopySharedClassInfoToArchive(CompactHashtableWriter* writer,
*** 1628,1638 **** --- 2032,2046 ---- if (DynamicDumpSharedSpaces) { delta = MetaspaceShared::object_delta_u4(DynamicArchive::buffer_to_target(record)); } else { delta = MetaspaceShared::object_delta_u4(record); } + if (_is_builtin && info._klass->is_hidden()) { + // skip + } else { _writer->add(hash, delta); + } if (log_is_enabled(Trace, cds, hashtables)) { ResourceMark rm; log_trace(cds,hashtables)("%s dictionary: %s", (_is_builtin ? "builtin" : "unregistered"), info._klass->external_name()); }
*** 1641,1650 **** --- 2049,2067 ---- } return true; // keep on iterating } }; + void SystemDictionaryShared::write_lambda_proxy_class_dictionary(LambdaProxyClassDictionary *dictionary) { + CompactHashtableStats stats; + dictionary->reset(); + CompactHashtableWriter writer(_dumptime_lambda_proxy_class_dictionary->_count, &stats); + CopyLambdaProxyClassInfoToArchive copy(&writer); + _dumptime_lambda_proxy_class_dictionary->iterate(&copy); + writer.dump(dictionary, "lambda proxy class dictionary"); + } + void SystemDictionaryShared::write_dictionary(RunTimeSharedDictionary* dictionary, bool is_builtin, bool is_static_archive) { CompactHashtableStats stats; dictionary->reset();
*** 1660,1679 **** --- 2077,2107 ---- write_dictionary(&_unregistered_dictionary, false); } else { write_dictionary(&_dynamic_builtin_dictionary, true); write_dictionary(&_dynamic_unregistered_dictionary, false); } + if (_dumptime_lambda_proxy_class_dictionary != NULL) { + write_lambda_proxy_class_dictionary(&_lambda_proxy_class_dictionary); + } + } + + void SystemDictionaryShared::adjust_lambda_proxy_class_dictionary() { + if (_dumptime_lambda_proxy_class_dictionary != NULL) { + AdjustLambdaProxyClassInfo adjuster; + _dumptime_lambda_proxy_class_dictionary->iterate(&adjuster); + } } void SystemDictionaryShared::serialize_dictionary_headers(SerializeClosure* soc, bool is_static_archive) { if (is_static_archive) { _builtin_dictionary.serialize_header(soc); _unregistered_dictionary.serialize_header(soc); } else { _dynamic_builtin_dictionary.serialize_header(soc); _dynamic_unregistered_dictionary.serialize_header(soc); + _lambda_proxy_class_dictionary.serialize_header(soc); } } void SystemDictionaryShared::serialize_well_known_klasses(SerializeClosure* soc) { for (int i = FIRST_WKID; i < WKID_LIMIT; i++) {
*** 1704,1713 **** --- 2132,2142 ---- } InstanceKlass* SystemDictionaryShared::find_builtin_class(Symbol* name) { const RunTimeSharedClassInfo* record = find_record(&_builtin_dictionary, &_dynamic_builtin_dictionary, name); if (record != NULL) { + assert(!record->_klass->is_hidden(), "hidden class cannot be looked up by name"); return record->_klass; } else { return NULL; } }
*** 1728,1746 **** --- 2157,2197 ---- ResourceMark rm; _st->print_cr("%4d: %s", (_index++), record->_klass->external_name()); } }; + class SharedLambdaDictionaryPrinter : StackObj { + outputStream* _st; + int _index; + public: + SharedLambdaDictionaryPrinter(outputStream* st) : _st(st), _index(0) {} + + void do_value(const RunTimeLambdaProxyClassInfo* record) { + ResourceMark rm; + _st->print_cr("%4d: %s", (_index++), record->proxy_klass()->external_name()); + Klass* k = record->proxy_klass()->next_link(); + while (k != NULL) { + _st->print_cr("%4d: %s", (_index++), k->external_name()); + k = k->next_link(); + } + } + }; + void SystemDictionaryShared::print_on(outputStream* st) { if (UseSharedSpaces) { st->print_cr("Shared Dictionary"); SharedDictionaryPrinter p(st); _builtin_dictionary.iterate(&p); _unregistered_dictionary.iterate(&p); if (DynamicArchive::is_mapped()) { _dynamic_builtin_dictionary.iterate(&p); _unregistered_dictionary.iterate(&p); + if (!_lambda_proxy_class_dictionary.empty()) { + st->print_cr("Shared Lambda Dictionary"); + SharedLambdaDictionaryPrinter ldp(st); + _lambda_proxy_class_dictionary.iterate(&ldp); + } } } } void SystemDictionaryShared::print_table_statistics(outputStream* st) {
*** 1748,1757 **** --- 2199,2209 ---- _builtin_dictionary.print_table_statistics(st, "Builtin Shared Dictionary"); _unregistered_dictionary.print_table_statistics(st, "Unregistered Shared Dictionary"); if (DynamicArchive::is_mapped()) { _dynamic_builtin_dictionary.print_table_statistics(st, "Dynamic Builtin Shared Dictionary"); _dynamic_unregistered_dictionary.print_table_statistics(st, "Unregistered Shared Dictionary"); + _lambda_proxy_class_dictionary.print_table_statistics(st, "Lambda Shared Dictionary"); } } } bool SystemDictionaryShared::empty_dumptime_table() {
< prev index next >