< prev index next >
src/hotspot/share/memory/filemap.cpp
Print this page
@@ -33,16 +33,19 @@
#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,10 +189,13 @@
_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,11 +529,11 @@
_paths_misc_info = NULL;
return false;
}
size_t len = lseek(fd, 0, SEEK_END);
- struct FileMapInfo::FileMapHeader::space_info* si =
+ 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,11 +611,11 @@
// 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];
+ 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,11 +764,11 @@
// 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];
+ 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,11 +816,11 @@
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];
+ 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,10 +856,14 @@
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,35 +874,60 @@
// 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()) {
+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());
- // Check that all the narrow oop and klass encodings match the archive
+ 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() ||
- 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);
+ 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());
- log_info(cds)("Current narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
- p2i(Universe::narrow_klass_base()), Universe::narrow_klass_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;
}
- } else {
+
+ 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,16 +941,15 @@
&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.");
- }
+}
+
+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,20 +960,19 @@
}
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;
+ 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(
+ 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,10 +1034,55 @@
}
}
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,11 +1133,11 @@
// 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];
+ 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,10 +1162,11 @@
}
}
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 >