< 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 >