8293291: Simplify relocation of native pointers in archive heap
Reviewed-by: ccheung, coleenp
This commit is contained in:
parent
1553551d82
commit
3f4964f83d
@ -1166,8 +1166,8 @@ void ArchiveBuilder::clean_up_src_obj_table() {
|
||||
void ArchiveBuilder::write_archive(FileMapInfo* mapinfo,
|
||||
GrowableArray<MemRegion>* closed_heap_regions,
|
||||
GrowableArray<MemRegion>* open_heap_regions,
|
||||
GrowableArray<ArchiveHeapOopmapInfo>* closed_heap_oopmaps,
|
||||
GrowableArray<ArchiveHeapOopmapInfo>* open_heap_oopmaps) {
|
||||
GrowableArray<ArchiveHeapBitmapInfo>* closed_heap_bitmaps,
|
||||
GrowableArray<ArchiveHeapBitmapInfo>* open_heap_bitmaps) {
|
||||
// Make sure NUM_CDS_REGIONS (exported in cds.h) agrees with
|
||||
// MetaspaceShared::n_regions (internal to hotspot).
|
||||
assert(NUM_CDS_REGIONS == MetaspaceShared::n_regions, "sanity");
|
||||
@ -1176,18 +1176,18 @@ void ArchiveBuilder::write_archive(FileMapInfo* mapinfo,
|
||||
write_region(mapinfo, MetaspaceShared::ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
|
||||
|
||||
size_t bitmap_size_in_bytes;
|
||||
char* bitmap = mapinfo->write_bitmap_region(ArchivePtrMarker::ptrmap(), closed_heap_oopmaps, open_heap_oopmaps,
|
||||
char* bitmap = mapinfo->write_bitmap_region(ArchivePtrMarker::ptrmap(), closed_heap_bitmaps, open_heap_bitmaps,
|
||||
bitmap_size_in_bytes);
|
||||
|
||||
if (closed_heap_regions != NULL) {
|
||||
_total_closed_heap_region_size = mapinfo->write_heap_regions(
|
||||
closed_heap_regions,
|
||||
closed_heap_oopmaps,
|
||||
closed_heap_bitmaps,
|
||||
MetaspaceShared::first_closed_heap_region,
|
||||
MetaspaceShared::max_num_closed_heap_regions);
|
||||
_total_open_heap_region_size = mapinfo->write_heap_regions(
|
||||
open_heap_regions,
|
||||
open_heap_oopmaps,
|
||||
open_heap_bitmaps,
|
||||
MetaspaceShared::first_open_heap_region,
|
||||
MetaspaceShared::max_num_open_heap_regions);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "utilities/resizeableResourceHash.hpp"
|
||||
#include "utilities/resourceHash.hpp"
|
||||
|
||||
struct ArchiveHeapOopmapInfo;
|
||||
struct ArchiveHeapBitmapInfo;
|
||||
class CHeapBitMap;
|
||||
class FileMapInfo;
|
||||
class Klass;
|
||||
@ -406,8 +406,8 @@ public:
|
||||
void write_archive(FileMapInfo* mapinfo,
|
||||
GrowableArray<MemRegion>* closed_heap_regions,
|
||||
GrowableArray<MemRegion>* open_heap_regions,
|
||||
GrowableArray<ArchiveHeapOopmapInfo>* closed_heap_oopmaps,
|
||||
GrowableArray<ArchiveHeapOopmapInfo>* open_heap_oopmaps);
|
||||
GrowableArray<ArchiveHeapBitmapInfo>* closed_heap_oopmaps,
|
||||
GrowableArray<ArchiveHeapBitmapInfo>* open_heap_oopmaps);
|
||||
void write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region,
|
||||
bool read_only, bool allow_exec);
|
||||
|
||||
|
@ -72,7 +72,7 @@ void ArchiveHeapLoader::fixup_regions() {
|
||||
if (is_mapped()) {
|
||||
mapinfo->fixup_mapped_heap_regions();
|
||||
} else if (_loading_failed) {
|
||||
fill_failed_loaded_region();
|
||||
fill_failed_loaded_heap();
|
||||
}
|
||||
if (is_fully_available()) {
|
||||
if (!MetaspaceShared::use_full_module_graph()) {
|
||||
@ -80,7 +80,6 @@ void ArchiveHeapLoader::fixup_regions() {
|
||||
ClassLoaderDataShared::clear_archived_oops();
|
||||
}
|
||||
}
|
||||
SystemDictionaryShared::update_archived_mirror_native_pointers();
|
||||
}
|
||||
|
||||
// ------------------ Support for Region MAPPING -----------------------------------------
|
||||
@ -171,7 +170,7 @@ struct LoadedArchiveHeapRegion {
|
||||
};
|
||||
|
||||
void ArchiveHeapLoader::init_loaded_heap_relocation(LoadedArchiveHeapRegion* loaded_regions,
|
||||
int num_loaded_regions) {
|
||||
int num_loaded_regions) {
|
||||
_dumptime_base_0 = loaded_regions[0]._dumptime_base;
|
||||
_dumptime_base_1 = loaded_regions[1]._dumptime_base;
|
||||
_dumptime_base_2 = loaded_regions[2]._dumptime_base;
|
||||
@ -314,7 +313,7 @@ bool ArchiveHeapLoader::load_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegi
|
||||
|
||||
if (!mapinfo->read_region(ri->_region_index, (char*)load_address, r->used(), /* do_commit = */ false)) {
|
||||
// There's no easy way to free the buffer, so we will fill it with zero later
|
||||
// in fill_failed_loaded_region(), and it will eventually be GC'ed.
|
||||
// in fill_failed_loaded_heap(), and it will eventually be GC'ed.
|
||||
log_warning(cds)("Loading of heap region %d has failed. Archived objects are disabled", i);
|
||||
_loading_failed = true;
|
||||
return false;
|
||||
@ -339,6 +338,7 @@ bool ArchiveHeapLoader::load_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegi
|
||||
bm.iterate(&patcher);
|
||||
}
|
||||
|
||||
r->set_mapped_base((char*)load_address);
|
||||
load_address += r->used();
|
||||
}
|
||||
|
||||
@ -392,17 +392,24 @@ class VerifyLoadedHeapEmbeddedPointers: public BasicOopIterateClosure {
|
||||
|
||||
void ArchiveHeapLoader::finish_initialization() {
|
||||
if (is_loaded()) {
|
||||
HeapWord* bottom = (HeapWord*)_loaded_heap_bottom;
|
||||
HeapWord* top = (HeapWord*)_loaded_heap_top;
|
||||
|
||||
MemRegion archive_space = MemRegion(bottom, top);
|
||||
Universe::heap()->complete_loaded_archive_space(archive_space);
|
||||
// These operations are needed only when the heap is loaded (not mapped).
|
||||
finish_loaded_heap();
|
||||
if (VerifyArchivedFields > 0) {
|
||||
verify_loaded_heap();
|
||||
}
|
||||
}
|
||||
patch_native_pointers();
|
||||
}
|
||||
|
||||
if (VerifyArchivedFields <= 0 || !is_loaded()) {
|
||||
return;
|
||||
}
|
||||
void ArchiveHeapLoader::finish_loaded_heap() {
|
||||
HeapWord* bottom = (HeapWord*)_loaded_heap_bottom;
|
||||
HeapWord* top = (HeapWord*)_loaded_heap_top;
|
||||
|
||||
MemRegion archive_space = MemRegion(bottom, top);
|
||||
Universe::heap()->complete_loaded_archive_space(archive_space);
|
||||
}
|
||||
|
||||
void ArchiveHeapLoader::verify_loaded_heap() {
|
||||
log_info(cds, heap)("Verify all oops and pointers in loaded heap");
|
||||
|
||||
ResourceMark rm;
|
||||
@ -424,7 +431,7 @@ void ArchiveHeapLoader::finish_initialization() {
|
||||
}
|
||||
}
|
||||
|
||||
void ArchiveHeapLoader::fill_failed_loaded_region() {
|
||||
void ArchiveHeapLoader::fill_failed_loaded_heap() {
|
||||
assert(_loading_failed, "must be");
|
||||
if (_loaded_heap_bottom != 0) {
|
||||
assert(_loaded_heap_top != 0, "must be");
|
||||
@ -434,4 +441,37 @@ void ArchiveHeapLoader::fill_failed_loaded_region() {
|
||||
}
|
||||
}
|
||||
|
||||
class PatchNativePointers: public BitMapClosure {
|
||||
Metadata** _start;
|
||||
|
||||
public:
|
||||
PatchNativePointers(Metadata** start) : _start(start) {}
|
||||
|
||||
bool do_bit(size_t offset) {
|
||||
Metadata** p = _start + offset;
|
||||
*p = (Metadata*)(address(*p) + MetaspaceShared::relocation_delta());
|
||||
// Currently we have only Klass pointers in heap objects.
|
||||
// This needs to be relaxed when we support other types of native
|
||||
// pointers such as Method.
|
||||
assert(((Klass*)(*p))->is_klass(), "must be");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void ArchiveHeapLoader::patch_native_pointers() {
|
||||
if (MetaspaceShared::relocation_delta() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = MetaspaceShared::first_archive_heap_region;
|
||||
i <= MetaspaceShared::last_archive_heap_region; i++) {
|
||||
FileMapRegion* r = FileMapInfo::current_info()->space_at(i);
|
||||
if (r->mapped_base() != NULL && r->has_ptrmap()) {
|
||||
log_info(cds, heap)("Patching native pointers in heap region %d", i);
|
||||
BitMapView bm = r->ptrmap_view();
|
||||
PatchNativePointers patcher((Metadata**)r->mapped_base());
|
||||
bm.iterate(&patcher);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // INCLUDE_CDS_JAVA_HEAP
|
||||
|
@ -146,7 +146,10 @@ private:
|
||||
int num_loaded_regions, uintptr_t buffer);
|
||||
static void init_loaded_heap_relocation(LoadedArchiveHeapRegion* reloc_info,
|
||||
int num_loaded_regions);
|
||||
static void fill_failed_loaded_region();
|
||||
static void patch_native_pointers();
|
||||
static void finish_loaded_heap();
|
||||
static void verify_loaded_heap();
|
||||
static void fill_failed_loaded_heap();
|
||||
|
||||
static bool is_in_loaded_heap(uintptr_t o) {
|
||||
return (_loaded_heap_bottom <= o && o < _loaded_heap_top);
|
||||
|
@ -1492,6 +1492,29 @@ void FileMapRegion::init(int region_index, size_t mapping_offset, size_t size, b
|
||||
_mapped_base = NULL;
|
||||
}
|
||||
|
||||
void FileMapRegion::init_bitmaps(ArchiveHeapBitmapInfo oopmap, ArchiveHeapBitmapInfo ptrmap) {
|
||||
_oopmap_offset = oopmap._bm_region_offset;
|
||||
_oopmap_size_in_bits = oopmap._size_in_bits;
|
||||
|
||||
_ptrmap_offset = ptrmap._bm_region_offset;
|
||||
_ptrmap_size_in_bits = ptrmap._size_in_bits;
|
||||
}
|
||||
|
||||
BitMapView FileMapRegion::bitmap_view(bool is_oopmap) {
|
||||
char* bitmap_base = FileMapInfo::current_info()->map_bitmap_region();
|
||||
bitmap_base += is_oopmap ? _oopmap_offset : _ptrmap_offset;
|
||||
size_t size_in_bits = is_oopmap ? _oopmap_size_in_bits : _ptrmap_size_in_bits;
|
||||
return BitMapView((BitMap::bm_word_t*)(bitmap_base), size_in_bits);
|
||||
}
|
||||
|
||||
BitMapView FileMapRegion::oopmap_view() {
|
||||
return bitmap_view(true);
|
||||
}
|
||||
|
||||
BitMapView FileMapRegion::ptrmap_view() {
|
||||
assert(has_ptrmap(), "must be");
|
||||
return bitmap_view(false);
|
||||
}
|
||||
|
||||
static const char* region_name(int region_index) {
|
||||
static const char* names[] = {
|
||||
@ -1566,41 +1589,41 @@ void FileMapInfo::write_region(int region, char* base, size_t size,
|
||||
}
|
||||
}
|
||||
|
||||
size_t FileMapInfo::set_oopmaps_offset(GrowableArray<ArchiveHeapOopmapInfo>* oopmaps, size_t curr_size) {
|
||||
for (int i = 0; i < oopmaps->length(); i++) {
|
||||
oopmaps->at(i)._offset = curr_size;
|
||||
curr_size += oopmaps->at(i)._oopmap_size_in_bytes;
|
||||
size_t FileMapInfo::set_bitmaps_offset(GrowableArray<ArchiveHeapBitmapInfo>* bitmaps, size_t curr_size) {
|
||||
for (int i = 0; i < bitmaps->length(); i++) {
|
||||
bitmaps->at(i)._bm_region_offset = curr_size;
|
||||
curr_size += bitmaps->at(i)._size_in_bytes;
|
||||
}
|
||||
return curr_size;
|
||||
}
|
||||
|
||||
size_t FileMapInfo::write_oopmaps(GrowableArray<ArchiveHeapOopmapInfo>* oopmaps, size_t curr_offset, char* buffer) {
|
||||
for (int i = 0; i < oopmaps->length(); i++) {
|
||||
memcpy(buffer + curr_offset, oopmaps->at(i)._oopmap, oopmaps->at(i)._oopmap_size_in_bytes);
|
||||
curr_offset += oopmaps->at(i)._oopmap_size_in_bytes;
|
||||
size_t FileMapInfo::write_bitmaps(GrowableArray<ArchiveHeapBitmapInfo>* bitmaps, size_t curr_offset, char* buffer) {
|
||||
for (int i = 0; i < bitmaps->length(); i++) {
|
||||
memcpy(buffer + curr_offset, bitmaps->at(i)._map, bitmaps->at(i)._size_in_bytes);
|
||||
curr_offset += bitmaps->at(i)._size_in_bytes;
|
||||
}
|
||||
return curr_offset;
|
||||
}
|
||||
|
||||
char* FileMapInfo::write_bitmap_region(const CHeapBitMap* ptrmap,
|
||||
GrowableArray<ArchiveHeapOopmapInfo>* closed_oopmaps,
|
||||
GrowableArray<ArchiveHeapOopmapInfo>* open_oopmaps,
|
||||
GrowableArray<ArchiveHeapBitmapInfo>* closed_bitmaps,
|
||||
GrowableArray<ArchiveHeapBitmapInfo>* open_bitmaps,
|
||||
size_t &size_in_bytes) {
|
||||
size_t size_in_bits = ptrmap->size();
|
||||
size_in_bytes = ptrmap->size_in_bytes();
|
||||
|
||||
if (closed_oopmaps != NULL && open_oopmaps != NULL) {
|
||||
size_in_bytes = set_oopmaps_offset(closed_oopmaps, size_in_bytes);
|
||||
size_in_bytes = set_oopmaps_offset(open_oopmaps, size_in_bytes);
|
||||
if (closed_bitmaps != NULL && open_bitmaps != NULL) {
|
||||
size_in_bytes = set_bitmaps_offset(closed_bitmaps, size_in_bytes);
|
||||
size_in_bytes = set_bitmaps_offset(open_bitmaps, size_in_bytes);
|
||||
}
|
||||
|
||||
char* buffer = NEW_C_HEAP_ARRAY(char, size_in_bytes, mtClassShared);
|
||||
ptrmap->write_to((BitMap::bm_word_t*)buffer, ptrmap->size_in_bytes());
|
||||
header()->set_ptrmap_size_in_bits(size_in_bits);
|
||||
|
||||
if (closed_oopmaps != NULL && open_oopmaps != NULL) {
|
||||
size_t curr_offset = write_oopmaps(closed_oopmaps, ptrmap->size_in_bytes(), buffer);
|
||||
write_oopmaps(open_oopmaps, curr_offset, buffer);
|
||||
if (closed_bitmaps != NULL && open_bitmaps != NULL) {
|
||||
size_t curr_offset = write_bitmaps(closed_bitmaps, ptrmap->size_in_bytes(), buffer);
|
||||
write_bitmaps(open_bitmaps, curr_offset, buffer);
|
||||
}
|
||||
|
||||
write_region(MetaspaceShared::bm, (char*)buffer, size_in_bytes, /*read_only=*/true, /*allow_exec=*/false);
|
||||
@ -1639,7 +1662,7 @@ char* FileMapInfo::write_bitmap_region(const CHeapBitMap* ptrmap,
|
||||
// |
|
||||
// +-- gap
|
||||
size_t FileMapInfo::write_heap_regions(GrowableArray<MemRegion>* regions,
|
||||
GrowableArray<ArchiveHeapOopmapInfo>* oopmaps,
|
||||
GrowableArray<ArchiveHeapBitmapInfo>* bitmaps,
|
||||
int first_region_id, int max_num_regions) {
|
||||
assert(max_num_regions <= 2, "Only support maximum 2 memory regions");
|
||||
|
||||
@ -1665,8 +1688,10 @@ size_t FileMapInfo::write_heap_regions(GrowableArray<MemRegion>* regions,
|
||||
int region_idx = i + first_region_id;
|
||||
write_region(region_idx, start, size, false, false);
|
||||
if (size > 0) {
|
||||
space_at(region_idx)->init_oopmap(oopmaps->at(i)._offset,
|
||||
oopmaps->at(i)._oopmap_size_in_bits);
|
||||
int oopmap_idx = i * 2;
|
||||
int ptrmap_idx = i * 2 + 1;
|
||||
space_at(region_idx)->init_bitmaps(bitmaps->at(oopmap_idx),
|
||||
bitmaps->at(ptrmap_idx));
|
||||
}
|
||||
}
|
||||
return total_size;
|
||||
@ -2307,6 +2332,8 @@ bool FileMapInfo::map_heap_regions(int first, int max, bool is_open_archive,
|
||||
log_info(cds)("UseSharedSpaces: mapped heap regions are corrupt");
|
||||
return false;
|
||||
}
|
||||
|
||||
si->set_mapped_base(base);
|
||||
}
|
||||
|
||||
cleanup._aborted = false;
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
static const int JVM_IDENT_MAX = 256;
|
||||
|
||||
class BitMapView;
|
||||
class CHeapBitMap;
|
||||
class ClassFileStream;
|
||||
class ClassLoaderData;
|
||||
@ -102,11 +103,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct ArchiveHeapOopmapInfo {
|
||||
address _oopmap; // bitmap for relocating embedded oops
|
||||
size_t _offset; // this oopmap is stored at this offset from the bottom of the BM region
|
||||
size_t _oopmap_size_in_bits;
|
||||
size_t _oopmap_size_in_bytes;
|
||||
struct ArchiveHeapBitmapInfo {
|
||||
address _map; // bitmap for relocating embedded oops
|
||||
size_t _bm_region_offset; // this bitmap is stored at this offset from the bottom of the BM region
|
||||
size_t _size_in_bits;
|
||||
size_t _size_in_bytes;
|
||||
};
|
||||
|
||||
class SharedPathTable {
|
||||
@ -137,6 +138,7 @@ public:
|
||||
|
||||
|
||||
class FileMapRegion: private CDSFileMapRegion {
|
||||
BitMapView bitmap_view(bool is_oopmap);
|
||||
public:
|
||||
void assert_is_heap_region() const {
|
||||
assert(_is_heap_region, "must be heap region");
|
||||
@ -156,7 +158,7 @@ public:
|
||||
size_t mapping_end_offset() const { return _mapping_offset + used_aligned(); }
|
||||
size_t used() const { return _used; }
|
||||
size_t used_aligned() const; // aligned up to MetaspaceShared::core_region_alignment()
|
||||
char* mapped_base() const { assert_is_not_heap_region(); return _mapped_base; }
|
||||
char* mapped_base() const { return _mapped_base; }
|
||||
char* mapped_end() const { return mapped_base() + used_aligned(); }
|
||||
bool read_only() const { return _read_only != 0; }
|
||||
bool allow_exec() const { return _allow_exec != 0; }
|
||||
@ -170,11 +172,10 @@ public:
|
||||
void set_mapped_from_file(bool v) { _mapped_from_file = v; }
|
||||
void init(int region_index, size_t mapping_offset, size_t size, bool read_only,
|
||||
bool allow_exec, int crc);
|
||||
|
||||
void init_oopmap(size_t oopmap_offset, size_t size_in_bits) {
|
||||
_oopmap_offset = oopmap_offset;
|
||||
_oopmap_size_in_bits = size_in_bits;
|
||||
}
|
||||
void init_bitmaps(ArchiveHeapBitmapInfo oopmap, ArchiveHeapBitmapInfo ptrmap);
|
||||
BitMapView oopmap_view();
|
||||
BitMapView ptrmap_view();
|
||||
bool has_ptrmap() { return _ptrmap_size_in_bits != 0; }
|
||||
|
||||
void print(outputStream* st, int region_index);
|
||||
};
|
||||
@ -444,11 +445,11 @@ public:
|
||||
void write_region(int region, char* base, size_t size,
|
||||
bool read_only, bool allow_exec);
|
||||
char* write_bitmap_region(const CHeapBitMap* ptrmap,
|
||||
GrowableArray<ArchiveHeapOopmapInfo>* closed_oopmaps,
|
||||
GrowableArray<ArchiveHeapOopmapInfo>* open_oopmaps,
|
||||
GrowableArray<ArchiveHeapBitmapInfo>* closed_bitmaps,
|
||||
GrowableArray<ArchiveHeapBitmapInfo>* open_bitmaps,
|
||||
size_t &size_in_bytes);
|
||||
size_t write_heap_regions(GrowableArray<MemRegion>* regions,
|
||||
GrowableArray<ArchiveHeapOopmapInfo>* oopmaps,
|
||||
GrowableArray<ArchiveHeapBitmapInfo>* bitmaps,
|
||||
int first_region_id, int max_num_regions);
|
||||
void write_bytes(const void* buffer, size_t count);
|
||||
void write_bytes_aligned(const void* buffer, size_t count);
|
||||
@ -573,8 +574,8 @@ public:
|
||||
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);
|
||||
static size_t set_oopmaps_offset(GrowableArray<ArchiveHeapOopmapInfo> *oopmaps, size_t curr_size);
|
||||
static size_t write_oopmaps(GrowableArray<ArchiveHeapOopmapInfo> *oopmaps, size_t curr_offset, char* buffer);
|
||||
static size_t set_bitmaps_offset(GrowableArray<ArchiveHeapBitmapInfo> *bitmaps, size_t curr_size);
|
||||
static size_t write_bitmaps(GrowableArray<ArchiveHeapBitmapInfo> *bitmaps, size_t curr_offset, char* buffer);
|
||||
|
||||
address decode_start_address(FileMapRegion* spc, bool with_current_oop_encoding_mode);
|
||||
|
||||
|
@ -82,6 +82,7 @@ struct ArchivableStaticFieldInfo {
|
||||
|
||||
bool HeapShared::_disable_writing = false;
|
||||
DumpedInternedStrings *HeapShared::_dumped_interned_strings = NULL;
|
||||
GrowableArrayCHeap<Metadata**, mtClassShared>* HeapShared::_native_pointers = NULL;
|
||||
|
||||
#ifndef PRODUCT
|
||||
#define ARCHIVE_TEST_FIELD_NAME "archivedObjects"
|
||||
@ -320,6 +321,7 @@ oop HeapShared::archive_object(oop obj) {
|
||||
if (_original_object_table != NULL) {
|
||||
_original_object_table->put(archived_oop, obj);
|
||||
}
|
||||
mark_native_pointers(obj, archived_oop);
|
||||
if (log_is_enabled(Debug, cds, heap)) {
|
||||
ResourceMark rm;
|
||||
log_debug(cds, heap)("Archived heap object " PTR_FORMAT " ==> " PTR_FORMAT " : %s",
|
||||
@ -353,6 +355,32 @@ void HeapShared::archive_klass_objects() {
|
||||
}
|
||||
}
|
||||
|
||||
void HeapShared::mark_native_pointers(oop orig_obj, oop archived_obj) {
|
||||
if (java_lang_Class::is_instance(orig_obj)) {
|
||||
mark_one_native_pointer(archived_obj, java_lang_Class::klass_offset());
|
||||
mark_one_native_pointer(archived_obj, java_lang_Class::array_klass_offset());
|
||||
}
|
||||
}
|
||||
|
||||
void HeapShared::mark_one_native_pointer(oop archived_obj, int offset) {
|
||||
Metadata* ptr = archived_obj->metadata_field_acquire(offset);
|
||||
if (ptr != NULL) {
|
||||
// Set the native pointer to the requested address (at runtime, if the metadata
|
||||
// is mapped at the default location, it will be at this address).
|
||||
address buffer_addr = ArchiveBuilder::current()->get_buffered_addr((address)ptr);
|
||||
address requested_addr = ArchiveBuilder::current()->to_requested(buffer_addr);
|
||||
archived_obj->metadata_field_put(offset, (Metadata*)requested_addr);
|
||||
|
||||
// Remember this pointer. At runtime, if the metadata is mapped at a non-default
|
||||
// location, the pointer needs to be patched (see ArchiveHeapLoader::patch_native_pointers()).
|
||||
_native_pointers->append(archived_obj->field_addr<Metadata*>(offset));
|
||||
|
||||
log_debug(cds, heap, mirror)(
|
||||
"Marked metadata field at %d: " PTR_FORMAT " ==> " PTR_FORMAT,
|
||||
offset, p2i(ptr), p2i(requested_addr));
|
||||
}
|
||||
}
|
||||
|
||||
// -- Handling of Enum objects
|
||||
// Java Enum classes have synthetic <clinit> methods that look like this
|
||||
// enum MyEnum {FOO, BAR}
|
||||
@ -1632,6 +1660,7 @@ void HeapShared::init_for_dumping(TRAPS) {
|
||||
if (HeapShared::can_write()) {
|
||||
setup_test_class(ArchiveHeapTestClass);
|
||||
_dumped_interned_strings = new (ResourceObj::C_HEAP, mtClass)DumpedInternedStrings();
|
||||
_native_pointers = new GrowableArrayCHeap<Metadata**, mtClassShared>(2048);
|
||||
init_subgraph_entry_fields(CHECK);
|
||||
}
|
||||
}
|
||||
@ -1797,4 +1826,33 @@ ResourceBitMap HeapShared::calculate_oopmap(MemRegion region) {
|
||||
return oopmap;
|
||||
}
|
||||
|
||||
|
||||
ResourceBitMap HeapShared::calculate_ptrmap(MemRegion region) {
|
||||
size_t num_bits = region.byte_size() / sizeof(Metadata*);
|
||||
ResourceBitMap oopmap(num_bits);
|
||||
|
||||
Metadata** start = (Metadata**)region.start();
|
||||
Metadata** end = (Metadata**)region.end();
|
||||
|
||||
int num_non_null_ptrs = 0;
|
||||
int len = _native_pointers->length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Metadata** p = _native_pointers->at(i);
|
||||
if (start <= p && p < end) {
|
||||
assert(*p != NULL, "must be non-null");
|
||||
num_non_null_ptrs ++;
|
||||
size_t idx = p - start;
|
||||
oopmap.set_bit(idx);
|
||||
}
|
||||
}
|
||||
|
||||
log_info(cds, heap)("calculate_ptrmap: marked %d non-null native pointers out of "
|
||||
SIZE_FORMAT " possible locations", num_non_null_ptrs, num_bits);
|
||||
if (num_non_null_ptrs > 0) {
|
||||
return oopmap;
|
||||
} else {
|
||||
return ResourceBitMap(0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // INCLUDE_CDS_JAVA_HEAP
|
||||
|
@ -160,6 +160,7 @@ private:
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
static bool _disable_writing;
|
||||
static DumpedInternedStrings *_dumped_interned_strings;
|
||||
static GrowableArrayCHeap<Metadata**, mtClassShared>* _native_pointers;
|
||||
|
||||
public:
|
||||
static unsigned oop_hash(oop const& p);
|
||||
@ -311,6 +312,8 @@ private:
|
||||
static void init_loaded_heap_relocation(LoadedArchiveHeapRegion* reloc_info,
|
||||
int num_loaded_regions);
|
||||
static void fill_failed_loaded_region();
|
||||
static void mark_native_pointers(oop orig_obj, oop archived_obj);
|
||||
static void mark_one_native_pointer(oop archived_obj, int offset);
|
||||
public:
|
||||
static void reset_archived_object_states(TRAPS);
|
||||
static void create_archived_object_cache(bool create_orig_table) {
|
||||
@ -359,7 +362,8 @@ private:
|
||||
oop orig_obj,
|
||||
bool is_closed_archive);
|
||||
|
||||
static ResourceBitMap calculate_oopmap(MemRegion region);
|
||||
static ResourceBitMap calculate_oopmap(MemRegion region); // marks all the oop pointers
|
||||
static ResourceBitMap calculate_ptrmap(MemRegion region); // marks all the native pointers
|
||||
static void add_to_dumped_interned_strings(oop string);
|
||||
|
||||
// We use the HeapShared::roots() array to make sure that objects stored in the
|
||||
|
@ -438,13 +438,15 @@ private:
|
||||
GrowableArray<MemRegion> *_closed_heap_regions;
|
||||
GrowableArray<MemRegion> *_open_heap_regions;
|
||||
|
||||
GrowableArray<ArchiveHeapOopmapInfo> *_closed_heap_oopmaps;
|
||||
GrowableArray<ArchiveHeapOopmapInfo> *_open_heap_oopmaps;
|
||||
GrowableArray<ArchiveHeapBitmapInfo> *_closed_heap_bitmaps;
|
||||
GrowableArray<ArchiveHeapBitmapInfo> *_open_heap_bitmaps;
|
||||
|
||||
void dump_java_heap_objects(GrowableArray<Klass*>* klasses) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
void dump_heap_oopmaps() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
void dump_heap_oopmaps(GrowableArray<MemRegion>* regions,
|
||||
GrowableArray<ArchiveHeapOopmapInfo>* oopmaps);
|
||||
void dump_heap_bitmaps() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
void dump_heap_bitmaps(GrowableArray<MemRegion>* regions,
|
||||
GrowableArray<ArchiveHeapBitmapInfo>* bitmaps);
|
||||
void dump_one_heap_bitmap(MemRegion region, GrowableArray<ArchiveHeapBitmapInfo>* bitmaps,
|
||||
ResourceBitMap bitmap, bool is_oopmap);
|
||||
void dump_shared_symbol_table(GrowableArray<Symbol*>* symbols) {
|
||||
log_info(cds)("Dumping symbol table ...");
|
||||
SymbolTable::write_to_archive(symbols);
|
||||
@ -457,8 +459,8 @@ public:
|
||||
VM_GC_Operation(0 /* total collections, ignored */, GCCause::_archive_time_gc),
|
||||
_closed_heap_regions(NULL),
|
||||
_open_heap_regions(NULL),
|
||||
_closed_heap_oopmaps(NULL),
|
||||
_open_heap_oopmaps(NULL) {}
|
||||
_closed_heap_bitmaps(NULL),
|
||||
_open_heap_bitmaps(NULL) {}
|
||||
|
||||
bool skip_operation() const { return false; }
|
||||
|
||||
@ -504,7 +506,7 @@ char* VM_PopulateDumpSharedSpace::dump_read_only_tables() {
|
||||
MetaspaceShared::serialize(&wc);
|
||||
|
||||
// Write the bitmaps for patching the archive heap regions
|
||||
dump_heap_oopmaps();
|
||||
dump_heap_bitmaps();
|
||||
|
||||
return start;
|
||||
}
|
||||
@ -566,8 +568,8 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||
builder.write_archive(mapinfo,
|
||||
_closed_heap_regions,
|
||||
_open_heap_regions,
|
||||
_closed_heap_oopmaps,
|
||||
_open_heap_oopmaps);
|
||||
_closed_heap_bitmaps,
|
||||
_open_heap_bitmaps);
|
||||
|
||||
if (PrintSystemDictionaryAtExit) {
|
||||
SystemDictionary::print();
|
||||
@ -899,36 +901,55 @@ void VM_PopulateDumpSharedSpace::dump_java_heap_objects(GrowableArray<Klass*>* k
|
||||
HeapShared::write_subgraph_info_table();
|
||||
}
|
||||
|
||||
void VM_PopulateDumpSharedSpace::dump_heap_oopmaps() {
|
||||
void VM_PopulateDumpSharedSpace::dump_heap_bitmaps() {
|
||||
if (HeapShared::can_write()) {
|
||||
_closed_heap_oopmaps = new GrowableArray<ArchiveHeapOopmapInfo>(2);
|
||||
dump_heap_oopmaps(_closed_heap_regions, _closed_heap_oopmaps);
|
||||
_closed_heap_bitmaps = new GrowableArray<ArchiveHeapBitmapInfo>(2);
|
||||
dump_heap_bitmaps(_closed_heap_regions, _closed_heap_bitmaps);
|
||||
|
||||
_open_heap_oopmaps = new GrowableArray<ArchiveHeapOopmapInfo>(2);
|
||||
dump_heap_oopmaps(_open_heap_regions, _open_heap_oopmaps);
|
||||
_open_heap_bitmaps = new GrowableArray<ArchiveHeapBitmapInfo>(2);
|
||||
dump_heap_bitmaps(_open_heap_regions, _open_heap_bitmaps);
|
||||
}
|
||||
}
|
||||
|
||||
void VM_PopulateDumpSharedSpace::dump_heap_oopmaps(GrowableArray<MemRegion>* regions,
|
||||
GrowableArray<ArchiveHeapOopmapInfo>* oopmaps) {
|
||||
for (int i=0; i<regions->length(); i++) {
|
||||
ResourceBitMap oopmap = HeapShared::calculate_oopmap(regions->at(i));
|
||||
size_t size_in_bits = oopmap.size();
|
||||
size_t size_in_bytes = oopmap.size_in_bytes();
|
||||
uintptr_t* buffer = (uintptr_t*)NEW_C_HEAP_ARRAY(char, size_in_bytes, mtInternal);
|
||||
oopmap.write_to(buffer, size_in_bytes);
|
||||
log_info(cds, heap)("Oopmap = " INTPTR_FORMAT " (" SIZE_FORMAT_W(6) " bytes) for heap region "
|
||||
INTPTR_FORMAT " (" SIZE_FORMAT_W(8) " bytes)",
|
||||
p2i(buffer), size_in_bytes,
|
||||
p2i(regions->at(i).start()), regions->at(i).byte_size());
|
||||
|
||||
ArchiveHeapOopmapInfo info;
|
||||
info._oopmap = (address)buffer;
|
||||
info._oopmap_size_in_bits = size_in_bits;
|
||||
info._oopmap_size_in_bytes = size_in_bytes;
|
||||
oopmaps->append(info);
|
||||
void VM_PopulateDumpSharedSpace::dump_heap_bitmaps(GrowableArray<MemRegion>* regions,
|
||||
GrowableArray<ArchiveHeapBitmapInfo>* bitmaps) {
|
||||
for (int i = 0; i < regions->length(); i++) {
|
||||
MemRegion region = regions->at(i);
|
||||
ResourceBitMap oopmap = HeapShared::calculate_oopmap(region);
|
||||
ResourceBitMap ptrmap = HeapShared::calculate_ptrmap(region);
|
||||
dump_one_heap_bitmap(region, bitmaps, oopmap, true);
|
||||
dump_one_heap_bitmap(region, bitmaps, ptrmap, false);
|
||||
}
|
||||
}
|
||||
|
||||
void VM_PopulateDumpSharedSpace::dump_one_heap_bitmap(MemRegion region,
|
||||
GrowableArray<ArchiveHeapBitmapInfo>* bitmaps,
|
||||
ResourceBitMap bitmap, bool is_oopmap) {
|
||||
size_t size_in_bits = bitmap.size();
|
||||
size_t size_in_bytes;
|
||||
uintptr_t* buffer;
|
||||
|
||||
if (size_in_bits > 0) {
|
||||
size_in_bytes = bitmap.size_in_bytes();
|
||||
buffer = (uintptr_t*)NEW_C_HEAP_ARRAY(char, size_in_bytes, mtInternal);
|
||||
bitmap.write_to(buffer, size_in_bytes);
|
||||
} else {
|
||||
size_in_bytes = 0;
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
log_info(cds, heap)("%s = " INTPTR_FORMAT " (" SIZE_FORMAT_W(6) " bytes) for heap region "
|
||||
INTPTR_FORMAT " (" SIZE_FORMAT_W(8) " bytes)",
|
||||
is_oopmap ? "Oopmap" : "Ptrmap",
|
||||
p2i(buffer), size_in_bytes,
|
||||
p2i(region.start()), region.byte_size());
|
||||
|
||||
ArchiveHeapBitmapInfo info;
|
||||
info._map = (address)buffer;
|
||||
info._size_in_bits = size_in_bits;
|
||||
info._size_in_bytes = size_in_bytes;
|
||||
bitmaps->append(info);
|
||||
}
|
||||
#endif // INCLUDE_CDS_JAVA_HEAP
|
||||
|
||||
void MetaspaceShared::set_shared_metaspace_range(void* base, void *static_top, void* top) {
|
||||
|
@ -1117,21 +1117,6 @@ class ResetMirrorField: public FieldClosure {
|
||||
}
|
||||
};
|
||||
|
||||
static void set_klass_field_in_archived_mirror(oop mirror_obj, int offset, Klass* k) {
|
||||
assert(java_lang_Class::is_instance(mirror_obj), "must be");
|
||||
// this is the copy of k in the output buffer
|
||||
Klass* copy = ArchiveBuilder::get_buffered_klass(k);
|
||||
|
||||
// This is the address of k, if the archive is loaded at the requested location
|
||||
Klass* def = ArchiveBuilder::current()->to_requested(copy);
|
||||
|
||||
log_debug(cds, heap, mirror)(
|
||||
"Relocate mirror metadata field at %d from " PTR_FORMAT " ==> " PTR_FORMAT,
|
||||
offset, p2i(k), p2i(def));
|
||||
|
||||
mirror_obj->metadata_field_put(offset, def);
|
||||
}
|
||||
|
||||
void java_lang_Class::archive_basic_type_mirrors() {
|
||||
assert(HeapShared::can_write(), "must be");
|
||||
|
||||
@ -1142,11 +1127,6 @@ void java_lang_Class::archive_basic_type_mirrors() {
|
||||
// Update the field at _array_klass_offset to point to the relocated array klass.
|
||||
oop archived_m = HeapShared::archive_object(m);
|
||||
assert(archived_m != NULL, "sanity");
|
||||
Klass *ak = (Klass*)(archived_m->metadata_field(_array_klass_offset));
|
||||
assert(ak != NULL || t == T_VOID, "should not be NULL");
|
||||
if (ak != NULL) {
|
||||
set_klass_field_in_archived_mirror(archived_m, _array_klass_offset, ak);
|
||||
}
|
||||
|
||||
// Clear the fields. Just to be safe
|
||||
Klass *k = m->klass();
|
||||
@ -1260,47 +1240,9 @@ oop java_lang_Class::process_archived_mirror(Klass* k, oop mirror,
|
||||
set_class_loader(archived_mirror, NULL);
|
||||
set_module(archived_mirror, NULL);
|
||||
|
||||
// The archived mirror's field at _klass_offset is still pointing to the original
|
||||
// klass. Updated the field in the archived mirror to point to the relocated
|
||||
// klass in the archive.
|
||||
set_klass_field_in_archived_mirror(archived_mirror, _klass_offset, as_Klass(mirror));
|
||||
|
||||
// The field at _array_klass_offset is pointing to the original one dimension
|
||||
// higher array klass if exists. Relocate the pointer.
|
||||
Klass *arr = array_klass_acquire(mirror);
|
||||
if (arr != NULL) {
|
||||
set_klass_field_in_archived_mirror(archived_mirror, _array_klass_offset, arr);
|
||||
}
|
||||
return archived_mirror;
|
||||
}
|
||||
|
||||
void java_lang_Class::update_archived_primitive_mirror_native_pointers(oop archived_mirror) {
|
||||
if (MetaspaceShared::relocation_delta() != 0) {
|
||||
assert(archived_mirror->metadata_field(_klass_offset) == NULL, "must be for primitive class");
|
||||
|
||||
Klass* ak = ((Klass*)archived_mirror->metadata_field(_array_klass_offset));
|
||||
if (ak != NULL) {
|
||||
archived_mirror->metadata_field_put(_array_klass_offset,
|
||||
(Klass*)(address(ak) + MetaspaceShared::relocation_delta()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void java_lang_Class::update_archived_mirror_native_pointers(oop archived_mirror) {
|
||||
assert(MetaspaceShared::relocation_delta() != 0, "must be");
|
||||
|
||||
Klass* k = ((Klass*)archived_mirror->metadata_field(_klass_offset));
|
||||
archived_mirror->metadata_field_put(_klass_offset,
|
||||
(Klass*)(address(k) + MetaspaceShared::relocation_delta()));
|
||||
|
||||
Klass* ak = ((Klass*)archived_mirror->metadata_field(_array_klass_offset));
|
||||
if (ak != NULL) {
|
||||
archived_mirror->metadata_field_put(_array_klass_offset,
|
||||
(Klass*)(address(ak) + MetaspaceShared::relocation_delta()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Returns true if the mirror is updated, false if no archived mirror
|
||||
// data is present. After the archived mirror object is restored, the
|
||||
// shared klass' _has_raw_archived_mirror flag is cleared.
|
||||
|
@ -253,8 +253,6 @@ class java_lang_Class : AllStatic {
|
||||
Handle protection_domain, Handle classData, TRAPS);
|
||||
static void fixup_mirror(Klass* k, TRAPS);
|
||||
static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS);
|
||||
static void update_archived_primitive_mirror_native_pointers(oop archived_mirror) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static void update_archived_mirror_native_pointers(oop archived_mirror) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
|
||||
// Archiving
|
||||
static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
|
||||
|
@ -1550,73 +1550,3 @@ void SystemDictionaryShared::cleanup_lambda_proxy_class_dictionary() {
|
||||
CleanupDumpTimeLambdaProxyClassTable cleanup_proxy_classes;
|
||||
_dumptime_lambda_proxy_class_dictionary->unlink(&cleanup_proxy_classes);
|
||||
}
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
|
||||
class ArchivedMirrorPatcher {
|
||||
protected:
|
||||
static void update(Klass* k) {
|
||||
if (k->has_archived_mirror_index()) {
|
||||
oop m = k->archived_java_mirror();
|
||||
if (m != NULL) {
|
||||
java_lang_Class::update_archived_mirror_native_pointers(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static void update_array_klasses(Klass* ak) {
|
||||
while (ak != NULL) {
|
||||
update(ak);
|
||||
ak = ArrayKlass::cast(ak)->higher_dimension();
|
||||
}
|
||||
}
|
||||
|
||||
void do_value(const RunTimeClassInfo* info) {
|
||||
InstanceKlass* ik = info->_klass;
|
||||
update(ik);
|
||||
update_array_klasses(ik->array_klasses());
|
||||
}
|
||||
};
|
||||
|
||||
class ArchivedLambdaMirrorPatcher : public ArchivedMirrorPatcher {
|
||||
public:
|
||||
void do_value(const RunTimeLambdaProxyClassInfo* info) {
|
||||
InstanceKlass* ik = info->proxy_klass_head();
|
||||
while (ik != NULL) {
|
||||
update(ik);
|
||||
Klass* k = ik->next_link();
|
||||
ik = (k != NULL) ? InstanceKlass::cast(k) : NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void SystemDictionaryShared::update_archived_mirror_native_pointers_for(RunTimeSharedDictionary* dict) {
|
||||
ArchivedMirrorPatcher patcher;
|
||||
dict->iterate(&patcher);
|
||||
}
|
||||
|
||||
void SystemDictionaryShared::update_archived_mirror_native_pointers_for(LambdaProxyClassDictionary* dict) {
|
||||
ArchivedLambdaMirrorPatcher patcher;
|
||||
dict->iterate(&patcher);
|
||||
}
|
||||
|
||||
void SystemDictionaryShared::update_archived_mirror_native_pointers() {
|
||||
if (!ArchiveHeapLoader::are_archived_mirrors_available()) {
|
||||
return;
|
||||
}
|
||||
if (MetaspaceShared::relocation_delta() == 0) {
|
||||
return;
|
||||
}
|
||||
// mirrors are not archived for the classes in the dynamic archive
|
||||
update_archived_mirror_native_pointers_for(&_static_archive._builtin_dictionary);
|
||||
update_archived_mirror_native_pointers_for(&_static_archive._unregistered_dictionary);
|
||||
update_archived_mirror_native_pointers_for(&_static_archive._lambda_proxy_class_dictionary);
|
||||
|
||||
for (int t = T_BOOLEAN; t <= T_LONG; t++) {
|
||||
Klass* k = Universe::typeArrayKlassObj((BasicType)t);
|
||||
ArchivedMirrorPatcher::update_array_klasses(k);
|
||||
}
|
||||
ArchivedMirrorPatcher::update_array_klasses(Universe::fillerArrayKlassObj());
|
||||
}
|
||||
#endif
|
||||
|
@ -346,14 +346,6 @@ public:
|
||||
}
|
||||
|
||||
static unsigned int hash_for_shared_dictionary(address ptr);
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
private:
|
||||
static void update_archived_mirror_native_pointers_for(RunTimeSharedDictionary* dict);
|
||||
static void update_archived_mirror_native_pointers_for(LambdaProxyClassDictionary* dict);
|
||||
public:
|
||||
static void update_archived_mirror_native_pointers() NOT_CDS_RETURN;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // SHARE_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
|
||||
|
@ -39,7 +39,7 @@
|
||||
#define CDS_ARCHIVE_MAGIC 0xf00baba2
|
||||
#define CDS_DYNAMIC_ARCHIVE_MAGIC 0xf00baba8
|
||||
#define CDS_GENERIC_HEADER_SUPPORTED_MIN_VERSION 13
|
||||
#define CURRENT_CDS_ARCHIVE_VERSION 14
|
||||
#define CURRENT_CDS_ARCHIVE_VERSION 15
|
||||
|
||||
typedef struct CDSFileMapRegion {
|
||||
int _crc; // CRC checksum of this region.
|
||||
@ -55,8 +55,12 @@ typedef struct CDSFileMapRegion {
|
||||
// - for heap regions, the base address is the compressed oop encoding base
|
||||
size_t _used; // Number of bytes actually used by this region (excluding padding bytes added
|
||||
// for alignment purposed.
|
||||
size_t _oopmap_offset; // Bitmap for relocating embedded oops (offset from SharedBaseAddress).
|
||||
size_t _oopmap_offset; // Bitmap for relocating oop fields in archived heap objects.
|
||||
// (The base address is the bottom of the BM region)
|
||||
size_t _oopmap_size_in_bits;
|
||||
size_t _ptrmap_offset; // Bitmap for relocating native pointer fields in archived heap objects.
|
||||
// (The base address is the bottom of the BM region).
|
||||
size_t _ptrmap_size_in_bits;
|
||||
char* _mapped_base; // Actually mapped address (NULL if this region is not mapped).
|
||||
} CDSFileMapRegion;
|
||||
|
||||
|
@ -258,9 +258,6 @@ void Universe::serialize(SerializeClosure* f) {
|
||||
}
|
||||
f->do_oop(&mirror_oop); // write to archive
|
||||
}
|
||||
if (mirror_oop != NULL) { // may be null if archived heap is disabled
|
||||
java_lang_Class::update_archived_primitive_mirror_native_pointers(mirror_oop);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -63,7 +63,7 @@ public class ArchiveRelocationTest {
|
||||
String mainClass = "Hello";
|
||||
String forceRelocation = "-XX:ArchiveRelocationMode=1";
|
||||
String runRelocArg = run_reloc ? forceRelocation : "-showversion";
|
||||
String logArg = "-Xlog:cds=debug,cds+reloc=debug";
|
||||
String logArg = "-Xlog:cds=debug,cds+reloc=debug,cds+heap";
|
||||
String unlockArg = "-XX:+UnlockDiagnosticVMOptions";
|
||||
String nmtArg = "-XX:NativeMemoryTracking=detail";
|
||||
|
||||
@ -76,6 +76,12 @@ public class ArchiveRelocationTest {
|
||||
.assertNormalExit(output -> {
|
||||
if (run_reloc) {
|
||||
output.shouldContain("Try to map archive(s) at an alternative address");
|
||||
if (output.getOutput().contains("Trying to map heap") || output.getOutput().contains("Loaded heap")) {
|
||||
// The native data in the RO/RW regions have been relocated. If the CDS heap is
|
||||
// mapped/loaded, we must patch all the native pointers. (CDS heap is
|
||||
// not supported on all platforms)
|
||||
output.shouldContain("Patching native pointers in heap region");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -91,6 +91,23 @@ public class TestSerialGCWithCDS {
|
||||
out.shouldContain(HELLO);
|
||||
out.shouldHaveExitValue(0);
|
||||
|
||||
System.out.println("2. Exec with " + execGC + " and test ArchiveRelocationMode");
|
||||
out = TestCommon.exec(helloJar,
|
||||
execGC,
|
||||
small1,
|
||||
small2,
|
||||
"-Xlog:cds,cds+heap",
|
||||
"-XX:ArchiveRelocationMode=1", // always relocate shared metadata
|
||||
"Hello");
|
||||
out.shouldContain(HELLO);
|
||||
if (out.getOutput().contains("Trying to map heap") || out.getOutput().contains("Loaded heap")) {
|
||||
// The native data in the RO/RW regions have been relocated. If the CDS heap is
|
||||
// mapped/loaded, we must patch all the native pointers. (CDS heap is
|
||||
// not supported on all platforms)
|
||||
out.shouldContain("Patching native pointers in heap region");
|
||||
}
|
||||
out.shouldHaveExitValue(0);
|
||||
|
||||
int n = 2;
|
||||
if (dumpWithSerial == false && execWithSerial == true) {
|
||||
// We dumped with G1, so we have an archived heap. At exec time, try to load them into
|
||||
|
Loading…
Reference in New Issue
Block a user