< prev index next >

src/hotspot/share/memory/filemap.cpp

Print this page

*** 33,48 **** --- 33,51 ---- #include "classfile/altHashing.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" #include "logging/logMessage.hpp" #include "memory/filemap.hpp" + #include "memory/heapShared.inline.hpp" + #include "memory/iterator.inline.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/objArrayOop.hpp" + #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/arguments.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" #include "runtime/vm_version.hpp"
*** 186,195 **** --- 189,201 ---- _narrow_klass_base = Universe::narrow_klass_base(); _narrow_klass_shift = Universe::narrow_klass_shift(); _shared_path_table_size = mapinfo->_shared_path_table_size; _shared_path_table = mapinfo->_shared_path_table; _shared_path_entry_size = mapinfo->_shared_path_entry_size; + if (MetaspaceShared::is_heap_object_archiving_allowed()) { + _g1_reserved = G1CollectedHeap::heap()->g1_reserved(); + } // The following fields are for sanity checks for whether this archive // will function correctly with this JVM and the bootclasspath it's // invoked with.
*** 523,533 **** _paths_misc_info = NULL; return false; } size_t len = lseek(fd, 0, SEEK_END); ! struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[MetaspaceShared::last_valid_region]; // The last space might be empty if (si->_file_offset > len || len - si->_file_offset < si->_used) { fail_continue("The shared archive file has been truncated."); return false; --- 529,539 ---- _paths_misc_info = NULL; return false; } size_t len = lseek(fd, 0, SEEK_END); ! FileMapHeader::space_info* si = &_header->_space[MetaspaceShared::last_valid_region]; // The last space might be empty if (si->_file_offset > len || len - si->_file_offset < si->_used) { fail_continue("The shared archive file has been truncated."); return false;
*** 605,615 **** // Dump region to file. void FileMapInfo::write_region(int region, char* base, size_t size, bool read_only, bool allow_exec) { ! struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[region]; if (_file_open) { guarantee(si->_file_offset == _file_offset, "file offset mismatch."); log_info(cds)("Shared file region %d: " SIZE_FORMAT_HEX_W(08) " bytes, addr " INTPTR_FORMAT " file offset " SIZE_FORMAT_HEX_W(08), --- 611,621 ---- // Dump region to file. void FileMapInfo::write_region(int region, char* base, size_t size, bool read_only, bool allow_exec) { ! FileMapHeader::space_info* si = &_header->_space[region]; if (_file_open) { guarantee(si->_file_offset == _file_offset, "file offset mismatch."); log_info(cds)("Shared file region %d: " SIZE_FORMAT_HEX_W(08) " bytes, addr " INTPTR_FORMAT " file offset " SIZE_FORMAT_HEX_W(08),
*** 758,768 **** // JVM/TI RedefineClasses() support: // Remap the shared readonly space to shared readwrite, private. bool FileMapInfo::remap_shared_readonly_as_readwrite() { int idx = MetaspaceShared::ro; ! struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[idx]; if (!si->_read_only) { // the space is already readwrite so we are done return true; } size_t used = si->_used; --- 764,774 ---- // JVM/TI RedefineClasses() support: // Remap the shared readonly space to shared readwrite, private. bool FileMapInfo::remap_shared_readonly_as_readwrite() { int idx = MetaspaceShared::ro; ! FileMapHeader::space_info* si = &_header->_space[idx]; if (!si->_read_only) { // the space is already readwrite so we are done return true; } size_t used = si->_used;
*** 810,820 **** static const char* shared_region_name[] = { "MiscData", "ReadWrite", "ReadOnly", "MiscCode", "OptionalData", "String1", "String2", "OpenArchive1", "OpenArchive2" }; char* FileMapInfo::map_region(int i, char** top_ret) { assert(!MetaspaceShared::is_heap_region(i), "sanity"); ! struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i]; size_t used = si->_used; size_t alignment = os::vm_allocation_granularity(); size_t size = align_up(used, alignment); char *requested_addr = _header->region_addr(i); --- 816,826 ---- static const char* shared_region_name[] = { "MiscData", "ReadWrite", "ReadOnly", "MiscCode", "OptionalData", "String1", "String2", "OpenArchive1", "OpenArchive2" }; char* FileMapInfo::map_region(int i, char** top_ret) { assert(!MetaspaceShared::is_heap_region(i), "sanity"); ! FileMapHeader::space_info* si = &_header->_space[i]; size_t used = si->_used; size_t alignment = os::vm_allocation_granularity(); size_t size = align_up(used, alignment); char *requested_addr = _header->region_addr(i);
*** 850,859 **** --- 856,869 ---- static MemRegion *open_archive_heap_ranges = NULL; static int num_string_ranges = 0; static int num_open_archive_heap_ranges = 0; #if INCLUDE_CDS_JAVA_HEAP + bool FileMapInfo::has_heap_regions() { + return (_header->_space[MetaspaceShared::first_string]._used > 0); + } + // // Map the shared string objects and open archive heap objects to the runtime // java heap. // // The shared strings are mapped near the runtime java heap top. The
*** 864,898 **** // the runtime java heap. The mapped open archive heap data only contain // references to the shared strings and open archive objects initially. // During runtime execution, out-going references to any other java heap // regions may be added. GC may mark and update references in the mapped // open archive objects. ! void FileMapInfo::map_heap_regions() { ! if (MetaspaceShared::is_heap_object_archiving_allowed()) { log_info(cds)("Archived narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d", narrow_oop_mode(), p2i(narrow_oop_base()), narrow_oop_shift()); log_info(cds)("Archived narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d", p2i(narrow_klass_base()), narrow_klass_shift()); ! // Check that all the narrow oop and klass encodings match the archive if (narrow_oop_mode() != Universe::narrow_oop_mode() || narrow_oop_base() != Universe::narrow_oop_base() || ! narrow_oop_shift() != Universe::narrow_oop_shift() || ! narrow_klass_base() != Universe::narrow_klass_base() || ! narrow_klass_shift() != Universe::narrow_klass_shift()) { ! if (log_is_enabled(Info, cds) && _header->_space[MetaspaceShared::first_string]._used > 0) { ! log_info(cds)("Cached heap data from the CDS archive is being ignored. " ! "The current CompressedOops/CompressedClassPointers encoding differs from " ! "that archived due to heap size change. The archive was dumped using max heap " ! "size " UINTX_FORMAT "M.", max_heap_size()/M); log_info(cds)("Current narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d", Universe::narrow_oop_mode(), p2i(Universe::narrow_oop_base()), Universe::narrow_oop_shift()); ! log_info(cds)("Current narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d", ! p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift()); } ! } else { // First, map string regions as closed archive heap regions. // GC does not write into the regions. if (map_heap_data(&string_ranges, MetaspaceShared::first_string, MetaspaceShared::max_strings, --- 874,933 ---- // the runtime java heap. The mapped open archive heap data only contain // references to the shared strings and open archive objects initially. // During runtime execution, out-going references to any other java heap // regions may be added. GC may mark and update references in the mapped // open archive objects. ! void FileMapInfo::map_heap_regions_impl() { ! if (!MetaspaceShared::is_heap_object_archiving_allowed()) { ! log_info(cds)("Cached heap data from the CDS archive is being ignored. UseG1GC, " ! "UseCompressedOops and UseCompressedClassPointers are required."); ! return; ! } ! ! if (narrow_klass_base() != Universe::narrow_klass_base() || ! narrow_klass_shift() != Universe::narrow_klass_shift()) { ! log_info(cds)("Cached heap data from the CDS archive need to be relocated because"); ! log_info(cds)("the CDS archive was created with an incompatible heap size: " UINTX_FORMAT "M.", max_heap_size()/M); ! log_info(cds)("Current narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d", ! p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift()); ! return; ! } ! log_info(cds)("Archived narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d", narrow_oop_mode(), p2i(narrow_oop_base()), narrow_oop_shift()); log_info(cds)("Archived narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d", p2i(narrow_klass_base()), narrow_klass_shift()); ! ptrdiff_t delta = 0; ! if (narrow_oop_mode() != Universe::narrow_oop_mode() || narrow_oop_base() != Universe::narrow_oop_base() || ! narrow_oop_shift() != Universe::narrow_oop_shift()) { ! log_info(cds)("Cached heap data from the CDS archive need to be relocated because"); ! log_info(cds)("the CDS archive was created with an incompatible heap size: " UINTX_FORMAT "M.", max_heap_size()/M); log_info(cds)("Current narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d", Universe::narrow_oop_mode(), p2i(Universe::narrow_oop_base()), Universe::narrow_oop_shift()); ! ! _heap_pointers_need_relocation = true; ! ! // dumptime heap end ------------v ! // [ |archived heap regions| ] runtime heap end ------v ! // [ |archived heap regions| ] ! // |<-----delta-------------------->| ! // ! // At dump time, the archived heap region were near the top of the heap. ! // At run time, that region may not be inside the heap, so we move it so ! // that it's now near the top of teh runtime time. This can be done by ! // the simple math of adding the delta as shown above. ! address dumptime_heap_end = (address)_header->_g1_reserved.end(); ! address runtime_heap_end = (address)G1CollectedHeap::heap()->g1_reserved().end(); ! delta = runtime_heap_end - dumptime_heap_end; } ! ! HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift()); ! // First, map string regions as closed archive heap regions. // GC does not write into the regions. if (map_heap_data(&string_ranges, MetaspaceShared::first_string, MetaspaceShared::max_strings,
*** 906,921 **** &num_open_archive_heap_ranges, true /* open */)) { MetaspaceShared::set_open_archive_heap_region_mapped(); } } ! } ! } else { ! if (log_is_enabled(Info, cds) && _header->_space[MetaspaceShared::first_string]._used > 0) { ! log_info(cds)("Cached heap data from the CDS archive is being ignored. UseG1GC, " ! "UseCompressedOops and UseCompressedClassPointers are required."); ! } } if (!StringTable::shared_string_mapped()) { assert(string_ranges == NULL && num_string_ranges == 0, "sanity"); } --- 941,955 ---- &num_open_archive_heap_ranges, true /* open */)) { MetaspaceShared::set_open_archive_heap_region_mapped(); } } ! } ! ! void FileMapInfo::map_heap_regions() { ! if (has_heap_regions()) { ! map_heap_regions_impl(); } if (!StringTable::shared_string_mapped()) { assert(string_ranges == NULL && num_string_ranges == 0, "sanity"); }
*** 926,945 **** } bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first, int max, int* num, bool is_open_archive) { MemRegion * regions = new MemRegion[max]; ! struct FileMapInfo::FileMapHeader::space_info* si; int region_num = 0; for (int i = first; i < first + max; i++) { si = &_header->_space[i]; ! size_t used = si->_used; ! if (used > 0) { ! size_t size = used; ! char* requested_addr = (char*)((void*)CompressedOops::decode_not_null( (narrowOop)si->_addr._offset)); regions[region_num] = MemRegion((HeapWord*)requested_addr, size / HeapWordSize); region_num ++; } } --- 960,978 ---- } bool FileMapInfo::map_heap_data(MemRegion **heap_mem, int first, int max, int* num, bool is_open_archive) { MemRegion * regions = new MemRegion[max]; ! FileMapHeader::space_info* si; int region_num = 0; for (int i = first; i < first + max; i++) { si = &_header->_space[i]; ! size_t size = si->_used; ! if (size > 0) { ! char* requested_addr = (char*)((void*)HeapShared::decode_not_null( (narrowOop)si->_addr._offset)); regions[region_num] = MemRegion((HeapWord*)requested_addr, size / HeapWordSize); region_num ++; } }
*** 1001,1010 **** --- 1034,1088 ---- } } return true; } + void FileMapInfo::relocate_archived_heap_embedded_pointers() { + if (!_heap_pointers_need_relocation) { + return; + } + + relocate_archived_heap_embedded_pointers_impl(string_ranges, + num_string_ranges); + + relocate_archived_heap_embedded_pointers_impl(open_archive_heap_ranges, + num_open_archive_heap_ranges); + } + + class RelocateInternalPointers: public BasicOopIterateClosure { + public: + virtual bool should_verify_oops(void) { + return false; + } + virtual void do_oop(narrowOop *p) { + narrowOop v = *p; + if (!CompressedOops::is_null(v)) { + oop o = HeapShared::decode_not_null(v); + RawAccess<IS_NOT_NULL>::oop_store(p, o); + } + } + virtual void do_oop(oop *p) { + ShouldNotReachHere(); + } + }; + + void FileMapInfo::relocate_archived_heap_embedded_pointers_impl(MemRegion *heap_mem, int num) { + RelocateInternalPointers relocator; + + for (int i=0; i<num; i++) { + HeapWord* p = heap_mem[i].start(); + HeapWord* end = heap_mem[i].end(); + while (p < end) { + oop o = (oop)p; + o->oop_iterate(&relocator); + p += o->size(); + } + } + } + + // This internally allocates objects using SystemDictionary::Object_klass(), so it + // must be called after the well-known classes are resolved. void FileMapInfo::fixup_mapped_heap_regions() { // If any string regions were found, call the fill routine to make them parseable. // Note that string_ranges may be non-NULL even if no ranges were found. if (num_string_ranges != 0) { assert(string_ranges != NULL, "Null string_ranges array with non-zero count");
*** 1055,1065 **** // Unmap a memory region in the address space. void FileMapInfo::unmap_region(int i) { assert(!MetaspaceShared::is_heap_region(i), "sanity"); ! struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i]; size_t used = si->_used; size_t size = align_up(used, os::vm_allocation_granularity()); if (used == 0) { return; --- 1133,1143 ---- // Unmap a memory region in the address space. void FileMapInfo::unmap_region(int i) { assert(!MetaspaceShared::is_heap_region(i), "sanity"); ! FileMapHeader::space_info* si = &_header->_space[i]; size_t used = si->_used; size_t size = align_up(used, os::vm_allocation_granularity()); if (used == 0) { return;
*** 1084,1093 **** --- 1162,1172 ---- } } FileMapInfo* FileMapInfo::_current_info = NULL; + bool FileMapInfo::_heap_pointers_need_relocation = false; Array<u8>* FileMapInfo::_shared_path_table = NULL; int FileMapInfo::_shared_path_table_size = 0; size_t FileMapInfo::_shared_path_entry_size = 0x1234baad; bool FileMapInfo::_validating_shared_path_table = false;
< prev index next >