src/share/vm/memory/metaspaceShared.cpp

Print this page
rev 9227 : [mq] cds

*** 21,30 **** --- 21,32 ---- * questions. * */ #include "precompiled.hpp" + #include "classfile/classListParser.hpp" + #include "classfile/classLoaderExt.hpp" #include "classfile/dictionary.hpp" #include "classfile/loaderConstraints.hpp" #include "classfile/placeholders.hpp" #include "classfile/sharedClassUtil.hpp" #include "classfile/symbolTable.hpp"
*** 40,49 **** --- 42,52 ---- #include "oops/oop.inline.hpp" #include "runtime/os.hpp" #include "runtime/signature.hpp" #include "runtime/vmThread.hpp" #include "runtime/vm_operations.hpp" + #include "utilities/defaultStream.hpp" #include "utilities/hashtable.inline.hpp" int MetaspaceShared::_max_alignment = 0; ReservedSpace* MetaspaceShared::_shared_rs = NULL;
*** 95,104 **** --- 98,111 ---- InstanceKlass* ik = InstanceKlass::cast(k); ik->array_klasses_do(collect_classes); } } + static void collect_classes2(Klass* k, ClassLoaderData* class_data) { + collect_classes(k); + } + static void remove_unshareable_in_classes() { for (int i = 0; i < _global_klass_objects->length(); i++) { Klass* k = _global_klass_objects->at(i); k->remove_unshareable_info(); }
*** 420,435 **** GrowableArray<Klass*> *_class_promote_order; VirtualSpace _md_vs; VirtualSpace _mc_vs; CompactHashtableWriter* _string_cht; GrowableArray<MemRegion> *_string_regions; public: VM_PopulateDumpSharedSpace(ClassLoaderData* loader_data, GrowableArray<Klass*> *class_promote_order) : _loader_data(loader_data) { - // Split up and initialize the misc code and data spaces ReservedSpace* shared_rs = MetaspaceShared::shared_rs(); size_t metadata_size = SharedReadOnlySize + SharedReadWriteSize; ReservedSpace shared_ro_rw = shared_rs->first_part(metadata_size); ReservedSpace misc_section = shared_rs->last_part(metadata_size); --- 427,445 ---- GrowableArray<Klass*> *_class_promote_order; VirtualSpace _md_vs; VirtualSpace _mc_vs; CompactHashtableWriter* _string_cht; GrowableArray<MemRegion> *_string_regions; + char* _md_alloc_low; + char* _md_alloc_top; + char* _md_alloc_max; + static VM_PopulateDumpSharedSpace* _instance; public: VM_PopulateDumpSharedSpace(ClassLoaderData* loader_data, GrowableArray<Klass*> *class_promote_order) : _loader_data(loader_data) { // Split up and initialize the misc code and data spaces ReservedSpace* shared_rs = MetaspaceShared::shared_rs(); size_t metadata_size = SharedReadOnlySize + SharedReadWriteSize; ReservedSpace shared_ro_rw = shared_rs->first_part(metadata_size); ReservedSpace misc_section = shared_rs->last_part(metadata_size);
*** 438,460 **** --- 448,503 ---- ReservedSpace md_rs = misc_section.first_part(SharedMiscDataSize); ReservedSpace mc_rs = misc_section.last_part(SharedMiscDataSize); _md_vs.initialize(md_rs, SharedMiscDataSize); _mc_vs.initialize(mc_rs, SharedMiscCodeSize); _class_promote_order = class_promote_order; + + _md_alloc_low = _md_vs.low(); + _md_alloc_top = _md_alloc_low + sizeof(char*); + _md_alloc_max = _md_vs.low() + SharedMiscDataSize; + + assert(_instance == NULL, "must be singleton"); + _instance = this; + } + + ~VM_PopulateDumpSharedSpace() { + assert(_instance == this, "must be singleton"); + _instance = NULL; + } + + static VM_PopulateDumpSharedSpace* instance() { + assert(_instance != NULL, "sanity"); + return _instance; } VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; } void doit(); // outline because gdb sucks + char* misc_data_space_alloc(size_t num_bytes) { + size_t alignment = sizeof(char*); + num_bytes = align_size_up(num_bytes, alignment); + _md_alloc_top = (char*)align_ptr_up(_md_alloc_top, alignment); + if (_md_alloc_top + num_bytes > _md_alloc_max) { + report_out_of_shared_space(SharedMiscData); + } + + char* p = _md_alloc_top; + _md_alloc_top += num_bytes; + + memset(p, 0, num_bytes); + return p; + } + private: void handle_misc_data_space_failure(bool success) { if (!success) { report_out_of_shared_space(SharedMiscData); } } }; // class VM_PopulateDumpSharedSpace + VM_PopulateDumpSharedSpace* VM_PopulateDumpSharedSpace::_instance; void VM_PopulateDumpSharedSpace::doit() { Thread* THREAD = VMThread::vm_thread(); NOT_PRODUCT(SystemDictionary::verify();) // The following guarantee is meant to ensure that no loader constraints
*** 473,483 **** // At this point, many classes have been loaded. // Gather systemDictionary classes in a global array and do everything to // that so we don't have to walk the SystemDictionary again. _global_klass_objects = new GrowableArray<Klass*>(1000); Universe::basic_type_classes_do(collect_classes); ! SystemDictionary::classes_do(collect_classes); tty->print_cr("Number of classes %d", _global_klass_objects->length()); { int num_type_array = 0, num_obj_array = 0, num_inst = 0; for (int i = 0; i < _global_klass_objects->length(); i++) { --- 516,530 ---- // At this point, many classes have been loaded. // Gather systemDictionary classes in a global array and do everything to // that so we don't have to walk the SystemDictionary again. _global_klass_objects = new GrowableArray<Klass*>(1000); Universe::basic_type_classes_do(collect_classes); ! ! // Need to call SystemDictionary::classes_do(void f(Klass*, ClassLoaderData*)) ! // as we may have some classes with NULL ClassLoaderData* in the dictionary. Other ! // variants of SystemDictionary::classes_do will skip those classes. ! SystemDictionary::classes_do(collect_classes2); tty->print_cr("Number of classes %d", _global_klass_objects->length()); { int num_type_array = 0, num_obj_array = 0, num_inst = 0; for (int i = 0; i < _global_klass_objects->length(); i++) {
*** 513,522 **** --- 560,573 ---- char* md_end = _md_vs.high(); char* mc_low = _mc_vs.low(); char* mc_top = mc_low; char* mc_end = _mc_vs.high(); + assert(_md_alloc_top != NULL, "sanity"); + *(char**)_md_alloc_low = _md_alloc_top; + md_top = _md_alloc_top; + // Reserve space for the list of Klass*s whose vtables are used // for patching others as needed. void** vtbl_list = (void**)md_top; int vtbl_list_size = MetaspaceShared::vtbl_list_size;
*** 733,742 **** --- 784,794 ---- // Preload classes from a list, populate the shared spaces and dump to a // file. void MetaspaceShared::preload_and_dump(TRAPS) { TraceTime timer("Dump Shared Spaces", TraceStartupTime); ResourceMark rm; + char class_list_path_str[JVM_MAXPATHLEN]; tty->print_cr("Allocated shared space: " SIZE_FORMAT " bytes at " PTR_FORMAT, MetaspaceShared::shared_rs()->size(), p2i(MetaspaceShared::shared_rs()->base()));
*** 745,755 **** const char* class_list_path; if (SharedClassListFile == NULL) { // Construct the path to the class list (in jre/lib) // Walk up two directories from the location of the VM and // optionally tack on "lib" (depending on platform) - char class_list_path_str[JVM_MAXPATHLEN]; os::jvm_path(class_list_path_str, sizeof(class_list_path_str)); for (int i = 0; i < 3; i++) { char *end = strrchr(class_list_path_str, *os::file_separator()); if (end != NULL) *end = '\0'; } --- 797,806 ----
*** 783,792 **** --- 834,848 ---- // java.util.HashMap static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;"; SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD); + // Need to allocate the op here: + // op.misc_data_space_alloc() will be called during preload_and_dump(). + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + VM_PopulateDumpSharedSpace op(loader_data, class_promote_order); + tty->print_cr("Loading classes to share ..."); _has_error_classes = false; class_count += preload_and_dump(class_list_path, class_promote_order, THREAD); if (ExtraSharedClassListFile) {
*** 807,854 **** // fails verification, all other interfaces that were not specified in the classlist but // are implemented by K are not verified. link_and_cleanup_shared_classes(CATCH); tty->print_cr("Rewriting and linking classes: done"); - // Create and dump the shared spaces. Everything so far is loaded - // with the null class loader. - ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); - VM_PopulateDumpSharedSpace op(loader_data, class_promote_order); VMThread::execute(&op); - // Since various initialization steps have been undone by this process, // it is not reasonable to continue running a java process. exit(0); } ! int MetaspaceShared::preload_and_dump(const char * class_list_path, GrowableArray<Klass*>* class_promote_order, TRAPS) { ! FILE* file = fopen(class_list_path, "r"); ! char class_name[256]; int class_count = 0; ! if (file != NULL) { ! while ((fgets(class_name, sizeof class_name, file)) != NULL) { ! if (*class_name == '#') { // comment ! continue; ! } ! // Remove trailing newline ! size_t name_len = strlen(class_name); ! if (class_name[name_len-1] == '\n') { ! class_name[name_len-1] = '\0'; ! } - // Got a class name - load it. - TempNewSymbol class_name_symbol = SymbolTable::new_permanent_symbol(class_name, THREAD); - guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol."); - Klass* klass = SystemDictionary::resolve_or_null(class_name_symbol, - THREAD); CLEAR_PENDING_EXCEPTION; if (klass != NULL) { if (PrintSharedSpaces && Verbose && WizardMode) { ! tty->print_cr("Shared spaces preloaded: %s", class_name); } InstanceKlass* ik = InstanceKlass::cast(klass); // Should be class load order as per -XX:+TraceClassLoadingPreorder --- 863,893 ---- // fails verification, all other interfaces that were not specified in the classlist but // are implemented by K are not verified. link_and_cleanup_shared_classes(CATCH); tty->print_cr("Rewriting and linking classes: done"); VMThread::execute(&op); // Since various initialization steps have been undone by this process, // it is not reasonable to continue running a java process. exit(0); } ! ! int MetaspaceShared::preload_and_dump(const char* class_list_path, GrowableArray<Klass*>* class_promote_order, TRAPS) { ! ClassListParser parser(class_list_path); int class_count = 0; ! while (parser.parse_one_line()) { ! Klass* klass = ClassLoaderExt::load_one_class(&parser, THREAD); CLEAR_PENDING_EXCEPTION; if (klass != NULL) { if (PrintSharedSpaces && Verbose && WizardMode) { ! ResourceMark rm; ! tty->print_cr("Shared spaces preloaded: %s", klass->external_name()); } InstanceKlass* ik = InstanceKlass::cast(klass); // Should be class load order as per -XX:+TraceClassLoadingPreorder
*** 860,880 **** // cpCache) are located together. try_link_class(ik, THREAD); guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class"); class_count++; - } else { - //tty->print_cr("Preload failed: %s", class_name); } } - fclose(file); - } else { - char errmsg[JVM_MAXPATHLEN]; - os::lasterror(errmsg, JVM_MAXPATHLEN); - tty->print_cr("Loading classlist failed: %s", errmsg); - exit(1); - } return class_count; } // Returns true if the class's status has changed --- 899,910 ----
*** 906,915 **** --- 936,950 ---- } else { return false; } } + // Allocate misc data blocks during dumping. + char* MetaspaceShared::misc_data_space_alloc(size_t num_bytes) { + return VM_PopulateDumpSharedSpace::instance()->misc_data_space_alloc(num_bytes); + } + // Closure for serializing initialization data in from a data area // (ptr_array) read from the shared file. class ReadClosure : public SerializeClosure { private:
*** 1031,1040 **** --- 1066,1077 ---- void MetaspaceShared::initialize_shared_spaces() { FileMapInfo *mapinfo = FileMapInfo::current_info(); char* buffer = mapinfo->header()->region_addr(md); + buffer = *((char**)buffer); // skip over the md_alloc'ed blocks + // Skip over (reserve space for) a list of addresses of C++ vtables // for Klass objects. They get filled in later. void** vtbl_list = (void**)buffer; buffer += MetaspaceShared::vtbl_list_size * sizeof(void*);