8293293: Move archive heap loading code out of heapShared.cpp
Reviewed-by: erikj, coleenp
This commit is contained in:
parent
e1e67324c0
commit
ac05bc8605
make/hotspot/lib
src/hotspot/share
@ -120,12 +120,8 @@ endif
|
|||||||
ifneq ($(call check-jvm-feature, cds), true)
|
ifneq ($(call check-jvm-feature, cds), true)
|
||||||
JVM_CFLAGS_FEATURES += -DINCLUDE_CDS=0
|
JVM_CFLAGS_FEATURES += -DINCLUDE_CDS=0
|
||||||
JVM_EXCLUDE_FILES += \
|
JVM_EXCLUDE_FILES += \
|
||||||
cdsProtectionDomain.cpp \
|
|
||||||
classLoaderDataShared.cpp \
|
classLoaderDataShared.cpp \
|
||||||
classLoaderExt.cpp \
|
classLoaderExt.cpp \
|
||||||
dumpTimeSharedClassInfo.cpp \
|
|
||||||
lambdaProxyClassDictionary.cpp \
|
|
||||||
runTimeSharedClassInfo.cpp \
|
|
||||||
systemDictionaryShared.cpp
|
systemDictionaryShared.cpp
|
||||||
JVM_EXCLUDE_PATTERNS += cds/
|
JVM_EXCLUDE_PATTERNS += cds/
|
||||||
endif
|
endif
|
||||||
|
437
src/hotspot/share/cds/archiveHeapLoader.cpp
Normal file
437
src/hotspot/share/cds/archiveHeapLoader.cpp
Normal file
@ -0,0 +1,437 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "cds/archiveHeapLoader.inline.hpp"
|
||||||
|
#include "cds/filemap.hpp"
|
||||||
|
#include "cds/heapShared.hpp"
|
||||||
|
#include "cds/metaspaceShared.hpp"
|
||||||
|
#include "classfile/classLoaderDataShared.hpp"
|
||||||
|
#include "classfile/systemDictionaryShared.hpp"
|
||||||
|
#include "gc/shared/collectedHeap.hpp"
|
||||||
|
#include "logging/log.hpp"
|
||||||
|
#include "memory/iterator.inline.hpp"
|
||||||
|
#include "memory/resourceArea.hpp"
|
||||||
|
#include "memory/universe.hpp"
|
||||||
|
#include "utilities/bitMap.inline.hpp"
|
||||||
|
#include "utilities/copy.hpp"
|
||||||
|
|
||||||
|
#if INCLUDE_CDS_JAVA_HEAP
|
||||||
|
|
||||||
|
bool ArchiveHeapLoader::_closed_regions_mapped = false;
|
||||||
|
bool ArchiveHeapLoader::_open_regions_mapped = false;
|
||||||
|
bool ArchiveHeapLoader::_is_loaded = false;
|
||||||
|
address ArchiveHeapLoader::_narrow_oop_base;
|
||||||
|
int ArchiveHeapLoader::_narrow_oop_shift;
|
||||||
|
|
||||||
|
// Support for loaded heap.
|
||||||
|
uintptr_t ArchiveHeapLoader::_loaded_heap_bottom = 0;
|
||||||
|
uintptr_t ArchiveHeapLoader::_loaded_heap_top = 0;
|
||||||
|
uintptr_t ArchiveHeapLoader::_dumptime_base_0 = UINTPTR_MAX;
|
||||||
|
uintptr_t ArchiveHeapLoader::_dumptime_base_1 = UINTPTR_MAX;
|
||||||
|
uintptr_t ArchiveHeapLoader::_dumptime_base_2 = UINTPTR_MAX;
|
||||||
|
uintptr_t ArchiveHeapLoader::_dumptime_base_3 = UINTPTR_MAX;
|
||||||
|
uintptr_t ArchiveHeapLoader::_dumptime_top = 0;
|
||||||
|
intx ArchiveHeapLoader::_runtime_offset_0 = 0;
|
||||||
|
intx ArchiveHeapLoader::_runtime_offset_1 = 0;
|
||||||
|
intx ArchiveHeapLoader::_runtime_offset_2 = 0;
|
||||||
|
intx ArchiveHeapLoader::_runtime_offset_3 = 0;
|
||||||
|
bool ArchiveHeapLoader::_loading_failed = false;
|
||||||
|
|
||||||
|
// Support for mapped heap (!UseCompressedOops only)
|
||||||
|
ptrdiff_t ArchiveHeapLoader::_runtime_delta = 0;
|
||||||
|
|
||||||
|
void ArchiveHeapLoader::init_narrow_oop_decoding(address base, int shift) {
|
||||||
|
_narrow_oop_base = base;
|
||||||
|
_narrow_oop_shift = shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArchiveHeapLoader::fixup_regions() {
|
||||||
|
FileMapInfo* mapinfo = FileMapInfo::current_info();
|
||||||
|
if (is_mapped()) {
|
||||||
|
mapinfo->fixup_mapped_heap_regions();
|
||||||
|
} else if (_loading_failed) {
|
||||||
|
fill_failed_loaded_region();
|
||||||
|
}
|
||||||
|
if (is_fully_available()) {
|
||||||
|
if (!MetaspaceShared::use_full_module_graph()) {
|
||||||
|
// Need to remove all the archived java.lang.Module objects from HeapShared::roots().
|
||||||
|
ClassLoaderDataShared::clear_archived_oops();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SystemDictionaryShared::update_archived_mirror_native_pointers();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------ Support for Region MAPPING -----------------------------------------
|
||||||
|
|
||||||
|
// Patch all the embedded oop pointers inside an archived heap region,
|
||||||
|
// to be consistent with the runtime oop encoding.
|
||||||
|
class PatchCompressedEmbeddedPointers: public BitMapClosure {
|
||||||
|
narrowOop* _start;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PatchCompressedEmbeddedPointers(narrowOop* start) : _start(start) {}
|
||||||
|
|
||||||
|
bool do_bit(size_t offset) {
|
||||||
|
narrowOop* p = _start + offset;
|
||||||
|
narrowOop v = *p;
|
||||||
|
assert(!CompressedOops::is_null(v), "null oops should have been filtered out at dump time");
|
||||||
|
oop o = ArchiveHeapLoader::decode_from_archive(v);
|
||||||
|
RawAccess<IS_NOT_NULL>::oop_store(p, o);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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 + ArchiveHeapLoader::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 (mapped) region
|
||||||
|
void ArchiveHeapLoader::patch_embedded_pointers(MemRegion region, address oopmap,
|
||||||
|
size_t oopmap_size_in_bits) {
|
||||||
|
BitMapView bm((BitMap::bm_word_t*)oopmap, oopmap_size_in_bits);
|
||||||
|
|
||||||
|
#ifndef PRODUCT
|
||||||
|
ResourceMark rm;
|
||||||
|
ResourceBitMap checkBm = HeapShared::calculate_oopmap(region);
|
||||||
|
assert(bm.is_same(checkBm), "sanity");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (UseCompressedOops) {
|
||||||
|
PatchCompressedEmbeddedPointers patcher((narrowOop*)region.start());
|
||||||
|
bm.iterate(&patcher);
|
||||||
|
} else {
|
||||||
|
PatchUncompressedEmbeddedPointers patcher((oop*)region.start());
|
||||||
|
bm.iterate(&patcher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------ Support for Region LOADING -----------------------------------------
|
||||||
|
|
||||||
|
// The CDS archive remembers each heap object by its address at dump time, but
|
||||||
|
// the heap object may be loaded at a different address at run time. This structure is used
|
||||||
|
// to translate the dump time addresses for all objects in FileMapInfo::space_at(region_index)
|
||||||
|
// to their runtime addresses.
|
||||||
|
struct LoadedArchiveHeapRegion {
|
||||||
|
int _region_index; // index for FileMapInfo::space_at(index)
|
||||||
|
size_t _region_size; // number of bytes in this region
|
||||||
|
uintptr_t _dumptime_base; // The dump-time (decoded) address of the first object in this region
|
||||||
|
intx _runtime_offset; // If an object's dump time address P is within in this region, its
|
||||||
|
// runtime address is P + _runtime_offset
|
||||||
|
|
||||||
|
static int comparator(const void* a, const void* b) {
|
||||||
|
LoadedArchiveHeapRegion* reg_a = (LoadedArchiveHeapRegion*)a;
|
||||||
|
LoadedArchiveHeapRegion* reg_b = (LoadedArchiveHeapRegion*)b;
|
||||||
|
if (reg_a->_dumptime_base < reg_b->_dumptime_base) {
|
||||||
|
return -1;
|
||||||
|
} else if (reg_a->_dumptime_base == reg_b->_dumptime_base) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t top() {
|
||||||
|
return _dumptime_base + _region_size;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void ArchiveHeapLoader::init_loaded_heap_relocation(LoadedArchiveHeapRegion* 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;
|
||||||
|
_dumptime_base_3 = loaded_regions[3]._dumptime_base;
|
||||||
|
_dumptime_top = loaded_regions[num_loaded_regions-1].top();
|
||||||
|
|
||||||
|
_runtime_offset_0 = loaded_regions[0]._runtime_offset;
|
||||||
|
_runtime_offset_1 = loaded_regions[1]._runtime_offset;
|
||||||
|
_runtime_offset_2 = loaded_regions[2]._runtime_offset;
|
||||||
|
_runtime_offset_3 = loaded_regions[3]._runtime_offset;
|
||||||
|
|
||||||
|
assert(2 <= num_loaded_regions && num_loaded_regions <= 4, "must be");
|
||||||
|
if (num_loaded_regions < 4) {
|
||||||
|
_dumptime_base_3 = UINTPTR_MAX;
|
||||||
|
}
|
||||||
|
if (num_loaded_regions < 3) {
|
||||||
|
_dumptime_base_2 = UINTPTR_MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArchiveHeapLoader::can_load() {
|
||||||
|
return Universe::heap()->can_load_archived_objects();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int NUM_LOADED_REGIONS>
|
||||||
|
class PatchLoadedRegionPointers: public BitMapClosure {
|
||||||
|
narrowOop* _start;
|
||||||
|
intx _offset_0;
|
||||||
|
intx _offset_1;
|
||||||
|
intx _offset_2;
|
||||||
|
intx _offset_3;
|
||||||
|
uintptr_t _base_0;
|
||||||
|
uintptr_t _base_1;
|
||||||
|
uintptr_t _base_2;
|
||||||
|
uintptr_t _base_3;
|
||||||
|
uintptr_t _top;
|
||||||
|
|
||||||
|
static_assert(MetaspaceShared::max_num_heap_regions == 4, "can't handle more than 4 regions");
|
||||||
|
static_assert(NUM_LOADED_REGIONS >= 2, "we have at least 2 loaded regions");
|
||||||
|
static_assert(NUM_LOADED_REGIONS <= 4, "we have at most 4 loaded regions");
|
||||||
|
|
||||||
|
public:
|
||||||
|
PatchLoadedRegionPointers(narrowOop* start, LoadedArchiveHeapRegion* loaded_regions)
|
||||||
|
: _start(start),
|
||||||
|
_offset_0(loaded_regions[0]._runtime_offset),
|
||||||
|
_offset_1(loaded_regions[1]._runtime_offset),
|
||||||
|
_offset_2(loaded_regions[2]._runtime_offset),
|
||||||
|
_offset_3(loaded_regions[3]._runtime_offset),
|
||||||
|
_base_0(loaded_regions[0]._dumptime_base),
|
||||||
|
_base_1(loaded_regions[1]._dumptime_base),
|
||||||
|
_base_2(loaded_regions[2]._dumptime_base),
|
||||||
|
_base_3(loaded_regions[3]._dumptime_base) {
|
||||||
|
_top = loaded_regions[NUM_LOADED_REGIONS-1].top();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool do_bit(size_t offset) {
|
||||||
|
narrowOop* p = _start + offset;
|
||||||
|
narrowOop v = *p;
|
||||||
|
assert(!CompressedOops::is_null(v), "null oops should have been filtered out at dump time");
|
||||||
|
uintptr_t o = cast_from_oop<uintptr_t>(ArchiveHeapLoader::decode_from_archive(v));
|
||||||
|
assert(_base_0 <= o && o < _top, "must be");
|
||||||
|
|
||||||
|
|
||||||
|
// We usually have only 2 regions for the default archive. Use template to avoid unnecessary comparisons.
|
||||||
|
if (NUM_LOADED_REGIONS > 3 && o >= _base_3) {
|
||||||
|
o += _offset_3;
|
||||||
|
} else if (NUM_LOADED_REGIONS > 2 && o >= _base_2) {
|
||||||
|
o += _offset_2;
|
||||||
|
} else if (o >= _base_1) {
|
||||||
|
o += _offset_1;
|
||||||
|
} else {
|
||||||
|
o += _offset_0;
|
||||||
|
}
|
||||||
|
ArchiveHeapLoader::assert_in_loaded_heap(o);
|
||||||
|
RawAccess<IS_NOT_NULL>::oop_store(p, cast_to_oop(o));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int ArchiveHeapLoader::init_loaded_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_regions,
|
||||||
|
MemRegion& archive_space) {
|
||||||
|
size_t total_bytes = 0;
|
||||||
|
int num_loaded_regions = 0;
|
||||||
|
for (int i = MetaspaceShared::first_archive_heap_region;
|
||||||
|
i <= MetaspaceShared::last_archive_heap_region; i++) {
|
||||||
|
FileMapRegion* r = mapinfo->space_at(i);
|
||||||
|
r->assert_is_heap_region();
|
||||||
|
if (r->used() > 0) {
|
||||||
|
assert(is_aligned(r->used(), HeapWordSize), "must be");
|
||||||
|
total_bytes += r->used();
|
||||||
|
LoadedArchiveHeapRegion* ri = &loaded_regions[num_loaded_regions++];
|
||||||
|
ri->_region_index = i;
|
||||||
|
ri->_region_size = r->used();
|
||||||
|
ri->_dumptime_base = (uintptr_t)mapinfo->start_address_as_decoded_from_archive(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(is_aligned(total_bytes, HeapWordSize), "must be");
|
||||||
|
size_t word_size = total_bytes / HeapWordSize;
|
||||||
|
HeapWord* buffer = Universe::heap()->allocate_loaded_archive_space(word_size);
|
||||||
|
if (buffer == nullptr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
archive_space = MemRegion(buffer, word_size);
|
||||||
|
_loaded_heap_bottom = (uintptr_t)archive_space.start();
|
||||||
|
_loaded_heap_top = _loaded_heap_bottom + total_bytes;
|
||||||
|
|
||||||
|
return num_loaded_regions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArchiveHeapLoader::sort_loaded_regions(LoadedArchiveHeapRegion* loaded_regions, int num_loaded_regions,
|
||||||
|
uintptr_t buffer) {
|
||||||
|
// Find the relocation offset of the pointers in each region
|
||||||
|
qsort(loaded_regions, num_loaded_regions, sizeof(LoadedArchiveHeapRegion),
|
||||||
|
LoadedArchiveHeapRegion::comparator);
|
||||||
|
|
||||||
|
uintptr_t p = buffer;
|
||||||
|
for (int i = 0; i < num_loaded_regions; i++) {
|
||||||
|
// This region will be loaded at p, so all objects inside this
|
||||||
|
// region will be shifted by ri->offset
|
||||||
|
LoadedArchiveHeapRegion* ri = &loaded_regions[i];
|
||||||
|
ri->_runtime_offset = p - ri->_dumptime_base;
|
||||||
|
p += ri->_region_size;
|
||||||
|
}
|
||||||
|
assert(p == _loaded_heap_top, "must be");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArchiveHeapLoader::load_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_regions,
|
||||||
|
int num_loaded_regions, uintptr_t buffer) {
|
||||||
|
uintptr_t bitmap_base = (uintptr_t)mapinfo->map_bitmap_region();
|
||||||
|
if (bitmap_base == 0) {
|
||||||
|
_loading_failed = true;
|
||||||
|
return false; // OOM or CRC error
|
||||||
|
}
|
||||||
|
uintptr_t load_address = buffer;
|
||||||
|
for (int i = 0; i < num_loaded_regions; i++) {
|
||||||
|
LoadedArchiveHeapRegion* ri = &loaded_regions[i];
|
||||||
|
FileMapRegion* r = mapinfo->space_at(ri->_region_index);
|
||||||
|
|
||||||
|
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.
|
||||||
|
log_warning(cds)("Loading of heap region %d has failed. Archived objects are disabled", i);
|
||||||
|
_loading_failed = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
log_info(cds)("Loaded heap region #%d at base " INTPTR_FORMAT " top " INTPTR_FORMAT
|
||||||
|
" size " SIZE_FORMAT_W(6) " delta " INTX_FORMAT,
|
||||||
|
ri->_region_index, load_address, load_address + ri->_region_size,
|
||||||
|
ri->_region_size, ri->_runtime_offset);
|
||||||
|
|
||||||
|
uintptr_t oopmap = bitmap_base + r->oopmap_offset();
|
||||||
|
BitMapView bm((BitMap::bm_word_t*)oopmap, r->oopmap_size_in_bits());
|
||||||
|
|
||||||
|
if (num_loaded_regions == 4) {
|
||||||
|
PatchLoadedRegionPointers<4> patcher((narrowOop*)load_address, loaded_regions);
|
||||||
|
bm.iterate(&patcher);
|
||||||
|
} else if (num_loaded_regions == 3) {
|
||||||
|
PatchLoadedRegionPointers<3> patcher((narrowOop*)load_address, loaded_regions);
|
||||||
|
bm.iterate(&patcher);
|
||||||
|
} else {
|
||||||
|
assert(num_loaded_regions == 2, "must be");
|
||||||
|
PatchLoadedRegionPointers<2> patcher((narrowOop*)load_address, loaded_regions);
|
||||||
|
bm.iterate(&patcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
load_address += r->used();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArchiveHeapLoader::load_heap_regions(FileMapInfo* mapinfo) {
|
||||||
|
init_narrow_oop_decoding(mapinfo->narrow_oop_base(), mapinfo->narrow_oop_shift());
|
||||||
|
|
||||||
|
LoadedArchiveHeapRegion loaded_regions[MetaspaceShared::max_num_heap_regions];
|
||||||
|
memset(loaded_regions, 0, sizeof(loaded_regions));
|
||||||
|
|
||||||
|
MemRegion archive_space;
|
||||||
|
int num_loaded_regions = init_loaded_regions(mapinfo, loaded_regions, archive_space);
|
||||||
|
if (num_loaded_regions <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sort_loaded_regions(loaded_regions, num_loaded_regions, (uintptr_t)archive_space.start());
|
||||||
|
if (!load_regions(mapinfo, loaded_regions, num_loaded_regions, (uintptr_t)archive_space.start())) {
|
||||||
|
assert(_loading_failed, "must be");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_loaded_heap_relocation(loaded_regions, num_loaded_regions);
|
||||||
|
_is_loaded = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
class VerifyLoadedHeapEmbeddedPointers: public BasicOopIterateClosure {
|
||||||
|
ResourceHashtable<uintptr_t, bool>* _table;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VerifyLoadedHeapEmbeddedPointers(ResourceHashtable<uintptr_t, bool>* table) : _table(table) {}
|
||||||
|
|
||||||
|
virtual void do_oop(narrowOop* p) {
|
||||||
|
// This should be called before the loaded regions are modified, so all the embedded pointers
|
||||||
|
// must be NULL, or must point to a valid object in the loaded regions.
|
||||||
|
narrowOop v = *p;
|
||||||
|
if (!CompressedOops::is_null(v)) {
|
||||||
|
oop o = CompressedOops::decode_not_null(v);
|
||||||
|
uintptr_t u = cast_from_oop<uintptr_t>(o);
|
||||||
|
ArchiveHeapLoader::assert_in_loaded_heap(u);
|
||||||
|
guarantee(_table->contains(u), "must point to beginning of object in loaded archived regions");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void do_oop(oop* p) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VerifyArchivedFields <= 0 || !is_loaded()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info(cds, heap)("Verify all oops and pointers in loaded heap");
|
||||||
|
|
||||||
|
ResourceMark rm;
|
||||||
|
ResourceHashtable<uintptr_t, bool> table;
|
||||||
|
VerifyLoadedHeapEmbeddedPointers verifier(&table);
|
||||||
|
HeapWord* bottom = (HeapWord*)_loaded_heap_bottom;
|
||||||
|
HeapWord* top = (HeapWord*)_loaded_heap_top;
|
||||||
|
|
||||||
|
for (HeapWord* p = bottom; p < top; ) {
|
||||||
|
oop o = cast_to_oop(p);
|
||||||
|
table.put(cast_from_oop<uintptr_t>(o), true);
|
||||||
|
p += o->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (HeapWord* p = bottom; p < top; ) {
|
||||||
|
oop o = cast_to_oop(p);
|
||||||
|
o->oop_iterate(&verifier);
|
||||||
|
p += o->size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArchiveHeapLoader::fill_failed_loaded_region() {
|
||||||
|
assert(_loading_failed, "must be");
|
||||||
|
if (_loaded_heap_bottom != 0) {
|
||||||
|
assert(_loaded_heap_top != 0, "must be");
|
||||||
|
HeapWord* bottom = (HeapWord*)_loaded_heap_bottom;
|
||||||
|
HeapWord* top = (HeapWord*)_loaded_heap_top;
|
||||||
|
Universe::heap()->fill_with_objects(bottom, top - bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // INCLUDE_CDS_JAVA_HEAP
|
170
src/hotspot/share/cds/archiveHeapLoader.hpp
Normal file
170
src/hotspot/share/cds/archiveHeapLoader.hpp
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARE_CDS_ARCHIVEHEAPLOADER_HPP
|
||||||
|
#define SHARE_CDS_ARCHIVEHEAPLOADER_HPP
|
||||||
|
|
||||||
|
#include "gc/shared/gc_globals.hpp"
|
||||||
|
#include "memory/allocation.hpp"
|
||||||
|
#include "memory/allStatic.hpp"
|
||||||
|
#include "runtime/globals.hpp"
|
||||||
|
#include "oops/oopsHierarchy.hpp"
|
||||||
|
#include "memory/memRegion.hpp"
|
||||||
|
#include "utilities/macros.hpp"
|
||||||
|
|
||||||
|
class FileMapInfo;
|
||||||
|
struct LoadedArchiveHeapRegion;
|
||||||
|
|
||||||
|
class ArchiveHeapLoader : AllStatic {
|
||||||
|
public:
|
||||||
|
// At runtime, heap regions in the CDS archive can be used in two different ways,
|
||||||
|
// depending on the GC type:
|
||||||
|
// - Mapped: (G1 only) the regions are directly mapped into the Java heap
|
||||||
|
// - Loaded: At VM start-up, the objects in the heap regions are copied into the
|
||||||
|
// Java heap. This is easier to implement than mapping but
|
||||||
|
// slightly less efficient, as the embedded pointers need to be relocated.
|
||||||
|
static bool can_use() { return can_map() || can_load(); }
|
||||||
|
|
||||||
|
// Can this VM map archived heap regions? Currently only G1+compressed{oops,cp}
|
||||||
|
static bool can_map() {
|
||||||
|
CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedClassPointers);)
|
||||||
|
NOT_CDS_JAVA_HEAP(return false;)
|
||||||
|
}
|
||||||
|
static bool is_mapped() {
|
||||||
|
return closed_regions_mapped() && open_regions_mapped();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can this VM load the objects from archived heap regions into the heap at start-up?
|
||||||
|
static bool can_load() NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||||
|
static void finish_initialization() NOT_CDS_JAVA_HEAP_RETURN;
|
||||||
|
static bool is_loaded() {
|
||||||
|
CDS_JAVA_HEAP_ONLY(return _is_loaded;)
|
||||||
|
NOT_CDS_JAVA_HEAP(return false;)
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool are_archived_strings_available() {
|
||||||
|
return is_loaded() || closed_regions_mapped();
|
||||||
|
}
|
||||||
|
static bool are_archived_mirrors_available() {
|
||||||
|
return is_fully_available();
|
||||||
|
}
|
||||||
|
static bool is_fully_available() {
|
||||||
|
return is_loaded() || is_mapped();
|
||||||
|
}
|
||||||
|
|
||||||
|
static ptrdiff_t runtime_delta() {
|
||||||
|
assert(!UseCompressedOops, "must be");
|
||||||
|
CDS_JAVA_HEAP_ONLY(return _runtime_delta;)
|
||||||
|
NOT_CDS_JAVA_HEAP_RETURN_(0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_closed_regions_mapped() {
|
||||||
|
CDS_JAVA_HEAP_ONLY(_closed_regions_mapped = true;)
|
||||||
|
NOT_CDS_JAVA_HEAP_RETURN;
|
||||||
|
}
|
||||||
|
static bool closed_regions_mapped() {
|
||||||
|
CDS_JAVA_HEAP_ONLY(return _closed_regions_mapped;)
|
||||||
|
NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||||
|
}
|
||||||
|
static void set_open_regions_mapped() {
|
||||||
|
CDS_JAVA_HEAP_ONLY(_open_regions_mapped = true;)
|
||||||
|
NOT_CDS_JAVA_HEAP_RETURN;
|
||||||
|
}
|
||||||
|
static bool open_regions_mapped() {
|
||||||
|
CDS_JAVA_HEAP_ONLY(return _open_regions_mapped;)
|
||||||
|
NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NarrowOops stored in the CDS archive may use a different encoding scheme
|
||||||
|
// than CompressedOops::{base,shift} -- see FileMapInfo::map_heap_regions_impl.
|
||||||
|
// To decode them, do not use CompressedOops::decode_not_null. Use this
|
||||||
|
// function instead.
|
||||||
|
inline static oop decode_from_archive(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(NULL);
|
||||||
|
|
||||||
|
static void init_narrow_oop_decoding(address base, int shift) NOT_CDS_JAVA_HEAP_RETURN;
|
||||||
|
|
||||||
|
static void patch_embedded_pointers(MemRegion region, address oopmap,
|
||||||
|
size_t oopmap_in_bits) NOT_CDS_JAVA_HEAP_RETURN;
|
||||||
|
|
||||||
|
static void fixup_regions() NOT_CDS_JAVA_HEAP_RETURN;
|
||||||
|
|
||||||
|
#if INCLUDE_CDS_JAVA_HEAP
|
||||||
|
private:
|
||||||
|
static bool _closed_regions_mapped;
|
||||||
|
static bool _open_regions_mapped;
|
||||||
|
static bool _is_loaded;
|
||||||
|
|
||||||
|
// Support for loaded archived heap. These are cached values from
|
||||||
|
// LoadedArchiveHeapRegion's.
|
||||||
|
static uintptr_t _dumptime_base_0;
|
||||||
|
static uintptr_t _dumptime_base_1;
|
||||||
|
static uintptr_t _dumptime_base_2;
|
||||||
|
static uintptr_t _dumptime_base_3;
|
||||||
|
static uintptr_t _dumptime_top;
|
||||||
|
static intx _runtime_offset_0;
|
||||||
|
static intx _runtime_offset_1;
|
||||||
|
static intx _runtime_offset_2;
|
||||||
|
static intx _runtime_offset_3;
|
||||||
|
|
||||||
|
static uintptr_t _loaded_heap_bottom;
|
||||||
|
static uintptr_t _loaded_heap_top;
|
||||||
|
static bool _loading_failed;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
static int init_loaded_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_regions,
|
||||||
|
MemRegion& archive_space);
|
||||||
|
static void sort_loaded_regions(LoadedArchiveHeapRegion* loaded_regions, int num_loaded_regions,
|
||||||
|
uintptr_t buffer);
|
||||||
|
static bool load_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_regions,
|
||||||
|
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 bool is_in_loaded_heap(uintptr_t o) {
|
||||||
|
return (_loaded_heap_bottom <= o && o < _loaded_heap_top);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static bool load_heap_regions(FileMapInfo* mapinfo);
|
||||||
|
static void assert_in_loaded_heap(uintptr_t o) {
|
||||||
|
assert(is_in_loaded_heap(o), "must be");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_runtime_delta(ptrdiff_t delta) {
|
||||||
|
assert(!UseCompressedOops, "must be");
|
||||||
|
_runtime_delta = delta;
|
||||||
|
}
|
||||||
|
#endif // INCLUDE_CDS_JAVA_HEAP
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHARE_CDS_ARCHIVEHEAPLOADER_HPP
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -22,16 +22,17 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SHARE_CDS_HEAPSHARED_INLINE_HPP
|
#ifndef SHARE_CDS_ARCHIVEHEAPLOADER_INLINE_HPP
|
||||||
#define SHARE_CDS_HEAPSHARED_INLINE_HPP
|
#define SHARE_CDS_ARCHIVEHEAPLOADER_INLINE_HPP
|
||||||
|
|
||||||
|
#include "cds/archiveHeapLoader.hpp"
|
||||||
|
|
||||||
#include "cds/heapShared.hpp"
|
|
||||||
#include "oops/compressedOops.inline.hpp"
|
#include "oops/compressedOops.inline.hpp"
|
||||||
#include "utilities/align.hpp"
|
#include "utilities/align.hpp"
|
||||||
|
|
||||||
#if INCLUDE_CDS_JAVA_HEAP
|
#if INCLUDE_CDS_JAVA_HEAP
|
||||||
|
|
||||||
inline oop HeapShared::decode_from_archive(narrowOop v) {
|
inline oop ArchiveHeapLoader::decode_from_archive(narrowOop v) {
|
||||||
assert(!CompressedOops::is_null(v), "narrow oop value can never be zero");
|
assert(!CompressedOops::is_null(v), "narrow oop value can never be zero");
|
||||||
uintptr_t p = ((uintptr_t)_narrow_oop_base) + ((uintptr_t)v << _narrow_oop_shift);
|
uintptr_t p = ((uintptr_t)_narrow_oop_base) + ((uintptr_t)v << _narrow_oop_shift);
|
||||||
if (p >= _dumptime_base_0) {
|
if (p >= _dumptime_base_0) {
|
||||||
@ -54,4 +55,4 @@ inline oop HeapShared::decode_from_archive(narrowOop v) {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // SHARE_CDS_HEAPSHARED_INLINE_HPP
|
#endif // SHARE_CDS_ARCHIVEHEAPLOADER_INLINE_HPP
|
@ -24,12 +24,13 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "cds/archiveBuilder.hpp"
|
#include "cds/archiveBuilder.hpp"
|
||||||
|
#include "cds/archiveHeapLoader.inline.hpp"
|
||||||
#include "cds/archiveUtils.hpp"
|
#include "cds/archiveUtils.hpp"
|
||||||
#include "cds/classListParser.hpp"
|
#include "cds/classListParser.hpp"
|
||||||
#include "cds/classListWriter.hpp"
|
#include "cds/classListWriter.hpp"
|
||||||
#include "cds/dynamicArchive.hpp"
|
#include "cds/dynamicArchive.hpp"
|
||||||
#include "cds/filemap.hpp"
|
#include "cds/filemap.hpp"
|
||||||
#include "cds/heapShared.inline.hpp"
|
#include "cds/heapShared.hpp"
|
||||||
#include "cds/metaspaceShared.hpp"
|
#include "cds/metaspaceShared.hpp"
|
||||||
#include "classfile/systemDictionaryShared.hpp"
|
#include "classfile/systemDictionaryShared.hpp"
|
||||||
#include "classfile/vmClasses.hpp"
|
#include "classfile/vmClasses.hpp"
|
||||||
@ -315,19 +316,19 @@ void ReadClosure::do_tag(int tag) {
|
|||||||
void ReadClosure::do_oop(oop *p) {
|
void ReadClosure::do_oop(oop *p) {
|
||||||
if (UseCompressedOops) {
|
if (UseCompressedOops) {
|
||||||
narrowOop o = CompressedOops::narrow_oop_cast(nextPtr());
|
narrowOop o = CompressedOops::narrow_oop_cast(nextPtr());
|
||||||
if (CompressedOops::is_null(o) || !HeapShared::is_fully_available()) {
|
if (CompressedOops::is_null(o) || !ArchiveHeapLoader::is_fully_available()) {
|
||||||
*p = NULL;
|
*p = NULL;
|
||||||
} else {
|
} else {
|
||||||
assert(HeapShared::can_use(), "sanity");
|
assert(ArchiveHeapLoader::can_use(), "sanity");
|
||||||
assert(HeapShared::is_fully_available(), "must be");
|
assert(ArchiveHeapLoader::is_fully_available(), "must be");
|
||||||
*p = HeapShared::decode_from_archive(o);
|
*p = ArchiveHeapLoader::decode_from_archive(o);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
intptr_t dumptime_oop = nextPtr();
|
intptr_t dumptime_oop = nextPtr();
|
||||||
if (dumptime_oop == 0 || !HeapShared::is_fully_available()) {
|
if (dumptime_oop == 0 || !ArchiveHeapLoader::is_fully_available()) {
|
||||||
*p = NULL;
|
*p = NULL;
|
||||||
} else {
|
} else {
|
||||||
intptr_t runtime_oop = dumptime_oop + HeapShared::runtime_delta();
|
intptr_t runtime_oop = dumptime_oop + ArchiveHeapLoader::runtime_delta();
|
||||||
*p = cast_to_oop(runtime_oop);
|
*p = cast_to_oop(runtime_oop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,12 @@
|
|||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
#include "cds/archiveBuilder.hpp"
|
#include "cds/archiveBuilder.hpp"
|
||||||
|
#include "cds/archiveHeapLoader.inline.hpp"
|
||||||
#include "cds/archiveUtils.inline.hpp"
|
#include "cds/archiveUtils.inline.hpp"
|
||||||
#include "cds/cds_globals.hpp"
|
#include "cds/cds_globals.hpp"
|
||||||
#include "cds/dynamicArchive.hpp"
|
#include "cds/dynamicArchive.hpp"
|
||||||
#include "cds/filemap.hpp"
|
#include "cds/filemap.hpp"
|
||||||
#include "cds/heapShared.inline.hpp"
|
#include "cds/heapShared.hpp"
|
||||||
#include "cds/metaspaceShared.hpp"
|
#include "cds/metaspaceShared.hpp"
|
||||||
#include "classfile/altHashing.hpp"
|
#include "classfile/altHashing.hpp"
|
||||||
#include "classfile/classFileStream.hpp"
|
#include "classfile/classFileStream.hpp"
|
||||||
@ -1970,7 +1971,7 @@ address FileMapInfo::decode_start_address(FileMapRegion* spc, bool with_current_
|
|||||||
if (with_current_oop_encoding_mode) {
|
if (with_current_oop_encoding_mode) {
|
||||||
return cast_from_oop<address>(CompressedOops::decode_raw_not_null(n));
|
return cast_from_oop<address>(CompressedOops::decode_raw_not_null(n));
|
||||||
} else {
|
} else {
|
||||||
return cast_from_oop<address>(HeapShared::decode_from_archive(n));
|
return cast_from_oop<address>(ArchiveHeapLoader::decode_from_archive(n));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2016,10 +2017,10 @@ void FileMapInfo::map_or_load_heap_regions() {
|
|||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
if (can_use_heap_regions()) {
|
if (can_use_heap_regions()) {
|
||||||
if (HeapShared::can_map()) {
|
if (ArchiveHeapLoader::can_map()) {
|
||||||
success = map_heap_regions();
|
success = map_heap_regions();
|
||||||
} else if (HeapShared::can_load()) {
|
} else if (ArchiveHeapLoader::can_load()) {
|
||||||
success = HeapShared::load_heap_regions(this);
|
success = ArchiveHeapLoader::load_heap_regions(this);
|
||||||
} else {
|
} else {
|
||||||
log_info(cds)("Cannot use CDS heap data. UseEpsilonGC, UseG1GC, UseSerialGC or UseParallelGC are required.");
|
log_info(cds)("Cannot use CDS heap data. UseEpsilonGC, UseG1GC, UseSerialGC or UseParallelGC are required.");
|
||||||
}
|
}
|
||||||
@ -2085,15 +2086,15 @@ address FileMapInfo::heap_region_runtime_start_address(FileMapRegion* spc) {
|
|||||||
return start_address_as_decoded_from_archive(spc);
|
return start_address_as_decoded_from_archive(spc);
|
||||||
} else {
|
} else {
|
||||||
assert(is_aligned(spc->mapping_offset(), sizeof(HeapWord)), "must be");
|
assert(is_aligned(spc->mapping_offset(), sizeof(HeapWord)), "must be");
|
||||||
return header()->heap_begin() + spc->mapping_offset() + HeapShared::runtime_delta();
|
return header()->heap_begin() + spc->mapping_offset() + ArchiveHeapLoader::runtime_delta();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileMapInfo::set_shared_heap_runtime_delta(ptrdiff_t delta) {
|
void FileMapInfo::set_shared_heap_runtime_delta(ptrdiff_t delta) {
|
||||||
if (UseCompressedOops) {
|
if (UseCompressedOops) {
|
||||||
HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift());
|
ArchiveHeapLoader::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift());
|
||||||
} else {
|
} else {
|
||||||
HeapShared::set_runtime_delta(delta);
|
ArchiveHeapLoader::set_runtime_delta(delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2209,14 +2210,14 @@ void FileMapInfo::map_heap_regions_impl() {
|
|||||||
MetaspaceShared::max_num_closed_heap_regions,
|
MetaspaceShared::max_num_closed_heap_regions,
|
||||||
/*is_open_archive=*/ false,
|
/*is_open_archive=*/ false,
|
||||||
&closed_heap_regions, &num_closed_heap_regions)) {
|
&closed_heap_regions, &num_closed_heap_regions)) {
|
||||||
HeapShared::set_closed_regions_mapped();
|
ArchiveHeapLoader::set_closed_regions_mapped();
|
||||||
|
|
||||||
// Now, map the open heap regions: GC can write into these regions.
|
// Now, map the open heap regions: GC can write into these regions.
|
||||||
if (map_heap_regions(MetaspaceShared::first_open_heap_region,
|
if (map_heap_regions(MetaspaceShared::first_open_heap_region,
|
||||||
MetaspaceShared::max_num_open_heap_regions,
|
MetaspaceShared::max_num_open_heap_regions,
|
||||||
/*is_open_archive=*/ true,
|
/*is_open_archive=*/ true,
|
||||||
&open_heap_regions, &num_open_heap_regions)) {
|
&open_heap_regions, &num_open_heap_regions)) {
|
||||||
HeapShared::set_open_regions_mapped();
|
ArchiveHeapLoader::set_open_regions_mapped();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2224,12 +2225,12 @@ void FileMapInfo::map_heap_regions_impl() {
|
|||||||
bool FileMapInfo::map_heap_regions() {
|
bool FileMapInfo::map_heap_regions() {
|
||||||
map_heap_regions_impl();
|
map_heap_regions_impl();
|
||||||
|
|
||||||
if (!HeapShared::closed_regions_mapped()) {
|
if (!ArchiveHeapLoader::closed_regions_mapped()) {
|
||||||
assert(closed_heap_regions == NULL &&
|
assert(closed_heap_regions == NULL &&
|
||||||
num_closed_heap_regions == 0, "sanity");
|
num_closed_heap_regions == 0, "sanity");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!HeapShared::open_regions_mapped()) {
|
if (!ArchiveHeapLoader::open_regions_mapped()) {
|
||||||
assert(open_heap_regions == NULL && num_open_heap_regions == 0, "sanity");
|
assert(open_heap_regions == NULL && num_open_heap_regions == 0, "sanity");
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -2336,7 +2337,7 @@ void FileMapInfo::patch_heap_embedded_pointers(MemRegion* regions, int num_regio
|
|||||||
assert(bitmap_base != NULL, "must have already been mapped");
|
assert(bitmap_base != NULL, "must have already been mapped");
|
||||||
for (int i=0; i<num_regions; i++) {
|
for (int i=0; i<num_regions; i++) {
|
||||||
FileMapRegion* si = space_at(i + first_region_idx);
|
FileMapRegion* si = space_at(i + first_region_idx);
|
||||||
HeapShared::patch_embedded_pointers(
|
ArchiveHeapLoader::patch_embedded_pointers(
|
||||||
regions[i],
|
regions[i],
|
||||||
(address)(space_at(MetaspaceShared::bm)->mapped_base()) + si->oopmap_offset(),
|
(address)(space_at(MetaspaceShared::bm)->mapped_base()) + si->oopmap_offset(),
|
||||||
si->oopmap_size_in_bits());
|
si->oopmap_size_in_bits());
|
||||||
|
@ -24,10 +24,10 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "cds/archiveBuilder.hpp"
|
#include "cds/archiveBuilder.hpp"
|
||||||
|
#include "cds/archiveHeapLoader.hpp"
|
||||||
#include "cds/archiveUtils.hpp"
|
#include "cds/archiveUtils.hpp"
|
||||||
#include "cds/cdsHeapVerifier.hpp"
|
#include "cds/cdsHeapVerifier.hpp"
|
||||||
#include "cds/filemap.hpp"
|
#include "cds/heapShared.hpp"
|
||||||
#include "cds/heapShared.inline.hpp"
|
|
||||||
#include "cds/metaspaceShared.hpp"
|
#include "cds/metaspaceShared.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderData.hpp"
|
||||||
#include "classfile/classLoaderDataShared.hpp"
|
#include "classfile/classLoaderDataShared.hpp"
|
||||||
@ -45,8 +45,6 @@
|
|||||||
#include "logging/log.hpp"
|
#include "logging/log.hpp"
|
||||||
#include "logging/logStream.hpp"
|
#include "logging/logStream.hpp"
|
||||||
#include "memory/iterator.inline.hpp"
|
#include "memory/iterator.inline.hpp"
|
||||||
#include "memory/metadataFactory.hpp"
|
|
||||||
#include "memory/metaspaceClosure.hpp"
|
|
||||||
#include "memory/resourceArea.hpp"
|
#include "memory/resourceArea.hpp"
|
||||||
#include "memory/universe.hpp"
|
#include "memory/universe.hpp"
|
||||||
#include "oops/compressedOops.inline.hpp"
|
#include "oops/compressedOops.inline.hpp"
|
||||||
@ -56,9 +54,7 @@
|
|||||||
#include "oops/typeArrayOop.inline.hpp"
|
#include "oops/typeArrayOop.inline.hpp"
|
||||||
#include "prims/jvmtiExport.hpp"
|
#include "prims/jvmtiExport.hpp"
|
||||||
#include "runtime/fieldDescriptor.inline.hpp"
|
#include "runtime/fieldDescriptor.inline.hpp"
|
||||||
#include "runtime/globals_extension.hpp"
|
|
||||||
#include "runtime/init.hpp"
|
#include "runtime/init.hpp"
|
||||||
#include "runtime/java.hpp"
|
|
||||||
#include "runtime/javaCalls.hpp"
|
#include "runtime/javaCalls.hpp"
|
||||||
#include "runtime/safepointVerifiers.hpp"
|
#include "runtime/safepointVerifiers.hpp"
|
||||||
#include "utilities/bitMap.inline.hpp"
|
#include "utilities/bitMap.inline.hpp"
|
||||||
@ -69,31 +65,9 @@
|
|||||||
|
|
||||||
#if INCLUDE_CDS_JAVA_HEAP
|
#if INCLUDE_CDS_JAVA_HEAP
|
||||||
|
|
||||||
bool HeapShared::_closed_regions_mapped = false;
|
|
||||||
bool HeapShared::_open_regions_mapped = false;
|
|
||||||
bool HeapShared::_is_loaded = false;
|
|
||||||
bool HeapShared::_disable_writing = false;
|
bool HeapShared::_disable_writing = false;
|
||||||
address HeapShared::_narrow_oop_base;
|
|
||||||
int HeapShared::_narrow_oop_shift;
|
|
||||||
DumpedInternedStrings *HeapShared::_dumped_interned_strings = NULL;
|
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;
|
|
||||||
uintptr_t HeapShared::_dumptime_base_1 = UINTPTR_MAX;
|
|
||||||
uintptr_t HeapShared::_dumptime_base_2 = UINTPTR_MAX;
|
|
||||||
uintptr_t HeapShared::_dumptime_base_3 = UINTPTR_MAX;
|
|
||||||
uintptr_t HeapShared::_dumptime_top = 0;
|
|
||||||
intx HeapShared::_runtime_offset_0 = 0;
|
|
||||||
intx HeapShared::_runtime_offset_1 = 0;
|
|
||||||
intx HeapShared::_runtime_offset_2 = 0;
|
|
||||||
intx HeapShared::_runtime_offset_3 = 0;
|
|
||||||
bool HeapShared::_loading_failed = false;
|
|
||||||
|
|
||||||
// Support 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!
|
// If you add new entries to the following tables, you should know what you're doing!
|
||||||
//
|
//
|
||||||
@ -162,22 +136,6 @@ bool HeapShared::is_subgraph_root_class(InstanceKlass* ik) {
|
|||||||
num_fmg_open_archive_subgraph_entry_fields, ik);
|
num_fmg_open_archive_subgraph_entry_fields, ik);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeapShared::fixup_regions() {
|
|
||||||
FileMapInfo* mapinfo = FileMapInfo::current_info();
|
|
||||||
if (is_mapped()) {
|
|
||||||
mapinfo->fixup_mapped_heap_regions();
|
|
||||||
} else if (_loading_failed) {
|
|
||||||
fill_failed_loaded_region();
|
|
||||||
}
|
|
||||||
if (is_fully_available()) {
|
|
||||||
if (!MetaspaceShared::use_full_module_graph()) {
|
|
||||||
// Need to remove all the archived java.lang.Module objects from HeapShared::roots().
|
|
||||||
ClassLoaderDataShared::clear_archived_oops();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SystemDictionaryShared::update_archived_mirror_native_pointers();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned HeapShared::oop_hash(oop const& p) {
|
unsigned HeapShared::oop_hash(oop const& p) {
|
||||||
// Do not call p->identity_hash() as that will update the
|
// Do not call p->identity_hash() as that will update the
|
||||||
// object header.
|
// object header.
|
||||||
@ -293,7 +251,7 @@ oop HeapShared::get_root(int index, bool clear) {
|
|||||||
void HeapShared::clear_root(int index) {
|
void HeapShared::clear_root(int index) {
|
||||||
assert(index >= 0, "sanity");
|
assert(index >= 0, "sanity");
|
||||||
assert(UseSharedSpaces, "must be");
|
assert(UseSharedSpaces, "must be");
|
||||||
if (is_fully_available()) {
|
if (ArchiveHeapLoader::is_fully_available()) {
|
||||||
if (log_is_enabled(Debug, cds, heap)) {
|
if (log_is_enabled(Debug, cds, heap)) {
|
||||||
oop old = roots()->obj_at(index);
|
oop old = roots()->obj_at(index);
|
||||||
log_debug(cds, heap)("Clearing root %d: was " PTR_FORMAT, index, p2i(old));
|
log_debug(cds, heap)("Clearing root %d: was " PTR_FORMAT, index, p2i(old));
|
||||||
@ -438,7 +396,7 @@ void HeapShared::check_enum_obj(int level,
|
|||||||
|
|
||||||
// See comments in HeapShared::check_enum_obj()
|
// See comments in HeapShared::check_enum_obj()
|
||||||
bool HeapShared::initialize_enum_klass(InstanceKlass* k, TRAPS) {
|
bool HeapShared::initialize_enum_klass(InstanceKlass* k, TRAPS) {
|
||||||
if (!is_fully_available()) {
|
if (!ArchiveHeapLoader::is_fully_available()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,11 +543,6 @@ void HeapShared::copy_roots() {
|
|||||||
log_info(cds)("archived obj roots[%d] = " SIZE_FORMAT " words, klass = %p, obj = %p", length, size, k, mem);
|
log_info(cds)("archived obj roots[%d] = " SIZE_FORMAT " words, klass = %p, obj = %p", length, size, k, mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeapShared::init_narrow_oop_decoding(address base, int shift) {
|
|
||||||
_narrow_oop_base = base;
|
|
||||||
_narrow_oop_shift = shift;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Subgraph archiving support
|
// Subgraph archiving support
|
||||||
//
|
//
|
||||||
@ -810,7 +763,7 @@ void HeapShared::serialize(SerializeClosure* soc) {
|
|||||||
assert(oopDesc::is_oop_or_null(roots_oop), "is oop");
|
assert(oopDesc::is_oop_or_null(roots_oop), "is oop");
|
||||||
// Create an OopHandle only if we have actually mapped or loaded the roots
|
// Create an OopHandle only if we have actually mapped or loaded the roots
|
||||||
if (roots_oop != NULL) {
|
if (roots_oop != NULL) {
|
||||||
assert(HeapShared::is_fully_available(), "must be");
|
assert(ArchiveHeapLoader::is_fully_available(), "must be");
|
||||||
_roots = OopHandle(Universe::vm_global(), roots_oop);
|
_roots = OopHandle(Universe::vm_global(), roots_oop);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -856,7 +809,7 @@ static void verify_the_heap(Klass* k, const char* which) {
|
|||||||
// ClassFileLoadHook is enabled, it's possible for this class to be dynamically replaced. In
|
// ClassFileLoadHook is enabled, it's possible for this class to be dynamically replaced. In
|
||||||
// this case, we will not load the ArchivedKlassSubGraphInfoRecord and will clear its roots.
|
// this case, we will not load the ArchivedKlassSubGraphInfoRecord and will clear its roots.
|
||||||
void HeapShared::resolve_classes(JavaThread* THREAD) {
|
void HeapShared::resolve_classes(JavaThread* THREAD) {
|
||||||
if (!is_fully_available()) {
|
if (!ArchiveHeapLoader::is_fully_available()) {
|
||||||
return; // nothing to do
|
return; // nothing to do
|
||||||
}
|
}
|
||||||
resolve_classes_for_subgraphs(closed_archive_subgraph_entry_fields,
|
resolve_classes_for_subgraphs(closed_archive_subgraph_entry_fields,
|
||||||
@ -894,7 +847,7 @@ void HeapShared::resolve_classes_for_subgraph_of(Klass* k, JavaThread* THREAD) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HeapShared::initialize_from_archived_subgraph(Klass* k, JavaThread* THREAD) {
|
void HeapShared::initialize_from_archived_subgraph(Klass* k, JavaThread* THREAD) {
|
||||||
if (!is_fully_available()) {
|
if (!ArchiveHeapLoader::is_fully_available()) {
|
||||||
return; // nothing to do
|
return; // nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1663,351 +1616,4 @@ ResourceBitMap HeapShared::calculate_oopmap(MemRegion region) {
|
|||||||
return oopmap;
|
return oopmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Patch all the embedded oop pointers inside an archived heap region,
|
|
||||||
// to be consistent with the runtime oop encoding.
|
|
||||||
class PatchCompressedEmbeddedPointers: public BitMapClosure {
|
|
||||||
narrowOop* _start;
|
|
||||||
|
|
||||||
public:
|
|
||||||
PatchCompressedEmbeddedPointers(narrowOop* start) : _start(start) {}
|
|
||||||
|
|
||||||
bool do_bit(size_t offset) {
|
|
||||||
narrowOop* p = _start + offset;
|
|
||||||
narrowOop v = *p;
|
|
||||||
assert(!CompressedOops::is_null(v), "null oops should have been filtered out at dump time");
|
|
||||||
oop o = HeapShared::decode_from_archive(v);
|
|
||||||
RawAccess<IS_NOT_NULL>::oop_store(p, o);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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,
|
|
||||||
size_t oopmap_size_in_bits) {
|
|
||||||
BitMapView bm((BitMap::bm_word_t*)oopmap, oopmap_size_in_bits);
|
|
||||||
|
|
||||||
#ifndef PRODUCT
|
|
||||||
ResourceMark rm;
|
|
||||||
ResourceBitMap checkBm = calculate_oopmap(region);
|
|
||||||
assert(bm.is_same(checkBm), "sanity");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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
|
|
||||||
// the heap object may be loaded at a different address at run time. This structure is used
|
|
||||||
// to translate the dump time addresses for all objects in FileMapInfo::space_at(region_index)
|
|
||||||
// to their runtime addresses.
|
|
||||||
struct LoadedArchiveHeapRegion {
|
|
||||||
int _region_index; // index for FileMapInfo::space_at(index)
|
|
||||||
size_t _region_size; // number of bytes in this region
|
|
||||||
uintptr_t _dumptime_base; // The dump-time (decoded) address of the first object in this region
|
|
||||||
intx _runtime_offset; // If an object's dump time address P is within in this region, its
|
|
||||||
// runtime address is P + _runtime_offset
|
|
||||||
|
|
||||||
static int comparator(const void* a, const void* b) {
|
|
||||||
LoadedArchiveHeapRegion* reg_a = (LoadedArchiveHeapRegion*)a;
|
|
||||||
LoadedArchiveHeapRegion* reg_b = (LoadedArchiveHeapRegion*)b;
|
|
||||||
if (reg_a->_dumptime_base < reg_b->_dumptime_base) {
|
|
||||||
return -1;
|
|
||||||
} else if (reg_a->_dumptime_base == reg_b->_dumptime_base) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t top() {
|
|
||||||
return _dumptime_base + _region_size;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void HeapShared::init_loaded_heap_relocation(LoadedArchiveHeapRegion* 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;
|
|
||||||
_dumptime_base_3 = loaded_regions[3]._dumptime_base;
|
|
||||||
_dumptime_top = loaded_regions[num_loaded_regions-1].top();
|
|
||||||
|
|
||||||
_runtime_offset_0 = loaded_regions[0]._runtime_offset;
|
|
||||||
_runtime_offset_1 = loaded_regions[1]._runtime_offset;
|
|
||||||
_runtime_offset_2 = loaded_regions[2]._runtime_offset;
|
|
||||||
_runtime_offset_3 = loaded_regions[3]._runtime_offset;
|
|
||||||
|
|
||||||
assert(2 <= num_loaded_regions && num_loaded_regions <= 4, "must be");
|
|
||||||
if (num_loaded_regions < 4) {
|
|
||||||
_dumptime_base_3 = UINTPTR_MAX;
|
|
||||||
}
|
|
||||||
if (num_loaded_regions < 3) {
|
|
||||||
_dumptime_base_2 = UINTPTR_MAX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HeapShared::can_load() {
|
|
||||||
return Universe::heap()->can_load_archived_objects();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <int NUM_LOADED_REGIONS>
|
|
||||||
class PatchLoadedRegionPointers: public BitMapClosure {
|
|
||||||
narrowOop* _start;
|
|
||||||
intx _offset_0;
|
|
||||||
intx _offset_1;
|
|
||||||
intx _offset_2;
|
|
||||||
intx _offset_3;
|
|
||||||
uintptr_t _base_0;
|
|
||||||
uintptr_t _base_1;
|
|
||||||
uintptr_t _base_2;
|
|
||||||
uintptr_t _base_3;
|
|
||||||
uintptr_t _top;
|
|
||||||
|
|
||||||
static_assert(MetaspaceShared::max_num_heap_regions == 4, "can't handle more than 4 regions");
|
|
||||||
static_assert(NUM_LOADED_REGIONS >= 2, "we have at least 2 loaded regions");
|
|
||||||
static_assert(NUM_LOADED_REGIONS <= 4, "we have at most 4 loaded regions");
|
|
||||||
|
|
||||||
public:
|
|
||||||
PatchLoadedRegionPointers(narrowOop* start, LoadedArchiveHeapRegion* loaded_regions)
|
|
||||||
: _start(start),
|
|
||||||
_offset_0(loaded_regions[0]._runtime_offset),
|
|
||||||
_offset_1(loaded_regions[1]._runtime_offset),
|
|
||||||
_offset_2(loaded_regions[2]._runtime_offset),
|
|
||||||
_offset_3(loaded_regions[3]._runtime_offset),
|
|
||||||
_base_0(loaded_regions[0]._dumptime_base),
|
|
||||||
_base_1(loaded_regions[1]._dumptime_base),
|
|
||||||
_base_2(loaded_regions[2]._dumptime_base),
|
|
||||||
_base_3(loaded_regions[3]._dumptime_base) {
|
|
||||||
_top = loaded_regions[NUM_LOADED_REGIONS-1].top();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool do_bit(size_t offset) {
|
|
||||||
narrowOop* p = _start + offset;
|
|
||||||
narrowOop v = *p;
|
|
||||||
assert(!CompressedOops::is_null(v), "null oops should have been filtered out at dump time");
|
|
||||||
uintptr_t o = cast_from_oop<uintptr_t>(HeapShared::decode_from_archive(v));
|
|
||||||
assert(_base_0 <= o && o < _top, "must be");
|
|
||||||
|
|
||||||
|
|
||||||
// We usually have only 2 regions for the default archive. Use template to avoid unnecessary comparisons.
|
|
||||||
if (NUM_LOADED_REGIONS > 3 && o >= _base_3) {
|
|
||||||
o += _offset_3;
|
|
||||||
} else if (NUM_LOADED_REGIONS > 2 && o >= _base_2) {
|
|
||||||
o += _offset_2;
|
|
||||||
} else if (o >= _base_1) {
|
|
||||||
o += _offset_1;
|
|
||||||
} else {
|
|
||||||
o += _offset_0;
|
|
||||||
}
|
|
||||||
HeapShared::assert_in_loaded_heap(o);
|
|
||||||
RawAccess<IS_NOT_NULL>::oop_store(p, cast_to_oop(o));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int HeapShared::init_loaded_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_regions,
|
|
||||||
MemRegion& archive_space) {
|
|
||||||
size_t total_bytes = 0;
|
|
||||||
int num_loaded_regions = 0;
|
|
||||||
for (int i = MetaspaceShared::first_archive_heap_region;
|
|
||||||
i <= MetaspaceShared::last_archive_heap_region; i++) {
|
|
||||||
FileMapRegion* r = mapinfo->space_at(i);
|
|
||||||
r->assert_is_heap_region();
|
|
||||||
if (r->used() > 0) {
|
|
||||||
assert(is_aligned(r->used(), HeapWordSize), "must be");
|
|
||||||
total_bytes += r->used();
|
|
||||||
LoadedArchiveHeapRegion* ri = &loaded_regions[num_loaded_regions++];
|
|
||||||
ri->_region_index = i;
|
|
||||||
ri->_region_size = r->used();
|
|
||||||
ri->_dumptime_base = (uintptr_t)mapinfo->start_address_as_decoded_from_archive(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(is_aligned(total_bytes, HeapWordSize), "must be");
|
|
||||||
size_t word_size = total_bytes / HeapWordSize;
|
|
||||||
HeapWord* buffer = Universe::heap()->allocate_loaded_archive_space(word_size);
|
|
||||||
if (buffer == nullptr) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
archive_space = MemRegion(buffer, word_size);
|
|
||||||
_loaded_heap_bottom = (uintptr_t)archive_space.start();
|
|
||||||
_loaded_heap_top = _loaded_heap_bottom + total_bytes;
|
|
||||||
|
|
||||||
return num_loaded_regions;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HeapShared::sort_loaded_regions(LoadedArchiveHeapRegion* loaded_regions, int num_loaded_regions,
|
|
||||||
uintptr_t buffer) {
|
|
||||||
// Find the relocation offset of the pointers in each region
|
|
||||||
qsort(loaded_regions, num_loaded_regions, sizeof(LoadedArchiveHeapRegion),
|
|
||||||
LoadedArchiveHeapRegion::comparator);
|
|
||||||
|
|
||||||
uintptr_t p = buffer;
|
|
||||||
for (int i = 0; i < num_loaded_regions; i++) {
|
|
||||||
// This region will be loaded at p, so all objects inside this
|
|
||||||
// region will be shifted by ri->offset
|
|
||||||
LoadedArchiveHeapRegion* ri = &loaded_regions[i];
|
|
||||||
ri->_runtime_offset = p - ri->_dumptime_base;
|
|
||||||
p += ri->_region_size;
|
|
||||||
}
|
|
||||||
assert(p == _loaded_heap_top, "must be");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HeapShared::load_regions(FileMapInfo* mapinfo, LoadedArchiveHeapRegion* loaded_regions,
|
|
||||||
int num_loaded_regions, uintptr_t buffer) {
|
|
||||||
uintptr_t bitmap_base = (uintptr_t)mapinfo->map_bitmap_region();
|
|
||||||
if (bitmap_base == 0) {
|
|
||||||
_loading_failed = true;
|
|
||||||
return false; // OOM or CRC error
|
|
||||||
}
|
|
||||||
uintptr_t load_address = buffer;
|
|
||||||
for (int i = 0; i < num_loaded_regions; i++) {
|
|
||||||
LoadedArchiveHeapRegion* ri = &loaded_regions[i];
|
|
||||||
FileMapRegion* r = mapinfo->space_at(ri->_region_index);
|
|
||||||
|
|
||||||
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.
|
|
||||||
log_warning(cds)("Loading of heap region %d has failed. Archived objects are disabled", i);
|
|
||||||
_loading_failed = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
log_info(cds)("Loaded heap region #%d at base " INTPTR_FORMAT " top " INTPTR_FORMAT
|
|
||||||
" size " SIZE_FORMAT_W(6) " delta " INTX_FORMAT,
|
|
||||||
ri->_region_index, load_address, load_address + ri->_region_size,
|
|
||||||
ri->_region_size, ri->_runtime_offset);
|
|
||||||
|
|
||||||
uintptr_t oopmap = bitmap_base + r->oopmap_offset();
|
|
||||||
BitMapView bm((BitMap::bm_word_t*)oopmap, r->oopmap_size_in_bits());
|
|
||||||
|
|
||||||
if (num_loaded_regions == 4) {
|
|
||||||
PatchLoadedRegionPointers<4> patcher((narrowOop*)load_address, loaded_regions);
|
|
||||||
bm.iterate(&patcher);
|
|
||||||
} else if (num_loaded_regions == 3) {
|
|
||||||
PatchLoadedRegionPointers<3> patcher((narrowOop*)load_address, loaded_regions);
|
|
||||||
bm.iterate(&patcher);
|
|
||||||
} else {
|
|
||||||
assert(num_loaded_regions == 2, "must be");
|
|
||||||
PatchLoadedRegionPointers<2> patcher((narrowOop*)load_address, loaded_regions);
|
|
||||||
bm.iterate(&patcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
load_address += r->used();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HeapShared::load_heap_regions(FileMapInfo* mapinfo) {
|
|
||||||
init_narrow_oop_decoding(mapinfo->narrow_oop_base(), mapinfo->narrow_oop_shift());
|
|
||||||
|
|
||||||
LoadedArchiveHeapRegion loaded_regions[MetaspaceShared::max_num_heap_regions];
|
|
||||||
memset(loaded_regions, 0, sizeof(loaded_regions));
|
|
||||||
|
|
||||||
MemRegion archive_space;
|
|
||||||
int num_loaded_regions = init_loaded_regions(mapinfo, loaded_regions, archive_space);
|
|
||||||
if (num_loaded_regions <= 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sort_loaded_regions(loaded_regions, num_loaded_regions, (uintptr_t)archive_space.start());
|
|
||||||
if (!load_regions(mapinfo, loaded_regions, num_loaded_regions, (uintptr_t)archive_space.start())) {
|
|
||||||
assert(_loading_failed, "must be");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
init_loaded_heap_relocation(loaded_regions, num_loaded_regions);
|
|
||||||
_is_loaded = true;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
class VerifyLoadedHeapEmbeddedPointers: public BasicOopIterateClosure {
|
|
||||||
ResourceHashtable<uintptr_t, bool>* _table;
|
|
||||||
|
|
||||||
public:
|
|
||||||
VerifyLoadedHeapEmbeddedPointers(ResourceHashtable<uintptr_t, bool>* table) : _table(table) {}
|
|
||||||
|
|
||||||
virtual void do_oop(narrowOop* p) {
|
|
||||||
// This should be called before the loaded regions are modified, so all the embedded pointers
|
|
||||||
// must be NULL, or must point to a valid object in the loaded regions.
|
|
||||||
narrowOop v = *p;
|
|
||||||
if (!CompressedOops::is_null(v)) {
|
|
||||||
oop o = CompressedOops::decode_not_null(v);
|
|
||||||
uintptr_t u = cast_from_oop<uintptr_t>(o);
|
|
||||||
HeapShared::assert_in_loaded_heap(u);
|
|
||||||
guarantee(_table->contains(u), "must point to beginning of object in loaded archived regions");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
virtual void do_oop(oop* p) {
|
|
||||||
ShouldNotReachHere();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void HeapShared::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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VerifyArchivedFields <= 0 || !is_loaded()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info(cds, heap)("Verify all oops and pointers in loaded heap");
|
|
||||||
|
|
||||||
ResourceMark rm;
|
|
||||||
ResourceHashtable<uintptr_t, bool> table;
|
|
||||||
VerifyLoadedHeapEmbeddedPointers verifier(&table);
|
|
||||||
HeapWord* bottom = (HeapWord*)_loaded_heap_bottom;
|
|
||||||
HeapWord* top = (HeapWord*)_loaded_heap_top;
|
|
||||||
|
|
||||||
for (HeapWord* p = bottom; p < top; ) {
|
|
||||||
oop o = cast_to_oop(p);
|
|
||||||
table.put(cast_from_oop<uintptr_t>(o), true);
|
|
||||||
p += o->size();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (HeapWord* p = bottom; p < top; ) {
|
|
||||||
oop o = cast_to_oop(p);
|
|
||||||
o->oop_iterate(&verifier);
|
|
||||||
p += o->size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void HeapShared::fill_failed_loaded_region() {
|
|
||||||
assert(_loading_failed, "must be");
|
|
||||||
if (_loaded_heap_bottom != 0) {
|
|
||||||
assert(_loaded_heap_top != 0, "must be");
|
|
||||||
HeapWord* bottom = (HeapWord*)_loaded_heap_bottom;
|
|
||||||
HeapWord* top = (HeapWord*)_loaded_heap_top;
|
|
||||||
Universe::heap()->fill_with_objects(bottom, top - bottom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // INCLUDE_CDS_JAVA_HEAP
|
#endif // INCLUDE_CDS_JAVA_HEAP
|
||||||
|
@ -29,16 +29,13 @@
|
|||||||
#include "cds/metaspaceShared.hpp"
|
#include "cds/metaspaceShared.hpp"
|
||||||
#include "classfile/compactHashtable.hpp"
|
#include "classfile/compactHashtable.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
|
||||||
#include "gc/shared/gc_globals.hpp"
|
#include "gc/shared/gc_globals.hpp"
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
|
#include "memory/allStatic.hpp"
|
||||||
#include "oops/compressedOops.hpp"
|
#include "oops/compressedOops.hpp"
|
||||||
#include "oops/objArrayKlass.hpp"
|
|
||||||
#include "oops/oop.hpp"
|
#include "oops/oop.hpp"
|
||||||
#include "oops/oopHandle.hpp"
|
#include "oops/oopHandle.hpp"
|
||||||
#include "oops/oopsHierarchy.hpp"
|
#include "oops/oopsHierarchy.hpp"
|
||||||
#include "oops/typeArrayKlass.hpp"
|
|
||||||
#include "utilities/bitMap.hpp"
|
|
||||||
#include "utilities/growableArray.hpp"
|
#include "utilities/growableArray.hpp"
|
||||||
#include "utilities/resourceHash.hpp"
|
#include "utilities/resourceHash.hpp"
|
||||||
|
|
||||||
@ -46,6 +43,7 @@
|
|||||||
class DumpedInternedStrings;
|
class DumpedInternedStrings;
|
||||||
class FileMapInfo;
|
class FileMapInfo;
|
||||||
class KlassSubGraphInfo;
|
class KlassSubGraphInfo;
|
||||||
|
class ResourceBitMap;
|
||||||
|
|
||||||
struct ArchivableStaticFieldInfo {
|
struct ArchivableStaticFieldInfo {
|
||||||
const char* klass_name;
|
const char* klass_name;
|
||||||
@ -148,14 +146,6 @@ class HeapShared: AllStatic {
|
|||||||
friend class VerifySharedOopClosure;
|
friend class VerifySharedOopClosure;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// At runtime, heap regions in the CDS archive can be used in two different ways,
|
|
||||||
// depending on the GC type:
|
|
||||||
// - Mapped: (G1 only) the regions are directly mapped into the Java heap
|
|
||||||
// - Loaded: At VM start-up, the objects in the heap regions are copied into the
|
|
||||||
// Java heap. This is easier to implement than mapping but
|
|
||||||
// slightly less efficient, as the embedded pointers need to be relocated.
|
|
||||||
static bool can_use() { return can_map() || can_load(); }
|
|
||||||
|
|
||||||
// Can this VM write heap regions into the CDS archive? Currently only G1+compressed{oops,cp}
|
// Can this VM write heap regions into the CDS archive? Currently only G1+compressed{oops,cp}
|
||||||
static bool can_write() {
|
static bool can_write() {
|
||||||
CDS_JAVA_HEAP_ONLY(
|
CDS_JAVA_HEAP_ONLY(
|
||||||
@ -170,67 +160,19 @@ public:
|
|||||||
static void disable_writing() {
|
static void disable_writing() {
|
||||||
CDS_JAVA_HEAP_ONLY(_disable_writing = true;)
|
CDS_JAVA_HEAP_ONLY(_disable_writing = true;)
|
||||||
}
|
}
|
||||||
// Can this VM map archived heap regions? Currently only G1+compressed{oops,cp}
|
|
||||||
static bool can_map() {
|
|
||||||
CDS_JAVA_HEAP_ONLY(return (UseG1GC && UseCompressedClassPointers);)
|
|
||||||
NOT_CDS_JAVA_HEAP(return false;)
|
|
||||||
}
|
|
||||||
static bool is_mapped() {
|
|
||||||
return closed_regions_mapped() && open_regions_mapped();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can this VM load the objects from archived heap regions into the heap at start-up?
|
|
||||||
static bool can_load() NOT_CDS_JAVA_HEAP_RETURN_(false);
|
|
||||||
static void finish_initialization() NOT_CDS_JAVA_HEAP_RETURN;
|
|
||||||
static bool is_loaded() {
|
|
||||||
CDS_JAVA_HEAP_ONLY(return _is_loaded;)
|
|
||||||
NOT_CDS_JAVA_HEAP(return false;)
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool are_archived_strings_available() {
|
|
||||||
return is_loaded() || closed_regions_mapped();
|
|
||||||
}
|
|
||||||
static bool are_archived_mirrors_available() {
|
|
||||||
return is_fully_available();
|
|
||||||
}
|
|
||||||
static bool is_fully_available() {
|
|
||||||
return is_loaded() || is_mapped();
|
|
||||||
}
|
|
||||||
static bool is_subgraph_root_class(InstanceKlass* ik);
|
static bool is_subgraph_root_class(InstanceKlass* ik);
|
||||||
private:
|
private:
|
||||||
#if INCLUDE_CDS_JAVA_HEAP
|
#if INCLUDE_CDS_JAVA_HEAP
|
||||||
static bool _disable_writing;
|
static bool _disable_writing;
|
||||||
static bool _closed_regions_mapped;
|
|
||||||
static bool _open_regions_mapped;
|
|
||||||
static bool _is_loaded;
|
|
||||||
static DumpedInternedStrings *_dumped_interned_strings;
|
static DumpedInternedStrings *_dumped_interned_strings;
|
||||||
|
|
||||||
// Support for loaded archived heap. These are cached values from
|
|
||||||
// LoadedArchiveHeapRegion's.
|
|
||||||
static uintptr_t _dumptime_base_0;
|
|
||||||
static uintptr_t _dumptime_base_1;
|
|
||||||
static uintptr_t _dumptime_base_2;
|
|
||||||
static uintptr_t _dumptime_base_3;
|
|
||||||
static uintptr_t _dumptime_top;
|
|
||||||
static intx _runtime_offset_0;
|
|
||||||
static intx _runtime_offset_1;
|
|
||||||
static intx _runtime_offset_2;
|
|
||||||
static intx _runtime_offset_3;
|
|
||||||
static uintptr_t _loaded_heap_bottom;
|
|
||||||
static uintptr_t _loaded_heap_top;
|
|
||||||
static bool _loading_failed;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static unsigned oop_hash(oop const& p);
|
static unsigned oop_hash(oop const& p);
|
||||||
static unsigned string_oop_hash(oop const& string) {
|
static unsigned string_oop_hash(oop const& string) {
|
||||||
return java_lang_String::hash_code(string);
|
return java_lang_String::hash_code(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool load_heap_regions(FileMapInfo* mapinfo);
|
|
||||||
static void assert_in_loaded_heap(uintptr_t o) {
|
|
||||||
assert(is_in_loaded_heap(o), "must be");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CachedOopInfo {
|
struct CachedOopInfo {
|
||||||
KlassSubGraphInfo* _subgraph_info;
|
KlassSubGraphInfo* _subgraph_info;
|
||||||
oop _referrer;
|
oop _referrer;
|
||||||
@ -243,9 +185,6 @@ private:
|
|||||||
KlassSubGraphInfo* subgraph_info,
|
KlassSubGraphInfo* subgraph_info,
|
||||||
oop orig_obj,
|
oop orig_obj,
|
||||||
bool is_closed_archive);
|
bool is_closed_archive);
|
||||||
static bool is_in_loaded_heap(uintptr_t o) {
|
|
||||||
return (_loaded_heap_bottom <= o && o < _loaded_heap_top);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef ResourceHashtable<oop, CachedOopInfo,
|
typedef ResourceHashtable<oop, CachedOopInfo,
|
||||||
36137, // prime number
|
36137, // prime number
|
||||||
@ -457,20 +396,9 @@ private:
|
|||||||
// Run-time only
|
// Run-time only
|
||||||
static void clear_root(int index);
|
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
|
#endif // INCLUDE_CDS_JAVA_HEAP
|
||||||
|
|
||||||
public:
|
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 void run_full_gc_in_vm_thread() NOT_CDS_JAVA_HEAP_RETURN;
|
||||||
|
|
||||||
static bool is_heap_region(int idx) {
|
static bool is_heap_region(int idx) {
|
||||||
@ -479,41 +407,11 @@ private:
|
|||||||
NOT_CDS_JAVA_HEAP_RETURN_(false);
|
NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_closed_regions_mapped() {
|
|
||||||
CDS_JAVA_HEAP_ONLY(_closed_regions_mapped = true;)
|
|
||||||
NOT_CDS_JAVA_HEAP_RETURN;
|
|
||||||
}
|
|
||||||
static bool closed_regions_mapped() {
|
|
||||||
CDS_JAVA_HEAP_ONLY(return _closed_regions_mapped;)
|
|
||||||
NOT_CDS_JAVA_HEAP_RETURN_(false);
|
|
||||||
}
|
|
||||||
static void set_open_regions_mapped() {
|
|
||||||
CDS_JAVA_HEAP_ONLY(_open_regions_mapped = true;)
|
|
||||||
NOT_CDS_JAVA_HEAP_RETURN;
|
|
||||||
}
|
|
||||||
static bool open_regions_mapped() {
|
|
||||||
CDS_JAVA_HEAP_ONLY(return _open_regions_mapped;)
|
|
||||||
NOT_CDS_JAVA_HEAP_RETURN_(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fixup_regions() NOT_CDS_JAVA_HEAP_RETURN;
|
|
||||||
|
|
||||||
static bool is_archived_object_during_dumptime(oop p) NOT_CDS_JAVA_HEAP_RETURN_(false);
|
static bool is_archived_object_during_dumptime(oop p) NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||||
|
|
||||||
static void resolve_classes(JavaThread* THREAD) NOT_CDS_JAVA_HEAP_RETURN;
|
static void resolve_classes(JavaThread* THREAD) NOT_CDS_JAVA_HEAP_RETURN;
|
||||||
static void initialize_from_archived_subgraph(Klass* k, JavaThread* THREAD) NOT_CDS_JAVA_HEAP_RETURN;
|
static void initialize_from_archived_subgraph(Klass* k, JavaThread* THREAD) NOT_CDS_JAVA_HEAP_RETURN;
|
||||||
|
|
||||||
// NarrowOops stored in the CDS archive may use a different encoding scheme
|
|
||||||
// than CompressedOops::{base,shift} -- see FileMapInfo::map_heap_regions_impl.
|
|
||||||
// To decode them, do not use CompressedOops::decode_not_null. Use this
|
|
||||||
// function instead.
|
|
||||||
inline static oop decode_from_archive(narrowOop v) NOT_CDS_JAVA_HEAP_RETURN_(NULL);
|
|
||||||
|
|
||||||
static void init_narrow_oop_decoding(address base, int shift) NOT_CDS_JAVA_HEAP_RETURN;
|
|
||||||
|
|
||||||
static void patch_embedded_pointers(MemRegion region, address oopmap,
|
|
||||||
size_t oopmap_in_bits) NOT_CDS_JAVA_HEAP_RETURN;
|
|
||||||
|
|
||||||
static void init_for_dumping(TRAPS) NOT_CDS_JAVA_HEAP_RETURN;
|
static void init_for_dumping(TRAPS) NOT_CDS_JAVA_HEAP_RETURN;
|
||||||
static void write_subgraph_info_table() NOT_CDS_JAVA_HEAP_RETURN;
|
static void write_subgraph_info_table() NOT_CDS_JAVA_HEAP_RETURN;
|
||||||
static void serialize(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN;
|
static void serialize(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "jvm_io.h"
|
#include "jvm_io.h"
|
||||||
#include "cds/archiveBuilder.hpp"
|
#include "cds/archiveBuilder.hpp"
|
||||||
|
#include "cds/archiveHeapLoader.hpp"
|
||||||
#include "cds/cds_globals.hpp"
|
#include "cds/cds_globals.hpp"
|
||||||
#include "cds/cdsProtectionDomain.hpp"
|
#include "cds/cdsProtectionDomain.hpp"
|
||||||
#include "cds/classListWriter.hpp"
|
#include "cds/classListWriter.hpp"
|
||||||
@ -1470,7 +1471,7 @@ void MetaspaceShared::initialize_shared_spaces() {
|
|||||||
// Finish up archived heap initialization. These must be
|
// Finish up archived heap initialization. These must be
|
||||||
// done after ReadClosure.
|
// done after ReadClosure.
|
||||||
static_mapinfo->patch_heap_embedded_pointers();
|
static_mapinfo->patch_heap_embedded_pointers();
|
||||||
HeapShared::finish_initialization();
|
ArchiveHeapLoader::finish_initialization();
|
||||||
|
|
||||||
// Close the mapinfo file
|
// Close the mapinfo file
|
||||||
static_mapinfo->close();
|
static_mapinfo->close();
|
||||||
@ -1557,7 +1558,7 @@ bool MetaspaceShared::use_full_module_graph() {
|
|||||||
if (DumpSharedSpaces) {
|
if (DumpSharedSpaces) {
|
||||||
result &= HeapShared::can_write();
|
result &= HeapShared::can_write();
|
||||||
} else if (UseSharedSpaces) {
|
} else if (UseSharedSpaces) {
|
||||||
result &= HeapShared::can_use();
|
result &= ArchiveHeapLoader::can_use();
|
||||||
} else {
|
} else {
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
#include "cds/archiveBuilder.hpp"
|
#include "cds/archiveBuilder.hpp"
|
||||||
#include "cds/cds_globals.hpp"
|
#include "cds/cds_globals.hpp"
|
||||||
#include "cds/heapShared.inline.hpp"
|
|
||||||
#include "classfile/compactHashtable.hpp"
|
#include "classfile/compactHashtable.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "logging/logMessage.hpp"
|
#include "logging/logMessage.hpp"
|
||||||
|
@ -25,7 +25,8 @@
|
|||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
#include "cds/archiveBuilder.hpp"
|
#include "cds/archiveBuilder.hpp"
|
||||||
#include "cds/heapShared.inline.hpp"
|
#include "cds/archiveHeapLoader.hpp"
|
||||||
|
#include "cds/heapShared.hpp"
|
||||||
#include "cds/metaspaceShared.hpp"
|
#include "cds/metaspaceShared.hpp"
|
||||||
#include "classfile/altHashing.hpp"
|
#include "classfile/altHashing.hpp"
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
@ -55,6 +56,7 @@
|
|||||||
#include "oops/klass.hpp"
|
#include "oops/klass.hpp"
|
||||||
#include "oops/klass.inline.hpp"
|
#include "oops/klass.inline.hpp"
|
||||||
#include "oops/method.inline.hpp"
|
#include "oops/method.inline.hpp"
|
||||||
|
#include "oops/objArrayKlass.hpp"
|
||||||
#include "oops/objArrayOop.inline.hpp"
|
#include "oops/objArrayOop.inline.hpp"
|
||||||
#include "oops/oopCast.inline.hpp"
|
#include "oops/oopCast.inline.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
@ -894,7 +896,7 @@ void java_lang_Class::fixup_mirror(Klass* k, TRAPS) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (k->is_shared() && k->has_archived_mirror_index()) {
|
if (k->is_shared() && k->has_archived_mirror_index()) {
|
||||||
if (HeapShared::are_archived_mirrors_available()) {
|
if (ArchiveHeapLoader::are_archived_mirrors_available()) {
|
||||||
bool present = restore_archived_mirror(k, Handle(), Handle(), Handle(), CHECK);
|
bool present = restore_archived_mirror(k, Handle(), Handle(), Handle(), CHECK);
|
||||||
assert(present, "Missing archived mirror for %s", k->external_name());
|
assert(present, "Missing archived mirror for %s", k->external_name());
|
||||||
return;
|
return;
|
||||||
@ -1321,7 +1323,7 @@ bool java_lang_Class::restore_archived_mirror(Klass *k,
|
|||||||
|
|
||||||
// mirror is archived, restore
|
// mirror is archived, restore
|
||||||
log_debug(cds, mirror)("Archived mirror is: " PTR_FORMAT, p2i(m));
|
log_debug(cds, mirror)("Archived mirror is: " PTR_FORMAT, p2i(m));
|
||||||
if (HeapShared::is_mapped()) {
|
if (ArchiveHeapLoader::is_mapped()) {
|
||||||
assert(Universe::heap()->is_archived_object(m), "must be archived mirror object");
|
assert(Universe::heap()->is_archived_object(m), "must be archived mirror object");
|
||||||
}
|
}
|
||||||
assert(as_Klass(m) == k, "must be");
|
assert(as_Klass(m) == k, "must be");
|
||||||
|
@ -24,8 +24,9 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "cds/archiveBuilder.hpp"
|
#include "cds/archiveBuilder.hpp"
|
||||||
|
#include "cds/archiveHeapLoader.inline.hpp"
|
||||||
#include "cds/filemap.hpp"
|
#include "cds/filemap.hpp"
|
||||||
#include "cds/heapShared.inline.hpp"
|
#include "cds/heapShared.hpp"
|
||||||
#include "classfile/altHashing.hpp"
|
#include "classfile/altHashing.hpp"
|
||||||
#include "classfile/compactHashtable.hpp"
|
#include "classfile/compactHashtable.hpp"
|
||||||
#include "classfile/javaClasses.inline.hpp"
|
#include "classfile/javaClasses.inline.hpp"
|
||||||
@ -74,13 +75,13 @@ inline oop read_string_from_compact_hashtable(address base_address, u4 offset) {
|
|||||||
if (UseCompressedOops) {
|
if (UseCompressedOops) {
|
||||||
assert(sizeof(narrowOop) == sizeof(offset), "must be");
|
assert(sizeof(narrowOop) == sizeof(offset), "must be");
|
||||||
narrowOop v = CompressedOops::narrow_oop_cast(offset);
|
narrowOop v = CompressedOops::narrow_oop_cast(offset);
|
||||||
return HeapShared::decode_from_archive(v);
|
return ArchiveHeapLoader::decode_from_archive(v);
|
||||||
} else {
|
} else {
|
||||||
intptr_t dumptime_oop = (uintptr_t)offset;
|
intptr_t dumptime_oop = (uintptr_t)offset;
|
||||||
assert(dumptime_oop != 0, "null strings cannot be interned");
|
assert(dumptime_oop != 0, "null strings cannot be interned");
|
||||||
intptr_t runtime_oop = dumptime_oop +
|
intptr_t runtime_oop = dumptime_oop +
|
||||||
(intptr_t)FileMapInfo::current_info()->header()->heap_begin() +
|
(intptr_t)FileMapInfo::current_info()->header()->heap_begin() +
|
||||||
(intptr_t)HeapShared::runtime_delta();
|
(intptr_t)ArchiveHeapLoader::runtime_delta();
|
||||||
return (oop)cast_to_oop(runtime_oop);
|
return (oop)cast_to_oop(runtime_oop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -831,7 +832,7 @@ void StringTable::serialize_shared_table_header(SerializeClosure* soc) {
|
|||||||
if (soc->writing()) {
|
if (soc->writing()) {
|
||||||
// Sanity. Make sure we don't use the shared table at dump time
|
// Sanity. Make sure we don't use the shared table at dump time
|
||||||
_shared_table.reset();
|
_shared_table.reset();
|
||||||
} else if (!HeapShared::are_archived_strings_available()) {
|
} else if (!ArchiveHeapLoader::are_archived_strings_available()) {
|
||||||
_shared_table.reset();
|
_shared_table.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -861,7 +862,7 @@ public:
|
|||||||
// _shared_table invalid. Therefore, we proactively copy all the shared
|
// _shared_table invalid. Therefore, we proactively copy all the shared
|
||||||
// strings into the _local_table, which can deal with oop relocation.
|
// strings into the _local_table, which can deal with oop relocation.
|
||||||
void StringTable::transfer_shared_strings_to_local_table() {
|
void StringTable::transfer_shared_strings_to_local_table() {
|
||||||
assert(HeapShared::is_loaded(), "must be");
|
assert(ArchiveHeapLoader::is_loaded(), "must be");
|
||||||
EXCEPTION_MARK;
|
EXCEPTION_MARK;
|
||||||
|
|
||||||
// Reset _shared_table so that during the transfer, StringTable::intern()
|
// Reset _shared_table so that during the transfer, StringTable::intern()
|
||||||
|
@ -23,13 +23,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "cds/archiveUtils.hpp"
|
|
||||||
#include "cds/archiveBuilder.hpp"
|
#include "cds/archiveBuilder.hpp"
|
||||||
|
#include "cds/archiveHeapLoader.hpp"
|
||||||
|
#include "cds/archiveUtils.hpp"
|
||||||
#include "cds/classListParser.hpp"
|
#include "cds/classListParser.hpp"
|
||||||
#include "cds/classListWriter.hpp"
|
#include "cds/classListWriter.hpp"
|
||||||
#include "cds/dynamicArchive.hpp"
|
#include "cds/dynamicArchive.hpp"
|
||||||
#include "cds/filemap.hpp"
|
#include "cds/filemap.hpp"
|
||||||
#include "cds/heapShared.hpp"
|
|
||||||
#include "cds/cdsProtectionDomain.hpp"
|
#include "cds/cdsProtectionDomain.hpp"
|
||||||
#include "cds/dumpTimeClassInfo.inline.hpp"
|
#include "cds/dumpTimeClassInfo.inline.hpp"
|
||||||
#include "cds/metaspaceShared.hpp"
|
#include "cds/metaspaceShared.hpp"
|
||||||
@ -60,6 +60,7 @@
|
|||||||
#include "memory/universe.hpp"
|
#include "memory/universe.hpp"
|
||||||
#include "oops/instanceKlass.hpp"
|
#include "oops/instanceKlass.hpp"
|
||||||
#include "oops/klass.inline.hpp"
|
#include "oops/klass.inline.hpp"
|
||||||
|
#include "oops/objArrayKlass.hpp"
|
||||||
#include "oops/objArrayOop.inline.hpp"
|
#include "oops/objArrayOop.inline.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "oops/oopHandle.inline.hpp"
|
#include "oops/oopHandle.inline.hpp"
|
||||||
@ -1599,7 +1600,7 @@ void SystemDictionaryShared::update_archived_mirror_native_pointers_for(LambdaPr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SystemDictionaryShared::update_archived_mirror_native_pointers() {
|
void SystemDictionaryShared::update_archived_mirror_native_pointers() {
|
||||||
if (!HeapShared::are_archived_mirrors_available()) {
|
if (!ArchiveHeapLoader::are_archived_mirrors_available()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (MetaspaceShared::relocation_delta() == 0) {
|
if (MetaspaceShared::relocation_delta() == 0) {
|
||||||
|
@ -23,10 +23,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "cds/heapShared.hpp"
|
#include "cds/archiveHeapLoader.hpp"
|
||||||
#include "classfile/classLoader.hpp"
|
#include "classfile/classLoader.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderData.hpp"
|
||||||
#include "classfile/dictionary.hpp"
|
#include "classfile/dictionary.hpp"
|
||||||
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/vmClasses.hpp"
|
#include "classfile/vmClasses.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
@ -135,13 +136,13 @@ void vmClasses::resolve_all(TRAPS) {
|
|||||||
// ConstantPool::restore_unshareable_info (restores the archived
|
// ConstantPool::restore_unshareable_info (restores the archived
|
||||||
// resolved_references array object).
|
// resolved_references array object).
|
||||||
//
|
//
|
||||||
// HeapShared::fixup_regions() fills the empty
|
// ArchiveHeapLoader::fixup_regions fills the empty
|
||||||
// spaces in the archived heap regions and may use
|
// spaces in the archived heap regions and may use
|
||||||
// vmClasses::Object_klass(), so we can do this only after
|
// vmClasses::Object_klass(), so we can do this only after
|
||||||
// Object_klass is resolved. See the above resolve_through()
|
// Object_klass is resolved. See the above resolve_through()
|
||||||
// call. No mirror objects are accessed/restored in the above call.
|
// call. No mirror objects are accessed/restored in the above call.
|
||||||
// Mirrors are restored after java.lang.Class is loaded.
|
// Mirrors are restored after java.lang.Class is loaded.
|
||||||
HeapShared::fixup_regions();
|
ArchiveHeapLoader::fixup_regions();
|
||||||
|
|
||||||
// Initialize the constant pool for the Object_class
|
// Initialize the constant pool for the Object_class
|
||||||
assert(Object_klass()->is_shared(), "must be");
|
assert(Object_klass()->is_shared(), "must be");
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "cds/archiveHeapLoader.hpp"
|
||||||
#include "cds/dynamicArchive.hpp"
|
#include "cds/dynamicArchive.hpp"
|
||||||
#include "cds/heapShared.hpp"
|
#include "cds/heapShared.hpp"
|
||||||
#include "cds/metaspaceShared.hpp"
|
#include "cds/metaspaceShared.hpp"
|
||||||
@ -451,9 +452,9 @@ void Universe::genesis(TRAPS) {
|
|||||||
void Universe::initialize_basic_type_mirrors(TRAPS) {
|
void Universe::initialize_basic_type_mirrors(TRAPS) {
|
||||||
#if INCLUDE_CDS_JAVA_HEAP
|
#if INCLUDE_CDS_JAVA_HEAP
|
||||||
if (UseSharedSpaces &&
|
if (UseSharedSpaces &&
|
||||||
HeapShared::are_archived_mirrors_available() &&
|
ArchiveHeapLoader::are_archived_mirrors_available() &&
|
||||||
_mirrors[T_INT].resolve() != NULL) {
|
_mirrors[T_INT].resolve() != NULL) {
|
||||||
assert(HeapShared::can_use(), "Sanity");
|
assert(ArchiveHeapLoader::can_use(), "Sanity");
|
||||||
|
|
||||||
// check that all mirrors are mapped also
|
// check that all mirrors are mapped also
|
||||||
for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
|
for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
|
||||||
@ -806,7 +807,7 @@ jint universe_init() {
|
|||||||
// currently mapped regions.
|
// currently mapped regions.
|
||||||
MetaspaceShared::initialize_shared_spaces();
|
MetaspaceShared::initialize_shared_spaces();
|
||||||
StringTable::create_table();
|
StringTable::create_table();
|
||||||
if (HeapShared::is_loaded()) {
|
if (ArchiveHeapLoader::is_loaded()) {
|
||||||
StringTable::transfer_shared_strings_to_local_table();
|
StringTable::transfer_shared_strings_to_local_table();
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "jvm.h"
|
#include "jvm.h"
|
||||||
|
#include "cds/archiveHeapLoader.hpp"
|
||||||
#include "cds/heapShared.hpp"
|
#include "cds/heapShared.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderData.hpp"
|
||||||
#include "classfile/javaClasses.inline.hpp"
|
#include "classfile/javaClasses.inline.hpp"
|
||||||
@ -346,7 +347,7 @@ void ConstantPool::restore_unshareable_info(TRAPS) {
|
|||||||
if (vmClasses::Object_klass_loaded()) {
|
if (vmClasses::Object_klass_loaded()) {
|
||||||
ClassLoaderData* loader_data = pool_holder()->class_loader_data();
|
ClassLoaderData* loader_data = pool_holder()->class_loader_data();
|
||||||
#if INCLUDE_CDS_JAVA_HEAP
|
#if INCLUDE_CDS_JAVA_HEAP
|
||||||
if (HeapShared::is_fully_available() &&
|
if (ArchiveHeapLoader::is_fully_available() &&
|
||||||
_cache->archived_references() != NULL) {
|
_cache->archived_references() != NULL) {
|
||||||
oop archived = _cache->archived_references();
|
oop archived = _cache->archived_references();
|
||||||
// Create handle for the archived resolved reference array object
|
// Create handle for the archived resolved reference array object
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "jvm_io.h"
|
#include "jvm_io.h"
|
||||||
|
#include "cds/archiveHeapLoader.hpp"
|
||||||
#include "cds/heapShared.hpp"
|
#include "cds/heapShared.hpp"
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
#include "classfile/classLoaderDataGraph.inline.hpp"
|
#include "classfile/classLoaderDataGraph.inline.hpp"
|
||||||
@ -43,6 +44,7 @@
|
|||||||
#include "oops/compressedOops.inline.hpp"
|
#include "oops/compressedOops.inline.hpp"
|
||||||
#include "oops/instanceKlass.hpp"
|
#include "oops/instanceKlass.hpp"
|
||||||
#include "oops/klass.inline.hpp"
|
#include "oops/klass.inline.hpp"
|
||||||
|
#include "oops/objArrayKlass.hpp"
|
||||||
#include "oops/oop.inline.hpp"
|
#include "oops/oop.inline.hpp"
|
||||||
#include "oops/oopHandle.inline.hpp"
|
#include "oops/oopHandle.inline.hpp"
|
||||||
#include "prims/jvmtiExport.hpp"
|
#include "prims/jvmtiExport.hpp"
|
||||||
@ -605,7 +607,7 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec
|
|||||||
if (this->has_archived_mirror_index()) {
|
if (this->has_archived_mirror_index()) {
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
log_debug(cds, mirror)("%s has raw archived mirror", external_name());
|
log_debug(cds, mirror)("%s has raw archived mirror", external_name());
|
||||||
if (HeapShared::are_archived_mirrors_available()) {
|
if (ArchiveHeapLoader::are_archived_mirrors_available()) {
|
||||||
bool present = java_lang_Class::restore_archived_mirror(this, loader, module_handle,
|
bool present = java_lang_Class::restore_archived_mirror(this, loader, module_handle,
|
||||||
protection_domain,
|
protection_domain,
|
||||||
CHECK);
|
CHECK);
|
||||||
|
@ -25,9 +25,10 @@
|
|||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include <new>
|
#include <new>
|
||||||
#include "cds.h"
|
#include "cds.h"
|
||||||
|
#include "cds/archiveHeapLoader.hpp"
|
||||||
#include "cds/cdsConstants.hpp"
|
#include "cds/cdsConstants.hpp"
|
||||||
#include "cds/filemap.hpp"
|
#include "cds/filemap.hpp"
|
||||||
#include "cds/heapShared.inline.hpp"
|
#include "cds/heapShared.hpp"
|
||||||
#include "cds/metaspaceShared.hpp"
|
#include "cds/metaspaceShared.hpp"
|
||||||
#include "classfile/classLoaderDataGraph.hpp"
|
#include "classfile/classLoaderDataGraph.hpp"
|
||||||
#include "classfile/javaClasses.inline.hpp"
|
#include "classfile/javaClasses.inline.hpp"
|
||||||
@ -1992,7 +1993,7 @@ WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
|
|||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
WB_ENTRY(jboolean, WB_AreSharedStringsMapped(JNIEnv* env))
|
WB_ENTRY(jboolean, WB_AreSharedStringsMapped(JNIEnv* env))
|
||||||
return HeapShared::closed_regions_mapped();
|
return ArchiveHeapLoader::closed_regions_mapped();
|
||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
WB_ENTRY(jobject, WB_GetResolvedReferences(JNIEnv* env, jobject wb, jclass clazz))
|
WB_ENTRY(jobject, WB_GetResolvedReferences(JNIEnv* env, jobject wb, jclass clazz))
|
||||||
@ -2017,7 +2018,7 @@ WB_ENTRY(void, WB_LinkClass(JNIEnv* env, jobject wb, jclass clazz))
|
|||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
WB_ENTRY(jboolean, WB_AreOpenArchiveHeapObjectsMapped(JNIEnv* env))
|
WB_ENTRY(jboolean, WB_AreOpenArchiveHeapObjectsMapped(JNIEnv* env))
|
||||||
return HeapShared::open_regions_mapped();
|
return ArchiveHeapLoader::open_regions_mapped();
|
||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
WB_ENTRY(jboolean, WB_IsCDSIncluded(JNIEnv* env))
|
WB_ENTRY(jboolean, WB_IsCDSIncluded(JNIEnv* env))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user