< prev index next >
src/share/vm/memory/filemap.cpp
Print this page
@@ -349,11 +349,12 @@
}
size_t len = lseek(fd, 0, SEEK_END);
struct FileMapInfo::FileMapHeader::space_info* si =
&_header->_space[MetaspaceShared::last_valid_region];
- if (si->_file_offset >= len || len - si->_file_offset < si->_used) {
+ // 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;
}
_file_offset += (long)n;
@@ -441,11 +442,11 @@
" bytes, addr " INTPTR_FORMAT " file offset " SIZE_FORMAT_HEX_W(08),
region, size, p2i(base), _file_offset);
} else {
si->_file_offset = _file_offset;
}
- if (MetaspaceShared::is_string_region(region)) {
+ if (MetaspaceShared::is_heap_region(region)) {
assert((base - (char*)Universe::narrow_oop_base()) % HeapWordSize == 0, "Sanity");
if (base != NULL) {
si->_addr._offset = (intx)oopDesc::encode_heap_oop_not_null((oop)base);
} else {
si->_addr._offset = 0;
@@ -458,80 +459,71 @@
si->_allow_exec = allow_exec;
si->_crc = ClassLoader::crc32(0, base, (jint)size);
write_bytes_aligned(base, (int)size);
}
-// Write the string space. The string space contains one or multiple GC(G1) regions.
-// When the total string space size is smaller than one GC region of the dump time,
-// only one string region is used for shared strings.
+// Write the current archive heap region, which contains one or multiple GC(G1) regions.
+// When current archive heap region size is smaller than one GC region of the dump time,
+// all archive heap data is written out as one region.
//
-// If the total string space size is bigger than one GC region, there would be more
-// than one GC regions allocated for shared strings. The first/bottom GC region might
+// If the current archive heap region size is bigger than one GC region, there would be more
+// than one GC regions allocated for archive heap data. The first/bottom GC region might
// be a partial GC region with the empty portion at the higher address within that region.
-// The non-empty portion of the first region is written into the archive as one string
+// The non-empty portion of the first region is written into the archive as one archive
// region. The rest are consecutive full GC regions if they exist, which can be written
-// out in one chunk as another string region.
+// out in one chunk as another archive region.
//
-// Here's the mapping from (GrowableArray<MemRegion> *regions) -> (metaspace string regions).
-// + We have 1 or more heap regions: r0, r1, r2 ..... rn
-// + We have 2 metaspace string regions: s0 and s1
+// Here's the mapping from (archive heap regions) -> (GrowableArray<MemRegion> *regions).
+// + We have 1 or more archive heap regions: ah0, ah1, ah2 ..... ahn
+// + We have 2 consolidate heap memory regions: r0 and r1
//
-// If there's a single heap region (r0), then s0 == r0, and s1 is empty.
+// If there's a single archive heap region (ah0), then r0 == ah0, and r1 is empty.
// Otherwise:
//
// "X" represented space that's occupied by heap objects.
// "_" represented unused spaced in the heap region.
//
//
-// |r0 | r1 | r2 | ...... | rn |
+// |ah0 | ah1 | ah2| ...... | ahn |
// |XXXXXX|__ |XXXXX|XXXX|XXXXXXXX|XXXX|
-// |<-s0->| |<- s1 ----------------->|
+// |<-r0->| |<- r1 ----------------->|
// ^^^
// |
-// +-- unmapped space
-void FileMapInfo::write_string_regions(GrowableArray<MemRegion> *regions,
- char** st0_start, char** st0_top, char** st0_end,
- char** st1_start, char** st1_top, char** st1_end) {
- *st0_start = *st0_top = *st0_end = NULL;
- *st1_start = *st1_top = *st1_end = NULL;
-
- assert(MetaspaceShared::max_strings == 2, "this loop doesn't work for any other value");
- for (int i = MetaspaceShared::first_string;
- i < MetaspaceShared::first_string + MetaspaceShared::max_strings; i++) {
+// +-- gap
+void FileMapInfo::write_archive_heap_regions(GrowableArray<MemRegion> *regions,
+ int first_region, int max_num_regions,
+ char** r0_start, char** r0_top,
+ char** r1_start, char** r1_top) {
+ int arr_len = regions == NULL ? 0 : regions->length();
+ assert(max_num_regions <= 2, "this loop doesn't work for any other value");
+ assert(arr_len <= max_num_regions, "number of memory regions exceeds maximum");
+
+ *r0_start = *r0_top = NULL;
+ *r1_start = *r1_top = NULL;
+
+ for (int i = first_region, arr_idx = 0; i < first_region + max_num_regions; i++, arr_idx++) {
char* start = NULL;
size_t size = 0;
- int len = regions->length();
- if (len > 0) {
- if (i == MetaspaceShared::first_string) {
- MemRegion first = regions->first();
- start = (char*)first.start();
- size = first.byte_size();
- *st0_start = start;
- *st0_top = start + size;
- if (len > 1) {
- *st0_end = (char*)regions->at(1).start();
- } else {
- *st0_end = start + size;
- }
+ if (arr_idx < arr_len) {
+ start = (char*)regions->at(arr_idx).start();
+ size = regions->at(arr_idx).byte_size();
+ }
+ if (i == first_region) {
+ *r0_start = start;
+ *r0_top = start + size;
} else {
- assert(i == MetaspaceShared::first_string + 1, "must be");
- if (len > 1) {
- start = (char*)regions->at(1).start();
- size = (char*)regions->at(len - 1).end() - start;
- *st1_start = start;
- *st1_top = start + size;
- *st1_end = start + size;
+ assert(i == first_region + 1, "must be");
+ *r1_start = start;
+ *r1_top = start + size;
}
- }
- }
- log_info(cds)("String region %d " INTPTR_FORMAT " - " INTPTR_FORMAT " = " SIZE_FORMAT_W(8) " bytes",
+
+ log_info(cds)("Archive heap region %d " INTPTR_FORMAT " - " INTPTR_FORMAT " = " SIZE_FORMAT_W(8) " bytes",
i, p2i(start), p2i(start + size), size);
write_region(i, start, size, false, false);
}
}
-
// Dump bytes to file -- at the current file position.
void FileMapInfo::write_bytes(const void* buffer, int nbytes) {
if (_file_open) {
int n = ::write(_fd, buffer, nbytes);
@@ -639,15 +631,15 @@
return rs;
}
// Memory map a region in the address space.
-static const char* shared_region_name[] = { "ReadOnly", "ReadWrite", "MiscData", "MiscCode",
- "String1", "String2", "OptionalData" };
+static const char* shared_region_name[] = { "MiscData", "ReadWrite", "ReadOnly", "MiscCode", "OptionalData",
+ "String1", "String2", "OpenArchive1", "OpenArchive2" };
char* FileMapInfo::map_region(int i) {
- assert(!MetaspaceShared::is_string_region(i), "sanity");
+ 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);
@@ -673,122 +665,187 @@
return base;
}
static MemRegion *string_ranges = NULL;
-static int num_ranges = 0;
-bool FileMapInfo::map_string_regions() {
-#if INCLUDE_ALL_GCS
- if (UseG1GC && UseCompressedOops && UseCompressedClassPointers) {
+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
+//
+// Map the string regions and open archive heap regions to the runtime java
+// heap.
+//
+// The archive string regions are mapped near the runtime java heap top. The
+// mapped string regions contain no out-going references to any other java heap
+// regions. GC does not write into the string regions.
+//
+// The open archive heap regions are mapped below the string regions in
+// the runtime java heap. The mapped open archive heap regions may contain
+// out-going references to the string regions or other java heap regions.
+// Objects inside the open archive heap regions may be marked by GC and
+// the references are updated by GC.
+//
+void FileMapInfo::map_heap_regions() {
+ if (MetaspaceShared::allow_archive_heap_object()) {
// Check that all the narrow oop and klass encodings match the archive
if (narrow_oop_mode() != Universe::narrow_oop_mode() ||
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)("Shared string data from the CDS archive is being ignored. "
+ 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);
}
} else {
- string_ranges = new MemRegion[MetaspaceShared::max_strings];
+ // 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,
+ &num_string_ranges)) {
+ StringTable::set_shared_string_mapped();
+
+ // Now, map open_archive heap regions, GC can write into the regions.
+ if (map_heap_data(&open_archive_heap_ranges,
+ MetaspaceShared::first_open_archive_heap_region,
+ MetaspaceShared::max_open_archive_heap_region,
+ &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");
+ }
+
+ if (!MetaspaceShared::open_archive_heap_region_mapped()) {
+ assert(open_archive_heap_ranges == NULL && num_open_archive_heap_ranges == 0, "sanity");
+ }
+}
+
+bool FileMapInfo::map_heap_data(MemRegion **mem_regions, 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 = MetaspaceShared::first_string;
- i < MetaspaceShared::first_string + MetaspaceShared::max_strings; i++) {
+ 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*)oopDesc::decode_heap_oop_not_null(
(narrowOop)si->_addr._offset));
- string_ranges[num_ranges] = MemRegion((HeapWord*)requested_addr, size / HeapWordSize);
- num_ranges ++;
+ regions[region_num] = MemRegion((HeapWord*)requested_addr, size / HeapWordSize);
+ region_num ++;
}
}
- if (num_ranges == 0) {
- StringTable::ignore_shared_strings(true);
- return true; // no shared string data
+ if (region_num == 0) {
+ return false; // no archived java heap data
}
// Check that ranges are within the java heap
- if (!G1CollectedHeap::heap()->check_archive_addresses(string_ranges, num_ranges)) {
- fail_continue("Unable to allocate shared string space: range is not "
- "within java heap.");
+ if (!G1CollectedHeap::heap()->check_archive_addresses(regions, region_num)) {
+ if (log_is_enabled(Info, cds)) {
+ log_info(cds)("UseSharedSpaces: Unable to allocate region, "
+ "range is not within java heap.");
+ }
return false;
}
// allocate from java heap
- if (!G1CollectedHeap::heap()->alloc_archive_regions(string_ranges, num_ranges)) {
- fail_continue("Unable to allocate shared string space: range is "
- "already in use.");
+ if (!G1CollectedHeap::heap()->alloc_archive_regions(
+ regions, region_num, is_open_archive)) {
+ if (log_is_enabled(Info, cds)) {
+ log_info(cds)("UseSharedSpaces: Unable to allocate region, "
+ "java heap range is already in use.");
+ }
return false;
}
- // Map the string data. No need to call MemTracker::record_virtual_memory_type()
- // for mapped string regions as they are part of the reserved java heap, which
- // is already recorded.
- for (int i = 0; i < num_ranges; i++) {
- si = &_header->_space[MetaspaceShared::first_string + i];
- char* addr = (char*)string_ranges[i].start();
+ // Map the archived heap data. No need to call MemTracker::record_virtual_memory_type()
+ // for mapped regions as they are part of the reserved java heap, which is
+ // already recorded.
+ for (int i = 0; i < region_num; i++) {
+ si = &_header->_space[first + i];
+ char* addr = (char*)regions[i].start();
char* base = os::map_memory(_fd, _full_path, si->_file_offset,
- addr, string_ranges[i].byte_size(), si->_read_only,
+ addr, regions[i].byte_size(), si->_read_only,
si->_allow_exec);
if (base == NULL || base != addr) {
- // dealloc the string regions from java heap
- dealloc_string_regions();
- fail_continue("Unable to map shared string space at required address.");
- return false;
- }
+ // dealloc the regions from java heap
+ dealloc_archive_heap_regions(regions, region_num);
+ if (log_is_enabled(Info, cds)) {
+ log_info(cds)("UseSharedSpaces: Unable to map at required address in java heap.");
}
-
- if (!verify_string_regions()) {
- // dealloc the string regions from java heap
- dealloc_string_regions();
- fail_continue("Shared string regions are corrupt");
return false;
}
-
- // the shared string data is mapped successfully
- return true;
}
- } else {
- if (log_is_enabled(Info, cds) && _header->_space[MetaspaceShared::first_string]._used > 0) {
- log_info(cds)("Shared string data from the CDS archive is being ignored. UseG1GC, "
- "UseCompressedOops and UseCompressedClassPointers are required.");
+
+ if (!verify_mapped_heap_regions(first, region_num)) {
+ // dealloc the regions from java heap
+ dealloc_archive_heap_regions(regions, region_num);
+ if (log_is_enabled(Info, cds)) {
+ log_info(cds)("UseSharedSpaces: mapped heap regions are corrupt");
}
+ return false;
}
- // if we get here, the shared string data is not mapped
- assert(string_ranges == NULL && num_ranges == 0, "sanity");
- StringTable::ignore_shared_strings(true);
-#endif
+ // the shared heap data is mapped successfully
+ *mem_regions = regions;
+ *num = region_num;
return true;
}
-bool FileMapInfo::verify_string_regions() {
- for (int i = MetaspaceShared::first_string;
- i < MetaspaceShared::first_string + MetaspaceShared::max_strings; i++) {
+bool FileMapInfo::verify_mapped_heap_regions(int first, int num) {
+ for (int i = first;
+ i <= first + num; i++) {
if (!verify_region_checksum(i)) {
return false;
}
}
return true;
}
-void FileMapInfo::fixup_string_regions() {
-#if INCLUDE_ALL_GCS
+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_ranges != 0) {
+ if (num_string_ranges != 0) {
assert(string_ranges != NULL, "Null string_ranges array with non-zero count");
- G1CollectedHeap::heap()->fill_archive_regions(string_ranges, num_ranges);
+ G1CollectedHeap::heap()->fill_archive_regions(string_ranges, num_string_ranges);
+ }
+
+ // do the same for mapped open archive heap regions
+ if (num_open_archive_heap_ranges != 0) {
+ assert(open_archive_heap_ranges != NULL, "NULL open_archive_heap_ranges array with non-zero count");
+ G1CollectedHeap::heap()->fill_archive_regions(open_archive_heap_ranges,
+ num_open_archive_heap_ranges);
+ }
+}
+
+// dealloc the archive regions from java heap
+void FileMapInfo::dealloc_archive_heap_regions(MemRegion* regions, int num) {
+ if (num > 0) {
+ assert(regions != NULL, "Null archive ranges array with non-zero count");
+ G1CollectedHeap::heap()->dealloc_archive_regions(regions, num);
}
-#endif
}
+#endif // INCLUDE_CDS_JAVA_HEAP
bool FileMapInfo::verify_region_checksum(int i) {
if (!VerifySharedSpaces) {
return true;
}
@@ -796,12 +853,15 @@
size_t sz = _header->_space[i]._used;
if (sz == 0) {
return true; // no data
}
- if (MetaspaceShared::is_string_region(i) && StringTable::shared_string_ignored()) {
- return true; // shared string data are not mapped
+ if ((MetaspaceShared::is_string_region(i) &&
+ !StringTable::shared_string_mapped()) ||
+ (MetaspaceShared::is_open_archive_heap_region(i) &&
+ !MetaspaceShared::open_archive_heap_region_mapped())) {
+ return true; // archived heap data is not mapped
}
const char* buf = _header->region_addr(i);
int crc = ClassLoader::crc32(0, buf, (jint)sz);
if (crc != _header->_space[i]._crc) {
fail_continue("Checksum verification failed.");
@@ -811,11 +871,11 @@
}
// Unmap a memory region in the address space.
void FileMapInfo::unmap_region(int i) {
- assert(!MetaspaceShared::is_string_region(i), "sanity");
+ 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) {
@@ -826,20 +886,10 @@
if (!os::unmap_memory(addr, size)) {
fail_stop("Unable to unmap shared space.");
}
}
-// dealloc the archived string region from java heap
-void FileMapInfo::dealloc_string_regions() {
-#if INCLUDE_ALL_GCS
- if (num_ranges > 0) {
- assert(string_ranges != NULL, "Null string_ranges array with non-zero count");
- G1CollectedHeap::heap()->dealloc_archive_regions(string_ranges, num_ranges);
- }
-#endif
-}
-
void FileMapInfo::assert_mark(bool check) {
if (!check) {
fail_stop("Mark mismatch while restoring from shared file.");
}
}
@@ -881,13 +931,13 @@
}
return true;
}
char* FileMapInfo::FileMapHeader::region_addr(int idx) {
- if (MetaspaceShared::is_string_region(idx)) {
- return (char*)((void*)oopDesc::decode_heap_oop_not_null(
- (narrowOop)_space[idx]._addr._offset));
+ if (MetaspaceShared::is_heap_region(idx)) {
+ return _space[idx]._used > 0 ?
+ (char*)((void*)oopDesc::decode_heap_oop_not_null((narrowOop)_space[idx]._addr._offset)) : NULL;
} else {
return _space[idx]._addr._base;
}
}
@@ -963,19 +1013,19 @@
}
return status;
}
// The following method is provided to see whether a given pointer
-// falls in the mapped shared space.
+// falls in the mapped shared metadata space.
// Param:
// p, The given pointer
// Return:
// True if the p is within the mapped shared space, otherwise, false.
bool FileMapInfo::is_in_shared_space(const void* p) {
- for (int i = 0; i < MetaspaceShared::n_regions; i++) {
+ for (int i = 0; i < MetaspaceShared::num_non_heap_spaces; i++) {
char *base;
- if (MetaspaceShared::is_string_region(i) && _header->_space[i]._used == 0) {
+ if (_header->_space[i]._used == 0) {
continue;
}
base = _header->region_addr(i);
if (p >= base && p < base + _header->_space[i]._used) {
return true;
@@ -983,11 +1033,11 @@
}
return false;
}
-// Check if a given address is within one of the shared regions ( ro, rw, mc or md)
+// Check if a given address is within one of the shared regions
bool FileMapInfo::is_in_shared_region(const void* p, int idx) {
assert(idx == MetaspaceShared::ro ||
idx == MetaspaceShared::rw ||
idx == MetaspaceShared::mc ||
idx == MetaspaceShared::md, "invalid region index");
@@ -1012,19 +1062,21 @@
// Unmap mapped regions of shared space.
void FileMapInfo::stop_sharing_and_unmap(const char* msg) {
FileMapInfo *map_info = FileMapInfo::current_info();
if (map_info) {
map_info->fail_continue("%s", msg);
- for (int i = 0; i < MetaspaceShared::num_non_strings; i++) {
+ for (int i = 0; i < MetaspaceShared::num_non_heap_spaces; i++) {
char *addr = map_info->_header->region_addr(i);
- if (addr != NULL && !MetaspaceShared::is_string_region(i)) {
+ if (addr != NULL && !MetaspaceShared::is_heap_region(i)) {
map_info->unmap_region(i);
map_info->_header->_space[i]._addr._base = NULL;
}
}
- // Dealloc the string regions only without unmapping. The string regions are part
+ // Dealloc the archive heap regions only without unmapping. The regions are part
// of the java heap. Unmapping of the heap regions are managed by GC.
- map_info->dealloc_string_regions();
+ map_info->dealloc_archive_heap_regions(open_archive_heap_ranges,
+ num_open_archive_heap_ranges);
+ map_info->dealloc_archive_heap_regions(string_ranges, num_string_ranges);
} else if (DumpSharedSpaces) {
fail_stop("%s", msg);
}
}
< prev index next >