8255495: Support CDS Archived Heap for uncompressed oops

Reviewed-by: iklam, tschatzl
This commit is contained in:
Calvin Cheung 2022-02-01 19:33:36 +00:00
parent bde2b3783e
commit d95de5c7fe
14 changed files with 367 additions and 62 deletions

View File

@ -266,7 +266,7 @@ void WriteClosure::do_oop(oop* o) {
} else {
assert(HeapShared::can_write(), "sanity");
_dump_region->append_intptr_t(
(intptr_t)CompressedOops::encode_not_null(*o));
UseCompressedOops ? (intptr_t)CompressedOops::encode_not_null(*o) : (intptr_t)((void*)(*o)));
}
}
@ -308,13 +308,23 @@ void ReadClosure::do_tag(int tag) {
}
void ReadClosure::do_oop(oop *p) {
narrowOop o = CompressedOops::narrow_oop_cast(nextPtr());
if (CompressedOops::is_null(o) || !HeapShared::is_fully_available()) {
*p = NULL;
if (UseCompressedOops) {
narrowOop o = CompressedOops::narrow_oop_cast(nextPtr());
if (CompressedOops::is_null(o) || !HeapShared::is_fully_available()) {
*p = NULL;
} else {
assert(HeapShared::can_use(), "sanity");
assert(HeapShared::is_fully_available(), "must be");
*p = HeapShared::decode_from_archive(o);
}
} else {
assert(HeapShared::can_use(), "sanity");
assert(HeapShared::is_fully_available(), "must be");
*p = HeapShared::decode_from_archive(o);
intptr_t dumptime_oop = nextPtr();
if (dumptime_oop == 0 || !HeapShared::is_fully_available()) {
*p = NULL;
} else {
intptr_t runtime_oop = dumptime_oop + HeapShared::runtime_delta();
*p = cast_to_oop(runtime_oop);
}
}
}

View File

@ -245,8 +245,13 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment,
_narrow_oop_mode = CompressedOops::mode();
_narrow_oop_base = CompressedOops::base();
_narrow_oop_shift = CompressedOops::shift();
_heap_begin = CompressedOops::begin();
_heap_end = CompressedOops::end();
if (UseCompressedOops) {
_heap_begin = CompressedOops::begin();
_heap_end = CompressedOops::end();
} else {
_heap_begin = (address)G1CollectedHeap::heap()->reserved().start();
_heap_end = (address)G1CollectedHeap::heap()->reserved().end();
}
}
_compressed_oops = UseCompressedOops;
_compressed_class_ptrs = UseCompressedClassPointers;
@ -316,6 +321,7 @@ void FileMapHeader::print(outputStream* st) {
st->print_cr("- compressed_class_ptrs: %d", _compressed_class_ptrs);
st->print_cr("- cloned_vtables_offset: " SIZE_FORMAT_HEX, _cloned_vtables_offset);
st->print_cr("- serialized_data_offset: " SIZE_FORMAT_HEX, _serialized_data_offset);
st->print_cr("- heap_begin: " INTPTR_FORMAT, p2i(_heap_begin));
st->print_cr("- heap_end: " INTPTR_FORMAT, p2i(_heap_end));
st->print_cr("- jvm_ident: %s", _jvm_ident);
st->print_cr("- shared_path_table_offset: " SIZE_FORMAT_HEX, _shared_path_table_offset);
@ -1491,7 +1497,11 @@ void FileMapInfo::write_region(int region, char* base, size_t size,
} else if (HeapShared::is_heap_region(region)) {
assert(!DynamicDumpSharedSpaces, "must be");
requested_base = base;
mapping_offset = (size_t)CompressedOops::encode_not_null(cast_to_oop(base));
if (UseCompressedOops) {
mapping_offset = (size_t)CompressedOops::encode_not_null(cast_to_oop(base));
} else {
mapping_offset = requested_base - (char*)G1CollectedHeap::heap()->reserved().start();
}
assert(mapping_offset == (size_t)(uint32_t)mapping_offset, "must be 32-bit only");
} else {
char* requested_SharedBaseAddress = (char*)MetaspaceShared::requested_base_address();
@ -2013,7 +2023,10 @@ bool FileMapInfo::can_use_heap_regions() {
log_info(cds)(" narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
CompressedOops::mode(), p2i(CompressedOops::base()), CompressedOops::shift());
log_info(cds)(" heap range = [" PTR_FORMAT " - " PTR_FORMAT "]",
p2i(CompressedOops::begin()), p2i(CompressedOops::end()));
UseCompressedOops ? p2i(CompressedOops::begin()) :
UseG1GC ? p2i((address)G1CollectedHeap::heap()->reserved().start()) : 0L,
UseCompressedOops ? p2i(CompressedOops::end()) :
UseG1GC ? p2i((address)G1CollectedHeap::heap()->reserved().end()) : 0L);
if (narrow_klass_base() != CompressedKlassPointers::base() ||
narrow_klass_shift() != CompressedKlassPointers::shift()) {
@ -2023,6 +2036,26 @@ bool FileMapInfo::can_use_heap_regions() {
return true;
}
// The address where the bottom of this shared heap region should be mapped
// at runtime
address FileMapInfo::heap_region_runtime_start_address(FileMapRegion* spc) {
assert(UseSharedSpaces, "runtime only");
spc->assert_is_heap_region();
if (UseCompressedOops) {
return start_address_as_decoded_from_archive(spc);
} else {
assert(is_aligned(spc->mapping_offset(), sizeof(HeapWord)), "must be");
return header()->heap_begin() + spc->mapping_offset() + HeapShared::runtime_delta();
}
}
void FileMapInfo::set_shared_heap_runtime_delta(ptrdiff_t delta) {
if (UseCompressedOops) {
HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift());
} else {
HeapShared::set_runtime_delta(delta);
}
}
//
// Map the closed and open archive heap objects to the runtime java heap.
@ -2045,39 +2078,66 @@ void FileMapInfo::map_heap_regions_impl() {
log_info(cds)("CDS heap data needs to be relocated because the archive was created with an incompatible oop encoding mode.");
_heap_pointers_need_patching = true;
} else {
MemRegion range = get_heap_regions_range_with_current_oop_encoding_mode();
if (!CompressedOops::is_in(range)) {
log_info(cds)("CDS heap data needs to be relocated because");
log_info(cds)("the desired range " PTR_FORMAT " - " PTR_FORMAT, p2i(range.start()), p2i(range.end()));
log_info(cds)("is outside of the heap " PTR_FORMAT " - " PTR_FORMAT, p2i(CompressedOops::begin()), p2i(CompressedOops::end()));
_heap_pointers_need_patching = true;
} else if (header()->heap_end() != CompressedOops::end()) {
log_info(cds)("CDS heap data needs to be relocated to the end of the runtime heap to reduce fragmentation");
_heap_pointers_need_patching = true;
if (UseCompressedOops) {
MemRegion range = get_heap_regions_range_with_current_oop_encoding_mode();
if (!CompressedOops::is_in(range)) {
log_info(cds)("CDS heap data needs to be relocated because");
log_info(cds)("the desired range " PTR_FORMAT " - " PTR_FORMAT, p2i(range.start()), p2i(range.end()));
log_info(cds)("is outside of the heap " PTR_FORMAT " - " PTR_FORMAT, p2i(CompressedOops::begin()), p2i(CompressedOops::end()));
_heap_pointers_need_patching = true;
} else if (header()->heap_end() != CompressedOops::end()) {
log_info(cds)("CDS heap data needs to be relocated to the end of the runtime heap to reduce fragmentation");
_heap_pointers_need_patching = true;
}
} else {
MemRegion range((HeapWord*)header()->heap_begin(), (HeapWord*)header()->heap_end());
if (!G1CollectedHeap::heap()->reserved().contains(range)) {
log_info(cds)("CDS heap data needs to be relocated because");
log_info(cds)("the desired range " PTR_FORMAT " - " PTR_FORMAT, p2i(range.start()), p2i(range.end()));
log_info(cds)("is outside of the heap " PTR_FORMAT " - " PTR_FORMAT,
p2i((address)G1CollectedHeap::heap()->reserved().start()), p2i((address)G1CollectedHeap::heap()->reserved().end()));
_heap_pointers_need_patching = true;
} else if (header()->heap_end() != (address)G1CollectedHeap::heap()->reserved().end()) {
log_info(cds)("CDS heap data needs to be relocated to the end of the runtime heap to reduce fragmentation");
_heap_pointers_need_patching = true;
}
}
}
ptrdiff_t delta = 0;
if (_heap_pointers_need_patching) {
// dumptime heap end ------------v
// [ |archived heap regions| ] runtime heap end ------v
// [ |archived heap regions| ] run time heap end -----v
// [ |archived heap regions| ]
// ^
// D ^
// R
// |<-----delta-------------------->|
//
// At dump time, the archived heap regions were near the top of the heap.
// At run time, they may not be inside the heap, so we move them so
// that they are now near the top of the runtime time. This can be done by
// At run time, if the heap ends at a different address, we need to
// move them near to top of the run time heap. This can be done by
// the simple math of adding the delta as shown above.
//
// Also: D = bottom of a heap region at dump time
// R = bottom of a heap region at run time
//
// FileMapRegion* spc = ...;
// address D = header()->heap_begin() + spc->mapping_offset();
// address R = D + delta;
address dumptime_heap_end = header()->heap_end();
address runtime_heap_end = CompressedOops::end();
address runtime_heap_end = UseCompressedOops ? CompressedOops::end() :
(address)G1CollectedHeap::heap()->reserved().end();
delta = runtime_heap_end - dumptime_heap_end;
}
log_info(cds)("CDS heap data relocation delta = " INTX_FORMAT " bytes", delta);
HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift());
set_shared_heap_runtime_delta(delta);
FileMapRegion* si = space_at(MetaspaceShared::first_closed_heap_region);
address relocated_closed_heap_region_bottom = start_address_as_decoded_from_archive(si);
address relocated_closed_heap_region_bottom = heap_region_runtime_start_address(si);
if (!is_aligned(relocated_closed_heap_region_bottom, HeapRegion::GrainBytes)) {
// Align the bottom of the closed archive heap regions at G1 region boundary.
// This will avoid the situation where the highest open region and the lowest
@ -2088,9 +2148,9 @@ void FileMapInfo::map_heap_regions_impl() {
log_info(cds)("CDS heap data needs to be relocated lower by a further " SIZE_FORMAT
" bytes to " INTX_FORMAT " to be aligned with HeapRegion::GrainBytes",
align, delta);
HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift());
set_shared_heap_runtime_delta(delta);
relocated_closed_heap_region_bottom = heap_region_runtime_start_address(si);
_heap_pointers_need_patching = true;
relocated_closed_heap_region_bottom = start_address_as_decoded_from_archive(si);
}
assert(is_aligned(relocated_closed_heap_region_bottom, HeapRegion::GrainBytes),
"must be");
@ -2148,7 +2208,7 @@ bool FileMapInfo::map_heap_regions(int first, int max, bool is_open_archive,
si = space_at(i);
size_t size = si->used();
if (size > 0) {
HeapWord* start = (HeapWord*)start_address_as_decoded_from_archive(si);
HeapWord* start = (HeapWord*)heap_region_runtime_start_address(si);
regions[num_regions] = MemRegion(start, size / HeapWordSize);
num_regions ++;
log_info(cds)("Trying to map heap data: region[%d] at " INTPTR_FORMAT ", size = " SIZE_FORMAT_W(8) " bytes",

View File

@ -351,9 +351,8 @@ private:
static bool _memory_mapping_failed;
static GrowableArray<const char*>* _non_existent_class_paths;
FileMapHeader *header() const { return _header; }
public:
FileMapHeader *header() const { return _header; }
static bool get_base_archive_name_from_header(const char* archive_name,
char** base_archive_name);
static SharedPathTable shared_path_table() {
@ -568,6 +567,8 @@ public:
bool can_use_heap_regions();
bool load_heap_regions() NOT_CDS_JAVA_HEAP_RETURN_(false);
bool map_heap_regions() NOT_CDS_JAVA_HEAP_RETURN_(false);
address heap_region_runtime_start_address(FileMapRegion* spc) NOT_CDS_JAVA_HEAP_RETURN_(NULL);
void set_shared_heap_runtime_delta(ptrdiff_t delta) NOT_CDS_JAVA_HEAP_RETURN;
void map_heap_regions_impl() NOT_CDS_JAVA_HEAP_RETURN;
MapArchiveResult map_region(int i, intx addr_delta, char* mapped_base_address, ReservedSpace rs);
bool relocate_pointers_in_core_regions(intx addr_delta);

View File

@ -76,6 +76,7 @@ address HeapShared::_narrow_oop_base;
int HeapShared::_narrow_oop_shift;
DumpedInternedStrings *HeapShared::_dumped_interned_strings = NULL;
// Support for loaded heap.
uintptr_t HeapShared::_loaded_heap_bottom = 0;
uintptr_t HeapShared::_loaded_heap_top = 0;
uintptr_t HeapShared::_dumptime_base_0 = UINTPTR_MAX;
@ -88,6 +89,10 @@ intx HeapShared::_runtime_offset_1 = 0;
intx HeapShared::_runtime_offset_2 = 0;
intx HeapShared::_runtime_offset_3 = 0;
bool HeapShared::_loading_failed = false;
// Suport for mapped heap (!UseCompressedOops only)
ptrdiff_t HeapShared::_runtime_delta = 0;
//
// If you add new entries to the following tables, you should know what you're doing!
//
@ -362,7 +367,10 @@ void HeapShared::archive_objects(GrowableArray<MemRegion>* closed_regions,
create_archived_object_cache();
log_info(cds)("Heap range = [" PTR_FORMAT " - " PTR_FORMAT "]",
p2i(CompressedOops::begin()), p2i(CompressedOops::end()));
UseCompressedOops ? p2i(CompressedOops::begin()) :
p2i((address)G1CollectedHeap::heap()->reserved().start()),
UseCompressedOops ? p2i(CompressedOops::end()) :
p2i((address)G1CollectedHeap::heap()->reserved().end()));
log_info(cds)("Dumping objects to closed archive heap region ...");
copy_closed_objects(closed_regions);
@ -658,7 +666,6 @@ void HeapShared::write_subgraph_info_table() {
CompactHashtableWriter writer(d_table->_count, &stats);
CopyKlassSubGraphInfoToArchive copy(&writer);
d_table->iterate(&copy);
writer.dump(&_run_time_subgraph_info_table, "subgraphs");
}
@ -1400,39 +1407,44 @@ void HeapShared::add_to_dumped_interned_strings(oop string) {
// region. This way we can quickly relocate all the pointers without using
// BasicOopIterateClosure at runtime.
class FindEmbeddedNonNullPointers: public BasicOopIterateClosure {
narrowOop* _start;
void* _start;
BitMap *_oopmap;
int _num_total_oops;
int _num_null_oops;
public:
FindEmbeddedNonNullPointers(narrowOop* start, BitMap* oopmap)
FindEmbeddedNonNullPointers(void* start, BitMap* oopmap)
: _start(start), _oopmap(oopmap), _num_total_oops(0), _num_null_oops(0) {}
virtual void do_oop(narrowOop* p) {
_num_total_oops ++;
narrowOop v = *p;
if (!CompressedOops::is_null(v)) {
size_t idx = p - _start;
size_t idx = p - (narrowOop*)_start;
_oopmap->set_bit(idx);
} else {
_num_null_oops ++;
}
}
virtual void do_oop(oop *p) {
ShouldNotReachHere();
virtual void do_oop(oop* p) {
_num_total_oops ++;
if ((*p) != NULL) {
size_t idx = p - (oop*)_start;
_oopmap->set_bit(idx);
} else {
_num_null_oops ++;
}
}
int num_total_oops() const { return _num_total_oops; }
int num_null_oops() const { return _num_null_oops; }
};
ResourceBitMap HeapShared::calculate_oopmap(MemRegion region) {
assert(UseCompressedOops, "must be");
size_t num_bits = region.byte_size() / sizeof(narrowOop);
size_t num_bits = region.byte_size() / (UseCompressedOops ? sizeof(narrowOop) : sizeof(oop));
ResourceBitMap oopmap(num_bits);
HeapWord* p = region.start();
HeapWord* end = region.end();
FindEmbeddedNonNullPointers finder((narrowOop*)p, &oopmap);
FindEmbeddedNonNullPointers finder((void*)p, &oopmap);
ArchiveBuilder* builder = DumpSharedSpaces ? ArchiveBuilder::current() : NULL;
int num_objs = 0;
@ -1453,11 +1465,11 @@ ResourceBitMap HeapShared::calculate_oopmap(MemRegion region) {
// Patch all the embedded oop pointers inside an archived heap region,
// to be consistent with the runtime oop encoding.
class PatchEmbeddedPointers: public BitMapClosure {
class PatchCompressedEmbeddedPointers: public BitMapClosure {
narrowOop* _start;
public:
PatchEmbeddedPointers(narrowOop* start) : _start(start) {}
PatchCompressedEmbeddedPointers(narrowOop* start) : _start(start) {}
bool do_bit(size_t offset) {
narrowOop* p = _start + offset;
@ -1469,6 +1481,22 @@ class PatchEmbeddedPointers: public BitMapClosure {
}
};
class PatchUncompressedEmbeddedPointers: public BitMapClosure {
oop* _start;
public:
PatchUncompressedEmbeddedPointers(oop* start) : _start(start) {}
bool do_bit(size_t offset) {
oop* p = _start + offset;
intptr_t dumptime_oop = (intptr_t)((void*)*p);
assert(dumptime_oop != 0, "null oops should have been filtered out at dump time");
intptr_t runtime_oop = dumptime_oop + HeapShared::runtime_delta();
RawAccess<IS_NOT_NULL>::oop_store(p, cast_to_oop(runtime_oop));
return true;
}
};
// Patch all the non-null pointers that are embedded in the archived heap objects
// in this region
void HeapShared::patch_embedded_pointers(MemRegion region, address oopmap,
@ -1481,8 +1509,13 @@ void HeapShared::patch_embedded_pointers(MemRegion region, address oopmap,
assert(bm.is_same(checkBm), "sanity");
#endif
PatchEmbeddedPointers patcher((narrowOop*)region.start());
bm.iterate(&patcher);
if (UseCompressedOops) {
PatchCompressedEmbeddedPointers patcher((narrowOop*)region.start());
bm.iterate(&patcher);
} else {
PatchUncompressedEmbeddedPointers patcher((oop*)region.start());
bm.iterate(&patcher);
}
}
// The CDS archive remembers each heap object by its address at dump time, but

View File

@ -159,7 +159,7 @@ public:
if (_disable_writing) {
return false;
}
return (UseG1GC && UseCompressedOops && UseCompressedClassPointers);
return (UseG1GC && UseCompressedClassPointers);
)
NOT_CDS_JAVA_HEAP(return false;)
}
@ -169,7 +169,7 @@ public:
}
// Can this VM map archived heap regions? Currently only G1+compressed{oops,cp}
static bool can_map() {
CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedOops && UseCompressedClassPointers);)
CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedClassPointers);)
NOT_CDS_JAVA_HEAP(return false;)
}
static bool is_mapped() {
@ -297,10 +297,13 @@ private:
static void init_subgraph_entry_fields(ArchivableStaticFieldInfo fields[],
int num, TRAPS);
// Used by decode_from_archive
// UseCompressedOops only: Used by decode_from_archive
static address _narrow_oop_base;
static int _narrow_oop_shift;
// !UseCompressedOops only: used to relocate pointers to the archived objects
static ptrdiff_t _runtime_delta;
typedef ResourceHashtable<oop, bool,
15889, // prime number
ResourceObj::C_HEAP,
@ -418,9 +421,21 @@ private:
// Run-time only
static void clear_root(int index);
static void set_runtime_delta(ptrdiff_t delta) {
assert(!UseCompressedOops, "must be");
_runtime_delta = delta;
}
#endif // INCLUDE_CDS_JAVA_HEAP
public:
static ptrdiff_t runtime_delta() {
assert(!UseCompressedOops, "must be");
CDS_JAVA_HEAP_ONLY(return _runtime_delta;)
NOT_CDS_JAVA_HEAP_RETURN_(0L);
}
static void run_full_gc_in_vm_thread() NOT_CDS_JAVA_HEAP_RETURN;
static bool is_heap_region(int idx) {

View File

@ -65,6 +65,7 @@
#include "oops/oopHandle.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/arguments.hpp"
#include "runtime/globals_extension.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/os.hpp"
#include "runtime/safepointVerifiers.hpp"
@ -709,6 +710,30 @@ void MetaspaceShared::preload_and_dump() {
}
}
#if INCLUDE_CDS_JAVA_HEAP && defined(_LP64)
void MetaspaceShared::adjust_heap_sizes_for_dumping() {
if (!DumpSharedSpaces || UseCompressedOops) {
return;
}
// CDS heap dumping requires all string oops to have an offset
// from the heap bottom that can be encoded in 32-bit.
julong max_heap_size = (julong)(4 * G);
if (MinHeapSize > max_heap_size) {
log_debug(cds)("Setting MinHeapSize to 4G for CDS dumping, original size = " SIZE_FORMAT "M", MinHeapSize/M);
FLAG_SET_ERGO(MinHeapSize, max_heap_size);
}
if (InitialHeapSize > max_heap_size) {
log_debug(cds)("Setting InitialHeapSize to 4G for CDS dumping, original size = " SIZE_FORMAT "M", InitialHeapSize/M);
FLAG_SET_ERGO(InitialHeapSize, max_heap_size);
}
if (MaxHeapSize > max_heap_size) {
log_debug(cds)("Setting MaxHeapSize to 4G for CDS dumping, original size = " SIZE_FORMAT "M", MaxHeapSize/M);
FLAG_SET_ERGO(MaxHeapSize, max_heap_size);
}
}
#endif // INCLUDE_CDS_JAVA_HEAP && _LP64
void MetaspaceShared::preload_classes(TRAPS) {
char default_classlist[JVM_MAXPATHLEN];
const char* classlist_path;
@ -834,11 +859,10 @@ bool MetaspaceShared::try_link_class(JavaThread* current, InstanceKlass* ik) {
void VM_PopulateDumpSharedSpace::dump_java_heap_objects(GrowableArray<Klass*>* klasses) {
if(!HeapShared::can_write()) {
log_info(cds)(
"Archived java heap is not supported as UseG1GC, "
"UseCompressedOops and UseCompressedClassPointers are required."
"Current settings: UseG1GC=%s, UseCompressedOops=%s, UseCompressedClassPointers=%s.",
BOOL_TO_STR(UseG1GC), BOOL_TO_STR(UseCompressedOops),
BOOL_TO_STR(UseCompressedClassPointers));
"Archived java heap is not supported as UseG1GC "
"and UseCompressedClassPointers are required."
"Current settings: UseG1GC=%s, UseCompressedClassPointers=%s.",
BOOL_TO_STR(UseG1GC), BOOL_TO_STR(UseCompressedClassPointers));
return;
}
// Find all the interned strings that should be dumped.

View File

@ -82,6 +82,9 @@ class MetaspaceShared : AllStatic {
static void prepare_for_dumping() NOT_CDS_RETURN;
static void preload_and_dump() NOT_CDS_RETURN;
#ifdef _LP64
static void adjust_heap_sizes_for_dumping() NOT_CDS_JAVA_HEAP_RETURN;
#endif
private:
static void preload_and_dump_impl(TRAPS) NOT_CDS_RETURN;

View File

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "cds/archiveBuilder.hpp"
#include "cds/filemap.hpp"
#include "cds/heapShared.inline.hpp"
#include "classfile/altHashing.hpp"
#include "classfile/compactHashtable.hpp"
@ -55,6 +56,9 @@
#include "utilities/macros.hpp"
#include "utilities/resizeableResourceHash.hpp"
#include "utilities/utf8.hpp"
#if INCLUDE_G1GC
#include "gc/g1/g1CollectedHeap.hpp"
#endif
// We prefer short chains of avg 2
const double PREF_AVG_LIST_LEN = 2.0;
@ -67,9 +71,18 @@ const double CLEAN_DEAD_HIGH_WATER_MARK = 0.5;
#if INCLUDE_CDS_JAVA_HEAP
inline oop read_string_from_compact_hashtable(address base_address, u4 offset) {
assert(sizeof(narrowOop) == sizeof(offset), "must be");
narrowOop v = CompressedOops::narrow_oop_cast(offset);
return HeapShared::decode_from_archive(v);
if (UseCompressedOops) {
assert(sizeof(narrowOop) == sizeof(offset), "must be");
narrowOop v = CompressedOops::narrow_oop_cast(offset);
return HeapShared::decode_from_archive(v);
} else {
intptr_t dumptime_oop = (uintptr_t)offset;
assert(dumptime_oop != 0, "null strings cannot be interned");
intptr_t runtime_oop = dumptime_oop +
(intptr_t)FileMapInfo::current_info()->header()->heap_begin() +
(intptr_t)HeapShared::runtime_delta();
return (oop)cast_to_oop(runtime_oop);
}
}
typedef CompactHashtable<
@ -746,6 +759,16 @@ oop StringTable::create_archived_string(oop s) {
class CopyToArchive : StackObj {
CompactHashtableWriter* _writer;
private:
u4 compute_delta(oop s) {
HeapWord* start = G1CollectedHeap::heap()->reserved().start();
intx offset = ((address)(void*)s) - ((address)(void*)start);
assert(offset >= 0, "must be");
if (offset > 0xffffffff) {
fatal("too large");
}
return (u4)offset;
}
public:
CopyToArchive(CompactHashtableWriter* writer) : _writer(writer) {}
bool do_entry(oop s, bool value_ignored) {
@ -757,7 +780,11 @@ public:
}
// add to the compact table
_writer->add(hash, CompressedOops::narrow_oop_value(new_s));
if (UseCompressedOops) {
_writer->add(hash, CompressedOops::narrow_oop_value(new_s));
} else {
_writer->add(hash, compute_delta(new_s));
}
return true;
}
};
@ -771,7 +798,6 @@ void StringTable::write_to_archive(const DumpedInternedStrings* dumped_interned_
// Copy the interned strings into the "string space" within the java heap
CopyToArchive copier(&writer);
dumped_interned_strings->iterate(&copier);
writer.dump(&_shared_table, "string");
}

View File

@ -132,7 +132,7 @@ public:
bool is_in_reserved(const void* addr) const { return _reserved.contains(addr); }
// Support for loading objects from CDS archive into the heap
virtual bool can_load_archived_objects() const { return true; }
virtual bool can_load_archived_objects() const { return UseCompressedOops; }
virtual HeapWord* allocate_loaded_archive_space(size_t size);
virtual void print_on(outputStream* st) const;

View File

@ -105,7 +105,7 @@ public:
virtual void safepoint_synchronize_end();
// Support for loading objects from CDS archive into the heap
bool can_load_archived_objects() const { return true; }
bool can_load_archived_objects() const { return UseCompressedOops; }
HeapWord* allocate_loaded_archive_space(size_t size);
void complete_loaded_archive_space(MemRegion archive_space);
};

View File

@ -748,6 +748,10 @@ jint universe_init() {
GCLogPrecious::initialize();
#ifdef _LP64
MetaspaceShared::adjust_heap_sizes_for_dumping();
#endif // _LP64
GCConfig::arguments()->initialize_heap_sizes();
jint status = Universe::initialize_heap();

View File

@ -46,6 +46,10 @@ hotspot_gc = \
hotspot_runtime = \
runtime
hotspot_runtime_no_cds = \
runtime \
-runtime/cds
hotspot_handshake = \
runtime/handshake
@ -384,6 +388,8 @@ hotspot_cds = \
runtime/cds/ \
runtime/CompressedOops/
hotspot_cds_only = \
runtime/cds/
hotspot_appcds_dynamic = \
runtime/cds/appcds/ \
@ -405,6 +411,7 @@ hotspot_appcds_dynamic = \
-runtime/cds/appcds/BadBSM.java \
-runtime/cds/appcds/DumpClassList.java \
-runtime/cds/appcds/DumpClassListWithLF.java \
-runtime/cds/appcds/DumpingWithNoCoops.java \
-runtime/cds/appcds/ExtraSymbols.java \
-runtime/cds/appcds/LambdaContainsOldInf.java \
-runtime/cds/appcds/LambdaEagerInit.java \

View File

@ -0,0 +1,120 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @bug 8255495
* @summary Test CDS with UseCompressedOops disable with various heap sizes.
* @requires vm.cds.write.archived.java.heap
* @requires vm.gc.G1
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* @compile test-classes/Hello.java
* @run driver DumpingWithNoCoops
*/
import java.util.ArrayList;
import java.util.List;
import jdk.test.lib.process.OutputAnalyzer;
public class DumpingWithNoCoops {
static class HeapArgs {
int initialSize, minSize, maxSize;
HeapArgs(int initial, int min, int max) {
initialSize = initial;
minSize = min;
maxSize = max;
}
String heapArgsString(HeapArgs ha) {
String heapArgs = "";
if (ha.initialSize > 0) {
heapArgs += "-XX:InitialHeapSize=" + ha.initialSize + "g";
}
if (ha.minSize > 0) {
if (heapArgs.length() > 0) {
heapArgs += " ";
}
heapArgs += "-XX:MinHeapSize=" + ha.minSize + "g";
}
if (ha.maxSize > 0) {
if (heapArgs.length() > 0) {
heapArgs += " ";
}
heapArgs += "-XX:MaxHeapSize=" + ha.maxSize + "g";
}
return heapArgs;
}
}
static HeapArgs[] heapArgsCases = {
// InitialHeapSize, MinHeapSize, MaxHeapSize
// all sizes are in the unit of GB
// size of 0 means don't set the heap size
new HeapArgs( 0, 0, 0),
new HeapArgs( 8, 0, 0),
new HeapArgs( 0, 8, 0),
new HeapArgs( 0, 0, 8),
new HeapArgs( 8, 8, 0),
new HeapArgs( 0, 8, 8),
new HeapArgs( 8, 0, 8),
new HeapArgs( 8, 8, 8),
new HeapArgs( 2, 1, 33),
};
public static void main(String[] args) throws Exception {
final String noCoops = "-XX:-UseCompressedOops";
final String logArg = "-Xlog:gc+heap=trace,cds=debug";
JarBuilder.getOrCreateHelloJar();
String appJar = TestCommon.getTestJar("hello.jar");
String appClasses[] = TestCommon.list("Hello");
for (HeapArgs ha : heapArgsCases) {
String heapArg = ha.heapArgsString(ha);
List<String> dumptimeArgs = new ArrayList<String>();
// UseCompressedOops is ergonomically disabled for MaxHeapSize > 32g.
if (ha.maxSize < 32) {
dumptimeArgs.add(noCoops);
}
dumptimeArgs.add(logArg);
OutputAnalyzer output;
if (heapArg.length() == 0) {
System.out.println("\n Test without heap args\n");
output = TestCommon.dump(appJar, appClasses, dumptimeArgs.toArray(new String[0]));
} else {
System.out.println("\n Test with heap args: " + heapArg + "\n");
String[] heapSizes = heapArg.split(" ");
for (String heapSize : heapSizes) {
dumptimeArgs.add(heapSize);
}
output = TestCommon.dump(appJar, appClasses, dumptimeArgs.toArray(new String[0]));
output.shouldContain("Setting MaxHeapSize to 4G for CDS dumping");
}
TestCommon.checkDump(output);
TestCommon.run("-cp", appJar,
logArg, "-Xlog:class+load", noCoops, "Hello")
.assertNormalExit("Hello source: shared objects file");
}
}
}

View File

@ -62,6 +62,8 @@ public class DifferentHeapSizes {
JarBuilder.getOrCreateHelloJar();
String appJar = TestCommon.getTestJar("hello.jar");
String appClasses[] = TestCommon.list("Hello");
WhiteBox wb = WhiteBox.getWhiteBox();
boolean useCompressedOops = wb.getBooleanVMFlag("UseCompressedOops");
for (Scenario s : scenarios) {
String dumpXmx = "-Xmx" + s.dumpSize + "m";
@ -71,7 +73,7 @@ public class DifferentHeapSizes {
String runXmx = "-Xmx" + runSize + "m";
CDSTestUtils.Result result = TestCommon.run("-cp", appJar, "-showversion",
"-Xlog:cds", runXmx, DEDUP, "Hello");
if (runSize < 32768) {
if (runSize < 32768 || !useCompressedOops) {
result
.assertNormalExit("Hello World")
.assertNormalExit(out -> {
@ -88,7 +90,7 @@ public class DifferentHeapSizes {
// Test various settings of -XX:HeapBaseMinAddress that would trigger
// "CDS heap data need to be relocated because the desired range ... is outside of the heap"
long default_base = WhiteBox.getWhiteBox().getSizeTVMFlag("HeapBaseMinAddress").longValue();
long default_base = wb.getSizeTVMFlag("HeapBaseMinAddress").longValue();
long M = 1024 * 1024;
long bases[] = new long[] {
/* dump xmx */ /* run xmx */ /* dump base */ /* run base */