mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-28 15:51:02 +00:00
8212995: Placing the Integer.IntegerCache and cached Integer objects in the closed archive heap region
Support shareable archive object subgraphs in closed archive heap regions. Reviewed-by: iklam, ccheung
This commit is contained in:
parent
e3a2417b63
commit
80ad2c7e71
@ -78,7 +78,6 @@ static CompactHashtable<
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
StringTable* StringTable::_the_table = NULL;
|
||||
volatile bool StringTable::_shared_string_mapped = false;
|
||||
volatile bool StringTable::_alt_hash = false;
|
||||
|
||||
static juint murmur_seed = 0;
|
||||
@ -871,7 +870,7 @@ void StringTable::serialize_shared_table_header(SerializeClosure* soc) {
|
||||
if (soc->writing()) {
|
||||
// Sanity. Make sure we don't use the shared table at dump time
|
||||
_shared_table.reset();
|
||||
} else if (!_shared_string_mapped) {
|
||||
} else if (!HeapShared::closed_archive_heap_region_mapped()) {
|
||||
_shared_table.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +55,6 @@ private:
|
||||
|
||||
// The string table
|
||||
static StringTable* _the_table;
|
||||
static volatile bool _shared_string_mapped;
|
||||
static volatile bool _alt_hash;
|
||||
|
||||
private:
|
||||
@ -166,8 +165,6 @@ private:
|
||||
static void copy_shared_string_table(CompactHashtableWriter* ch_table) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
public:
|
||||
static oop create_archived_string(oop s, Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN_(NULL);
|
||||
static void set_shared_string_mapped() { _shared_string_mapped = true; }
|
||||
static bool shared_string_mapped() { return _shared_string_mapped; }
|
||||
static void shared_oops_do(OopClosure* f) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static void write_to_archive() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static void serialize_shared_table_header(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
#include "jvm.h"
|
||||
#include "classfile/classLoader.inline.hpp"
|
||||
#include "classfile/classLoaderExt.hpp"
|
||||
#include "classfile/stringTable.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "classfile/systemDictionaryShared.hpp"
|
||||
#include "classfile/altHashing.hpp"
|
||||
@ -615,7 +614,7 @@ void FileMapInfo::write_region(int region, char* base, size_t size,
|
||||
} else {
|
||||
si->_file_offset = _file_offset;
|
||||
}
|
||||
if (MetaspaceShared::is_heap_region(region)) {
|
||||
if (HeapShared::is_heap_region(region)) {
|
||||
assert((base - (char*)Universe::narrow_oop_base()) % HeapWordSize == 0, "Sanity");
|
||||
if (base != NULL) {
|
||||
si->_addr._offset = (intx)CompressedOops::encode_not_null((oop)base);
|
||||
@ -814,7 +813,7 @@ static const char* shared_region_name[] = { "MiscData", "ReadWrite", "ReadOnly",
|
||||
"String1", "String2", "OpenArchive1", "OpenArchive2" };
|
||||
|
||||
char* FileMapInfo::map_region(int i, char** top_ret) {
|
||||
assert(!MetaspaceShared::is_heap_region(i), "sanity");
|
||||
assert(!HeapShared::is_heap_region(i), "sanity");
|
||||
CDSFileMapRegion* si = space_at(i);
|
||||
size_t used = si->_used;
|
||||
size_t alignment = os::vm_allocation_granularity();
|
||||
@ -857,14 +856,14 @@ address FileMapInfo::decode_start_address(CDSFileMapRegion* spc, bool with_curre
|
||||
}
|
||||
}
|
||||
|
||||
static MemRegion *string_ranges = NULL;
|
||||
static MemRegion *closed_archive_heap_ranges = NULL;
|
||||
static MemRegion *open_archive_heap_ranges = NULL;
|
||||
static int num_string_ranges = 0;
|
||||
static int num_closed_archive_heap_ranges = 0;
|
||||
static int num_open_archive_heap_ranges = 0;
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
bool FileMapInfo::has_heap_regions() {
|
||||
return (_header->_space[MetaspaceShared::first_string]._used > 0);
|
||||
return (_header->_space[MetaspaceShared::first_closed_archive_heap_region]._used > 0);
|
||||
}
|
||||
|
||||
// Returns the address range of the archived heap regions computed using the
|
||||
@ -875,7 +874,9 @@ MemRegion FileMapInfo::get_heap_regions_range_with_current_oop_encoding_mode() {
|
||||
address start = (address) max_uintx;
|
||||
address end = NULL;
|
||||
|
||||
for (int i = MetaspaceShared::first_string; i <= MetaspaceShared::last_valid_region; i++) {
|
||||
for (int i = MetaspaceShared::first_closed_archive_heap_region;
|
||||
i <= MetaspaceShared::last_valid_region;
|
||||
i++) {
|
||||
CDSFileMapRegion* si = space_at(i);
|
||||
size_t size = si->_used;
|
||||
if (size > 0) {
|
||||
@ -894,16 +895,16 @@ MemRegion FileMapInfo::get_heap_regions_range_with_current_oop_encoding_mode() {
|
||||
}
|
||||
|
||||
//
|
||||
// Map the shared string objects and open archive heap objects to the runtime
|
||||
// java heap.
|
||||
// Map the closed and open archive heap objects to the runtime java heap.
|
||||
//
|
||||
// The shared strings are mapped close to the end of the java heap top in
|
||||
// closed archive regions. The mapped strings contain no out-going references
|
||||
// to any other java heap regions. GC does not write into the mapped shared strings.
|
||||
// The shared objects are mapped at (or close to ) the java heap top in
|
||||
// closed archive regions. The mapped objects contain no out-going
|
||||
// references to any other java heap regions. GC does not write into the
|
||||
// mapped closed archive heap region.
|
||||
//
|
||||
// The open archive heap objects are mapped below the shared strings in
|
||||
// the runtime java heap. The mapped open archive heap data only contain
|
||||
// references to the shared strings and open archive objects initially.
|
||||
// The open archive heap objects are mapped below the shared objects in
|
||||
// the runtime java heap. The mapped open archive heap data only contains
|
||||
// references to the shared objects and open archive objects initially.
|
||||
// During runtime execution, out-going references to any other java heap
|
||||
// regions may be added. GC may mark and update references in the mapped
|
||||
// open archive objects.
|
||||
@ -983,29 +984,31 @@ void FileMapInfo::map_heap_regions_impl() {
|
||||
log_info(cds)("CDS heap data relocation delta = " INTX_FORMAT " bytes", delta);
|
||||
HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift());
|
||||
|
||||
CDSFileMapRegion* si = space_at(MetaspaceShared::first_string);
|
||||
address relocated_strings_bottom = start_address_as_decoded_from_archive(si);
|
||||
if (!is_aligned(relocated_strings_bottom, HeapRegion::GrainBytes)) {
|
||||
// Align the bottom of the string regions at G1 region boundary. This will avoid
|
||||
// the situation where the highest open region and the lowest string region sharing
|
||||
// the same G1 region. Otherwise we will fail to map the open regions.
|
||||
size_t align = size_t(relocated_strings_bottom) % HeapRegion::GrainBytes;
|
||||
CDSFileMapRegion* si = space_at(MetaspaceShared::first_closed_archive_heap_region);
|
||||
address relocated_closed_heap_region_bottom = start_address_as_decoded_from_archive(si);
|
||||
if (!is_aligned(relocated_closed_heap_region_bottom, HeapRegion::GrainBytes)) {
|
||||
// Align the bottom of the closed archive heap regions at G1 region boundary.
|
||||
// This will avoid the situation where the highest open region and the lowest
|
||||
// closed region sharing the same G1 region. Otherwise we will fail to map the
|
||||
// open regions.
|
||||
size_t align = size_t(relocated_closed_heap_region_bottom) % HeapRegion::GrainBytes;
|
||||
delta -= align;
|
||||
log_info(cds)("CDS heap data need to be relocated lower by a further " SIZE_FORMAT
|
||||
" bytes to " INTX_FORMAT " to be aligned with HeapRegion::GrainBytes", align, delta);
|
||||
" bytes to " INTX_FORMAT " to be aligned with HeapRegion::GrainBytes",
|
||||
align, delta);
|
||||
HeapShared::init_narrow_oop_decoding(narrow_oop_base() + delta, narrow_oop_shift());
|
||||
_heap_pointers_need_patching = true;
|
||||
relocated_strings_bottom = start_address_as_decoded_from_archive(si);
|
||||
relocated_closed_heap_region_bottom = start_address_as_decoded_from_archive(si);
|
||||
}
|
||||
assert(is_aligned(relocated_strings_bottom, HeapRegion::GrainBytes), "must be");
|
||||
assert(is_aligned(relocated_closed_heap_region_bottom, HeapRegion::GrainBytes),
|
||||
"must be");
|
||||
|
||||
// First, map string regions as closed archive heap regions.
|
||||
// GC does not write into the regions.
|
||||
if (map_heap_data(&string_ranges,
|
||||
MetaspaceShared::first_string,
|
||||
MetaspaceShared::max_strings,
|
||||
&num_string_ranges)) {
|
||||
StringTable::set_shared_string_mapped();
|
||||
// Map the closed_archive_heap regions, GC does not write into the regions.
|
||||
if (map_heap_data(&closed_archive_heap_ranges,
|
||||
MetaspaceShared::first_closed_archive_heap_region,
|
||||
MetaspaceShared::max_closed_archive_heap_region,
|
||||
&num_closed_archive_heap_ranges)) {
|
||||
HeapShared::set_closed_archive_heap_region_mapped();
|
||||
|
||||
// Now, map open_archive heap regions, GC can write into the regions.
|
||||
if (map_heap_data(&open_archive_heap_ranges,
|
||||
@ -1023,8 +1026,9 @@ void FileMapInfo::map_heap_regions() {
|
||||
map_heap_regions_impl();
|
||||
}
|
||||
|
||||
if (!StringTable::shared_string_mapped()) {
|
||||
assert(string_ranges == NULL && num_string_ranges == 0, "sanity");
|
||||
if (!HeapShared::closed_archive_heap_region_mapped()) {
|
||||
assert(closed_archive_heap_ranges == NULL &&
|
||||
num_closed_archive_heap_ranges == 0, "sanity");
|
||||
}
|
||||
|
||||
if (!HeapShared::open_archive_heap_region_mapped()) {
|
||||
@ -1115,9 +1119,9 @@ void FileMapInfo::patch_archived_heap_embedded_pointers() {
|
||||
return;
|
||||
}
|
||||
|
||||
patch_archived_heap_embedded_pointers(string_ranges,
|
||||
num_string_ranges,
|
||||
MetaspaceShared::first_string);
|
||||
patch_archived_heap_embedded_pointers(closed_archive_heap_ranges,
|
||||
num_closed_archive_heap_ranges,
|
||||
MetaspaceShared::first_closed_archive_heap_region);
|
||||
|
||||
patch_archived_heap_embedded_pointers(open_archive_heap_ranges,
|
||||
num_open_archive_heap_ranges,
|
||||
@ -1136,11 +1140,13 @@ void FileMapInfo::patch_archived_heap_embedded_pointers(MemRegion* ranges, int n
|
||||
// This internally allocates objects using SystemDictionary::Object_klass(), so it
|
||||
// must be called after the well-known classes are resolved.
|
||||
void FileMapInfo::fixup_mapped_heap_regions() {
|
||||
// If any string regions were found, call the fill routine to make them parseable.
|
||||
// Note that string_ranges may be non-NULL even if no ranges were found.
|
||||
if (num_string_ranges != 0) {
|
||||
assert(string_ranges != NULL, "Null string_ranges array with non-zero count");
|
||||
G1CollectedHeap::heap()->fill_archive_regions(string_ranges, num_string_ranges);
|
||||
// If any closed regions were found, call the fill routine to make them parseable.
|
||||
// Note that closed_archive_heap_ranges may be non-NULL even if no ranges were found.
|
||||
if (num_closed_archive_heap_ranges != 0) {
|
||||
assert(closed_archive_heap_ranges != NULL,
|
||||
"Null closed_archive_heap_ranges array with non-zero count");
|
||||
G1CollectedHeap::heap()->fill_archive_regions(closed_archive_heap_ranges,
|
||||
num_closed_archive_heap_ranges);
|
||||
}
|
||||
|
||||
// do the same for mapped open archive heap regions
|
||||
@ -1170,9 +1176,9 @@ bool FileMapInfo::verify_region_checksum(int i) {
|
||||
if (sz == 0) {
|
||||
return true; // no data
|
||||
}
|
||||
if ((MetaspaceShared::is_string_region(i) &&
|
||||
!StringTable::shared_string_mapped()) ||
|
||||
(MetaspaceShared::is_open_archive_heap_region(i) &&
|
||||
if ((HeapShared::is_closed_archive_heap_region(i) &&
|
||||
!HeapShared::closed_archive_heap_region_mapped()) ||
|
||||
(HeapShared::is_open_archive_heap_region(i) &&
|
||||
!HeapShared::open_archive_heap_region_mapped())) {
|
||||
return true; // archived heap data is not mapped
|
||||
}
|
||||
@ -1188,7 +1194,7 @@ bool FileMapInfo::verify_region_checksum(int i) {
|
||||
// Unmap a memory region in the address space.
|
||||
|
||||
void FileMapInfo::unmap_region(int i) {
|
||||
assert(!MetaspaceShared::is_heap_region(i), "sanity");
|
||||
assert(!HeapShared::is_heap_region(i), "sanity");
|
||||
CDSFileMapRegion* si = space_at(i);
|
||||
size_t used = si->_used;
|
||||
size_t size = align_up(used, os::vm_allocation_granularity());
|
||||
@ -1259,7 +1265,7 @@ bool FileMapInfo::initialize() {
|
||||
|
||||
char* FileMapInfo::region_addr(int idx) {
|
||||
CDSFileMapRegion* si = space_at(idx);
|
||||
if (MetaspaceShared::is_heap_region(idx)) {
|
||||
if (HeapShared::is_heap_region(idx)) {
|
||||
assert(DumpSharedSpaces, "The following doesn't work at runtime");
|
||||
return si->_used > 0 ?
|
||||
(char*)start_address_as_decoded_with_current_oop_encoding_mode(si) : NULL;
|
||||
@ -1326,7 +1332,7 @@ bool FileMapHeader::validate() {
|
||||
if (prop != NULL) {
|
||||
warning("Archived non-system classes are disabled because the "
|
||||
"java.system.class.loader property is specified (value = \"%s\"). "
|
||||
"To use archived non-system classes, this property must be not be set", prop);
|
||||
"To use archived non-system classes, this property must not be set", prop);
|
||||
_has_platform_or_app_classes = false;
|
||||
}
|
||||
|
||||
@ -1383,7 +1389,7 @@ void FileMapInfo::stop_sharing_and_unmap(const char* msg) {
|
||||
if (map_info) {
|
||||
map_info->fail_continue("%s", msg);
|
||||
for (int i = 0; i < MetaspaceShared::num_non_heap_spaces; i++) {
|
||||
if (!MetaspaceShared::is_heap_region(i)) {
|
||||
if (!HeapShared::is_heap_region(i)) {
|
||||
char *addr = map_info->region_addr(i);
|
||||
if (addr != NULL) {
|
||||
map_info->unmap_region(i);
|
||||
@ -1395,7 +1401,8 @@ void FileMapInfo::stop_sharing_and_unmap(const char* msg) {
|
||||
// of the java heap. Unmapping of the heap regions are managed by GC.
|
||||
map_info->dealloc_archive_heap_regions(open_archive_heap_ranges,
|
||||
num_open_archive_heap_ranges);
|
||||
map_info->dealloc_archive_heap_regions(string_ranges, num_string_ranges);
|
||||
map_info->dealloc_archive_heap_regions(closed_archive_heap_ranges,
|
||||
num_closed_archive_heap_ranges);
|
||||
} else if (DumpSharedSpaces) {
|
||||
fail_stop("%s", msg);
|
||||
}
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
#include "memory/metaspaceClosure.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/compressedOops.inline.hpp"
|
||||
#include "oops/fieldStreams.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/fieldDescriptor.inline.hpp"
|
||||
#include "runtime/safepointVerifiers.hpp"
|
||||
@ -47,12 +48,40 @@
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
|
||||
bool HeapShared::_closed_archive_heap_region_mapped = false;
|
||||
bool HeapShared::_open_archive_heap_region_mapped = false;
|
||||
bool HeapShared::_archive_heap_region_fixed = false;
|
||||
|
||||
address HeapShared::_narrow_oop_base;
|
||||
int HeapShared::_narrow_oop_shift;
|
||||
|
||||
//
|
||||
// If you add new entries to the following tables, you should know what you're doing!
|
||||
//
|
||||
|
||||
// Entry fields for shareable subgraphs archived in the closed archive heap
|
||||
// region. Warning: Objects in the subgraphs should not have reference fields
|
||||
// assigned at runtime.
|
||||
static ArchivableStaticFieldInfo closed_archive_subgraph_entry_fields[] = {
|
||||
{"java/lang/Integer$IntegerCache", "archivedCache"},
|
||||
};
|
||||
// Entry fields for subgraphs archived in the open archive heap region.
|
||||
static ArchivableStaticFieldInfo open_archive_subgraph_entry_fields[] = {
|
||||
{"jdk/internal/module/ArchivedModuleGraph", "archivedSystemModules"},
|
||||
{"jdk/internal/module/ArchivedModuleGraph", "archivedModuleFinder"},
|
||||
{"jdk/internal/module/ArchivedModuleGraph", "archivedMainModule"},
|
||||
{"jdk/internal/module/ArchivedModuleGraph", "archivedConfiguration"},
|
||||
{"java/util/ImmutableCollections$ListN", "EMPTY_LIST"},
|
||||
{"java/util/ImmutableCollections$MapN", "EMPTY_MAP"},
|
||||
{"java/util/ImmutableCollections$SetN", "EMPTY_SET"},
|
||||
{"java/lang/module/Configuration", "EMPTY_CONFIGURATION"},
|
||||
};
|
||||
|
||||
const static int num_closed_archive_subgraph_entry_fields =
|
||||
sizeof(closed_archive_subgraph_entry_fields) / sizeof(ArchivableStaticFieldInfo);
|
||||
const static int num_open_archive_subgraph_entry_fields =
|
||||
sizeof(open_archive_subgraph_entry_fields) / sizeof(ArchivableStaticFieldInfo);
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Java heap object archiving support
|
||||
@ -189,6 +218,10 @@ void HeapShared::copy_closed_archive_heap_objects(
|
||||
// Archive interned string objects
|
||||
StringTable::write_to_archive();
|
||||
|
||||
archive_object_subgraphs(closed_archive_subgraph_entry_fields,
|
||||
num_closed_archive_subgraph_entry_fields,
|
||||
true /* is_closed_archive */, THREAD);
|
||||
|
||||
G1CollectedHeap::heap()->end_archive_alloc_range(closed_archive,
|
||||
os::vm_allocation_granularity());
|
||||
}
|
||||
@ -204,7 +237,10 @@ void HeapShared::copy_open_archive_heap_objects(
|
||||
|
||||
archive_klass_objects(THREAD);
|
||||
|
||||
archive_object_subgraphs(THREAD);
|
||||
archive_object_subgraphs(open_archive_subgraph_entry_fields,
|
||||
num_open_archive_subgraph_entry_fields,
|
||||
false /* is_closed_archive */,
|
||||
THREAD);
|
||||
|
||||
G1CollectedHeap::heap()->end_archive_alloc_range(open_archive,
|
||||
os::vm_allocation_granularity());
|
||||
@ -237,7 +273,8 @@ KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) {
|
||||
}
|
||||
|
||||
// Add an entry field to the current KlassSubGraphInfo.
|
||||
void KlassSubGraphInfo::add_subgraph_entry_field(int static_field_offset, oop v) {
|
||||
void KlassSubGraphInfo::add_subgraph_entry_field(
|
||||
int static_field_offset, oop v, bool is_closed_archive) {
|
||||
assert(DumpSharedSpaces, "dump time only");
|
||||
if (_subgraph_entry_fields == NULL) {
|
||||
_subgraph_entry_fields =
|
||||
@ -245,6 +282,7 @@ void KlassSubGraphInfo::add_subgraph_entry_field(int static_field_offset, oop v)
|
||||
}
|
||||
_subgraph_entry_fields->append((juint)static_field_offset);
|
||||
_subgraph_entry_fields->append(CompressedOops::encode(v));
|
||||
_subgraph_entry_fields->append(is_closed_archive ? 1 : 0);
|
||||
}
|
||||
|
||||
// Add the Klass* for an object in the current KlassSubGraphInfo's subgraphs.
|
||||
@ -315,7 +353,7 @@ void ArchivedKlassSubGraphInfoRecord::init(KlassSubGraphInfo* info) {
|
||||
GrowableArray<juint>* entry_fields = info->subgraph_entry_fields();
|
||||
if (entry_fields != NULL) {
|
||||
int num_entry_fields = entry_fields->length();
|
||||
assert(num_entry_fields % 2 == 0, "sanity");
|
||||
assert(num_entry_fields % 3 == 0, "sanity");
|
||||
_entry_field_records =
|
||||
MetaspaceShared::new_ro_array<juint>(num_entry_fields);
|
||||
for (int i = 0 ; i < num_entry_fields; i++) {
|
||||
@ -365,8 +403,8 @@ struct CopyKlassSubGraphInfoToArchive : StackObj {
|
||||
// Build the records of archived subgraph infos, which include:
|
||||
// - Entry points to all subgraphs from the containing class mirror. The entry
|
||||
// points are static fields in the mirror. For each entry point, the field
|
||||
// offset and value are recorded in the sub-graph info. The value are stored
|
||||
// back to the corresponding field at runtime.
|
||||
// offset, value and is_closed_archive flag are recorded in the sub-graph
|
||||
// info. The value is stored back to the corresponding field at runtime.
|
||||
// - A list of klasses that need to be loaded/initialized before archived
|
||||
// java object sub-graph can be accessed at runtime.
|
||||
void HeapShared::write_subgraph_info_table() {
|
||||
@ -448,15 +486,25 @@ void HeapShared::initialize_from_archived_subgraph(Klass* k) {
|
||||
Array<juint>* entry_field_records = record->entry_field_records();
|
||||
if (entry_field_records != NULL) {
|
||||
int efr_len = entry_field_records->length();
|
||||
assert(efr_len % 2 == 0, "sanity");
|
||||
assert(efr_len % 3 == 0, "sanity");
|
||||
for (i = 0; i < efr_len;) {
|
||||
int field_offset = entry_field_records->at(i);
|
||||
// The object refereced by the field becomes 'known' by GC from this
|
||||
// point. All objects in the subgraph reachable from the object are
|
||||
// also 'known' by GC.
|
||||
oop v = materialize_archived_object(entry_field_records->at(i+1));
|
||||
narrowOop nv = entry_field_records->at(i+1);
|
||||
int is_closed_archive = entry_field_records->at(i+2);
|
||||
oop v;
|
||||
if (is_closed_archive == 0) {
|
||||
// It's an archived object in the open archive heap regions, not shared.
|
||||
// The object refereced by the field becomes 'known' by GC from this
|
||||
// point. All objects in the subgraph reachable from the object are
|
||||
// also 'known' by GC.
|
||||
v = materialize_archived_object(nv);
|
||||
} else {
|
||||
// Shared object in the closed archive heap regions. Decode directly.
|
||||
assert(!CompressedOops::is_null(nv), "shared object is null");
|
||||
v = HeapShared::decode_from_archive(nv);
|
||||
}
|
||||
m->obj_field_put(field_offset, v);
|
||||
i += 2;
|
||||
i += 3;
|
||||
|
||||
log_debug(cds, heap)(" " PTR_FORMAT " init field @ %2d = " PTR_FORMAT, p2i(k), field_offset, p2i(v));
|
||||
}
|
||||
@ -469,16 +517,20 @@ void HeapShared::initialize_from_archived_subgraph(Klass* k) {
|
||||
|
||||
class WalkOopAndArchiveClosure: public BasicOopIterateClosure {
|
||||
int _level;
|
||||
bool _is_closed_archive;
|
||||
bool _record_klasses_only;
|
||||
KlassSubGraphInfo* _subgraph_info;
|
||||
oop _orig_referencing_obj;
|
||||
oop _archived_referencing_obj;
|
||||
Thread* _thread;
|
||||
public:
|
||||
WalkOopAndArchiveClosure(int level, bool record_klasses_only,
|
||||
WalkOopAndArchiveClosure(int level,
|
||||
bool is_closed_archive,
|
||||
bool record_klasses_only,
|
||||
KlassSubGraphInfo* subgraph_info,
|
||||
oop orig, oop archived, TRAPS) :
|
||||
_level(level), _record_klasses_only(record_klasses_only),
|
||||
_level(level), _is_closed_archive(is_closed_archive),
|
||||
_record_klasses_only(record_klasses_only),
|
||||
_subgraph_info(subgraph_info),
|
||||
_orig_referencing_obj(orig), _archived_referencing_obj(archived),
|
||||
_thread(THREAD) {}
|
||||
@ -506,7 +558,8 @@ class WalkOopAndArchiveClosure: public BasicOopIterateClosure {
|
||||
obj->print_on(&out);
|
||||
}
|
||||
|
||||
oop archived = HeapShared::archive_reachable_objects_from(_level + 1, _subgraph_info, obj, THREAD);
|
||||
oop archived = HeapShared::archive_reachable_objects_from(
|
||||
_level + 1, _subgraph_info, obj, _is_closed_archive, THREAD);
|
||||
assert(archived != NULL, "VM should have exited with unarchivable objects for _level > 1");
|
||||
assert(HeapShared::is_archived_object(archived), "must be");
|
||||
|
||||
@ -520,11 +573,32 @@ class WalkOopAndArchiveClosure: public BasicOopIterateClosure {
|
||||
}
|
||||
};
|
||||
|
||||
void HeapShared::check_closed_archive_heap_region_object(InstanceKlass* k,
|
||||
Thread* THREAD) {
|
||||
// Check fields in the object
|
||||
for (JavaFieldStream fs(k); !fs.done(); fs.next()) {
|
||||
if (!fs.access_flags().is_static()) {
|
||||
BasicType ft = fs.field_descriptor().field_type();
|
||||
if (!fs.access_flags().is_final() && (ft == T_ARRAY || T_OBJECT)) {
|
||||
ResourceMark rm(THREAD);
|
||||
log_warning(cds, heap)(
|
||||
"Please check reference field in %s instance in closed archive heap region: %s %s",
|
||||
k->external_name(), (fs.name())->as_C_string(),
|
||||
(fs.signature())->as_C_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// (1) If orig_obj has not been archived yet, archive it.
|
||||
// (2) If orig_obj has not been seen yet (since start_recording_subgraph() was called),
|
||||
// trace all objects that are reachable from it, and make sure these objects are archived.
|
||||
// (3) Record the klasses of all orig_obj and all reachable objects.
|
||||
oop HeapShared::archive_reachable_objects_from(int level, KlassSubGraphInfo* subgraph_info, oop orig_obj, TRAPS) {
|
||||
oop HeapShared::archive_reachable_objects_from(int level,
|
||||
KlassSubGraphInfo* subgraph_info,
|
||||
oop orig_obj,
|
||||
bool is_closed_archive,
|
||||
TRAPS) {
|
||||
assert(orig_obj != NULL, "must be");
|
||||
assert(!is_archived_object(orig_obj), "sanity");
|
||||
|
||||
@ -578,8 +652,12 @@ oop HeapShared::archive_reachable_objects_from(int level, KlassSubGraphInfo* sub
|
||||
Klass *relocated_k = archived_obj->klass();
|
||||
subgraph_info->add_subgraph_object_klass(orig_k, relocated_k);
|
||||
|
||||
WalkOopAndArchiveClosure walker(level, record_klasses_only, subgraph_info, orig_obj, archived_obj, THREAD);
|
||||
WalkOopAndArchiveClosure walker(level, is_closed_archive, record_klasses_only,
|
||||
subgraph_info, orig_obj, archived_obj, THREAD);
|
||||
orig_obj->oop_iterate(&walker);
|
||||
if (is_closed_archive && orig_k->is_instance_klass()) {
|
||||
check_closed_archive_heap_region_object(InstanceKlass::cast(orig_k), THREAD);
|
||||
}
|
||||
return archived_obj;
|
||||
}
|
||||
|
||||
@ -621,15 +699,12 @@ void HeapShared::archive_reachable_objects_from_static_field(InstanceKlass *k,
|
||||
const char* klass_name,
|
||||
int field_offset,
|
||||
const char* field_name,
|
||||
bool is_closed_archive,
|
||||
TRAPS) {
|
||||
assert(DumpSharedSpaces, "dump time only");
|
||||
assert(k->is_shared_boot_class(), "must be boot class");
|
||||
|
||||
oop m = k->java_mirror();
|
||||
oop archived_m = find_archived_heap_object(m);
|
||||
if (CompressedOops::is_null(archived_m)) {
|
||||
return;
|
||||
}
|
||||
|
||||
KlassSubGraphInfo* subgraph_info = get_subgraph_info(k);
|
||||
oop f = m->obj_field(field_offset);
|
||||
@ -643,7 +718,8 @@ void HeapShared::archive_reachable_objects_from_static_field(InstanceKlass *k,
|
||||
f->print_on(&out);
|
||||
}
|
||||
|
||||
oop af = archive_reachable_objects_from(1, subgraph_info, f, CHECK);
|
||||
oop af = archive_reachable_objects_from(1, subgraph_info, f,
|
||||
is_closed_archive, CHECK);
|
||||
|
||||
if (af == NULL) {
|
||||
log_error(cds, heap)("Archiving failed %s::%s (some reachable objects cannot be archived)",
|
||||
@ -652,13 +728,13 @@ void HeapShared::archive_reachable_objects_from_static_field(InstanceKlass *k,
|
||||
// Note: the field value is not preserved in the archived mirror.
|
||||
// Record the field as a new subGraph entry point. The recorded
|
||||
// information is restored from the archive at runtime.
|
||||
subgraph_info->add_subgraph_entry_field(field_offset, af);
|
||||
subgraph_info->add_subgraph_entry_field(field_offset, af, is_closed_archive);
|
||||
log_info(cds, heap)("Archived field %s::%s => " PTR_FORMAT, klass_name, field_name, p2i(af));
|
||||
}
|
||||
} else {
|
||||
// The field contains null, we still need to record the entry point,
|
||||
// so it can be restored at runtime.
|
||||
subgraph_info->add_subgraph_entry_field(field_offset, NULL);
|
||||
subgraph_info->add_subgraph_entry_field(field_offset, NULL, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -687,10 +763,6 @@ void HeapShared::verify_subgraph_from_static_field(InstanceKlass* k, int field_o
|
||||
assert(k->is_shared_boot_class(), "must be boot class");
|
||||
|
||||
oop m = k->java_mirror();
|
||||
oop archived_m = find_archived_heap_object(m);
|
||||
if (CompressedOops::is_null(archived_m)) {
|
||||
return;
|
||||
}
|
||||
oop f = m->obj_field(field_offset);
|
||||
if (!CompressedOops::is_null(f)) {
|
||||
verify_subgraph_from(f);
|
||||
@ -783,30 +855,6 @@ void HeapShared::done_recording_subgraph(InstanceKlass *k, const char* class_nam
|
||||
_num_total_recorded_klasses += num_new_recorded_klasses;
|
||||
}
|
||||
|
||||
struct ArchivableStaticFieldInfo {
|
||||
const char* klass_name;
|
||||
const char* field_name;
|
||||
InstanceKlass* klass;
|
||||
int offset;
|
||||
BasicType type;
|
||||
};
|
||||
|
||||
// If you add new entries to this table, you should know what you're doing!
|
||||
static ArchivableStaticFieldInfo archivable_static_fields[] = {
|
||||
{"jdk/internal/module/ArchivedModuleGraph", "archivedSystemModules"},
|
||||
{"jdk/internal/module/ArchivedModuleGraph", "archivedModuleFinder"},
|
||||
{"jdk/internal/module/ArchivedModuleGraph", "archivedMainModule"},
|
||||
{"jdk/internal/module/ArchivedModuleGraph", "archivedConfiguration"},
|
||||
{"java/util/ImmutableCollections$ListN", "EMPTY_LIST"},
|
||||
{"java/util/ImmutableCollections$MapN", "EMPTY_MAP"},
|
||||
{"java/util/ImmutableCollections$SetN", "EMPTY_SET"},
|
||||
{"java/lang/Integer$IntegerCache", "archivedCache"},
|
||||
{"java/lang/module/Configuration", "EMPTY_CONFIGURATION"},
|
||||
};
|
||||
|
||||
const static int num_archivable_static_fields =
|
||||
sizeof(archivable_static_fields) / sizeof(ArchivableStaticFieldInfo);
|
||||
|
||||
class ArchivableStaticFieldFinder: public FieldClosure {
|
||||
InstanceKlass* _ik;
|
||||
Symbol* _field_name;
|
||||
@ -828,11 +876,10 @@ public:
|
||||
int offset() { return _offset; }
|
||||
};
|
||||
|
||||
void HeapShared::init_archivable_static_fields(Thread* THREAD) {
|
||||
_dump_time_subgraph_info_table = new (ResourceObj::C_HEAP, mtClass)DumpTimeKlassSubGraphInfoTable();
|
||||
|
||||
for (int i = 0; i < num_archivable_static_fields; i++) {
|
||||
ArchivableStaticFieldInfo* info = &archivable_static_fields[i];
|
||||
void HeapShared::init_subgraph_entry_fields(ArchivableStaticFieldInfo fields[],
|
||||
int num, Thread* THREAD) {
|
||||
for (int i = 0; i < num; i++) {
|
||||
ArchivableStaticFieldInfo* info = &fields[i];
|
||||
TempNewSymbol klass_name = SymbolTable::new_symbol(info->klass_name, THREAD);
|
||||
TempNewSymbol field_name = SymbolTable::new_symbol(info->field_name, THREAD);
|
||||
|
||||
@ -849,7 +896,26 @@ void HeapShared::init_archivable_static_fields(Thread* THREAD) {
|
||||
}
|
||||
}
|
||||
|
||||
void HeapShared::archive_object_subgraphs(Thread* THREAD) {
|
||||
void HeapShared::init_subgraph_entry_fields(Thread* THREAD) {
|
||||
_dump_time_subgraph_info_table = new (ResourceObj::C_HEAP, mtClass)DumpTimeKlassSubGraphInfoTable();
|
||||
|
||||
init_subgraph_entry_fields(closed_archive_subgraph_entry_fields,
|
||||
num_closed_archive_subgraph_entry_fields,
|
||||
THREAD);
|
||||
init_subgraph_entry_fields(open_archive_subgraph_entry_fields,
|
||||
num_open_archive_subgraph_entry_fields,
|
||||
THREAD);
|
||||
}
|
||||
|
||||
void HeapShared::archive_object_subgraphs(ArchivableStaticFieldInfo fields[],
|
||||
int num, bool is_closed_archive,
|
||||
Thread* THREAD) {
|
||||
_num_total_subgraph_recordings = 0;
|
||||
_num_total_walked_objs = 0;
|
||||
_num_total_archived_objs = 0;
|
||||
_num_total_recorded_klasses = 0;
|
||||
_num_total_verifications = 0;
|
||||
|
||||
// For each class X that has one or more archived fields:
|
||||
// [1] Dump the subgraph of each archived field
|
||||
// [2] Create a list of all the class of the objects that can be reached
|
||||
@ -857,38 +923,40 @@ void HeapShared::archive_object_subgraphs(Thread* THREAD) {
|
||||
// At runtime, these classes are initialized before X's archived fields
|
||||
// are restored by HeapShared::initialize_from_archived_subgraph().
|
||||
int i;
|
||||
for (i = 0; i < num_archivable_static_fields; ) {
|
||||
ArchivableStaticFieldInfo* info = &archivable_static_fields[i];
|
||||
for (i = 0; i < num; ) {
|
||||
ArchivableStaticFieldInfo* info = &fields[i];
|
||||
const char* klass_name = info->klass_name;
|
||||
start_recording_subgraph(info->klass, klass_name);
|
||||
|
||||
// If you have specified consecutive fields of the same klass in
|
||||
// archivable_static_fields[], these will be archived in the same
|
||||
// fields[], these will be archived in the same
|
||||
// {start_recording_subgraph ... done_recording_subgraph} pass to
|
||||
// save time.
|
||||
for (; i < num_archivable_static_fields; i++) {
|
||||
ArchivableStaticFieldInfo* f = &archivable_static_fields[i];
|
||||
for (; i < num; i++) {
|
||||
ArchivableStaticFieldInfo* f = &fields[i];
|
||||
if (f->klass_name != klass_name) {
|
||||
break;
|
||||
}
|
||||
archive_reachable_objects_from_static_field(f->klass, f->klass_name,
|
||||
f->offset, f->field_name, CHECK);
|
||||
f->offset, f->field_name,
|
||||
is_closed_archive, CHECK);
|
||||
}
|
||||
done_recording_subgraph(info->klass, klass_name);
|
||||
}
|
||||
|
||||
log_info(cds, heap)("Performed subgraph records = %d times", _num_total_subgraph_recordings);
|
||||
log_info(cds, heap)("Walked %d objects", _num_total_walked_objs);
|
||||
log_info(cds, heap)("Archived %d objects", _num_total_archived_objs);
|
||||
log_info(cds, heap)("Recorded %d klasses", _num_total_recorded_klasses);
|
||||
|
||||
log_info(cds, heap)("Archived subgraph records in %s archive heap region = %d",
|
||||
is_closed_archive ? "closed" : "open",
|
||||
_num_total_subgraph_recordings);
|
||||
log_info(cds, heap)(" Walked %d objects", _num_total_walked_objs);
|
||||
log_info(cds, heap)(" Archived %d objects", _num_total_archived_objs);
|
||||
log_info(cds, heap)(" Recorded %d klasses", _num_total_recorded_klasses);
|
||||
|
||||
#ifndef PRODUCT
|
||||
for (int i = 0; i < num_archivable_static_fields; i++) {
|
||||
ArchivableStaticFieldInfo* f = &archivable_static_fields[i];
|
||||
for (int i = 0; i < num; i++) {
|
||||
ArchivableStaticFieldInfo* f = &fields[i];
|
||||
verify_subgraph_from_static_field(f->klass, f->offset);
|
||||
}
|
||||
log_info(cds, heap)("Verified %d references", _num_total_verifications);
|
||||
log_info(cds, heap)(" Verified %d references", _num_total_verifications);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "classfile/compactHashtable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "memory/metaspaceShared.hpp"
|
||||
#include "memory/universe.hpp"
|
||||
#include "oops/objArrayKlass.hpp"
|
||||
#include "oops/oop.hpp"
|
||||
@ -37,6 +38,14 @@
|
||||
#include "utilities/resourceHash.hpp"
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
struct ArchivableStaticFieldInfo {
|
||||
const char* klass_name;
|
||||
const char* field_name;
|
||||
InstanceKlass* klass;
|
||||
int offset;
|
||||
BasicType type;
|
||||
};
|
||||
|
||||
// A dump time sub-graph info for Klass _k. It includes the entry points
|
||||
// (static fields in _k's mirror) of the archived sub-graphs reachable
|
||||
// from _k's mirror. It also contains a list of Klasses of the objects
|
||||
@ -50,7 +59,8 @@ class KlassSubGraphInfo: public CHeapObj<mtClass> {
|
||||
// object sub-graphs can be accessed at runtime.
|
||||
GrowableArray<Klass*>* _subgraph_object_klasses;
|
||||
// A list of _k's static fields as the entry points of archived sub-graphs.
|
||||
// For each entry field, it is a pair of field_offset and field_value.
|
||||
// For each entry field, it is a tuple of field_offset, field_value and
|
||||
// is_closed_archive flag.
|
||||
GrowableArray<juint>* _subgraph_entry_fields;
|
||||
|
||||
public:
|
||||
@ -73,7 +83,8 @@ class KlassSubGraphInfo: public CHeapObj<mtClass> {
|
||||
GrowableArray<juint>* subgraph_entry_fields() {
|
||||
return _subgraph_entry_fields;
|
||||
}
|
||||
void add_subgraph_entry_field(int static_field_offset, oop v);
|
||||
void add_subgraph_entry_field(int static_field_offset, oop v,
|
||||
bool is_closed_archive);
|
||||
void add_subgraph_object_klass(Klass *orig_k, Klass *relocated_k);
|
||||
int num_subgraph_object_klasses() {
|
||||
return _subgraph_object_klasses == NULL ? 0 :
|
||||
@ -109,6 +120,7 @@ class HeapShared: AllStatic {
|
||||
private:
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
static bool _closed_archive_heap_region_mapped;
|
||||
static bool _open_archive_heap_region_mapped;
|
||||
static bool _archive_heap_region_fixed;
|
||||
|
||||
@ -160,21 +172,34 @@ class HeapShared: AllStatic {
|
||||
static DumpTimeKlassSubGraphInfoTable* _dump_time_subgraph_info_table;
|
||||
static RunTimeKlassSubGraphInfoTable _run_time_subgraph_info_table;
|
||||
|
||||
static void check_closed_archive_heap_region_object(InstanceKlass* k,
|
||||
Thread* THREAD);
|
||||
|
||||
static void archive_object_subgraphs(ArchivableStaticFieldInfo fields[],
|
||||
int num,
|
||||
bool is_closed_archive,
|
||||
Thread* THREAD);
|
||||
|
||||
// Archive object sub-graph starting from the given static field
|
||||
// in Klass k's mirror.
|
||||
static void archive_reachable_objects_from_static_field(
|
||||
InstanceKlass* k, const char* klass_name,
|
||||
int field_offset, const char* field_name, TRAPS);
|
||||
int field_offset, const char* field_name,
|
||||
bool is_closed_archive, TRAPS);
|
||||
|
||||
static void verify_subgraph_from_static_field(
|
||||
InstanceKlass* k, int field_offset) PRODUCT_RETURN;
|
||||
|
||||
static void verify_reachable_objects_from(oop obj, bool is_archived) PRODUCT_RETURN;
|
||||
static void verify_subgraph_from(oop orig_obj) PRODUCT_RETURN;
|
||||
|
||||
static KlassSubGraphInfo* get_subgraph_info(Klass *k);
|
||||
static int num_of_subgraph_infos();
|
||||
|
||||
static void build_archived_subgraph_info_records(int num_records);
|
||||
|
||||
static void init_subgraph_entry_fields(ArchivableStaticFieldInfo fields[],
|
||||
int num, Thread* THREAD);
|
||||
|
||||
// Used by decode_from_archive
|
||||
static address _narrow_oop_base;
|
||||
static int _narrow_oop_shift;
|
||||
@ -245,6 +270,14 @@ class HeapShared: AllStatic {
|
||||
GrowableArray<MemRegion> *open);
|
||||
static void copy_closed_archive_heap_objects(GrowableArray<MemRegion> * closed_archive);
|
||||
static void copy_open_archive_heap_objects(GrowableArray<MemRegion> * open_archive);
|
||||
|
||||
static oop archive_reachable_objects_from(int level,
|
||||
KlassSubGraphInfo* subgraph_info,
|
||||
oop orig_obj,
|
||||
bool is_closed_archive,
|
||||
TRAPS);
|
||||
|
||||
static ResourceBitMap calculate_oopmap(MemRegion region);
|
||||
#endif // INCLUDE_CDS_JAVA_HEAP
|
||||
|
||||
public:
|
||||
@ -253,6 +286,30 @@ class HeapShared: AllStatic {
|
||||
NOT_CDS_JAVA_HEAP(return false;)
|
||||
}
|
||||
|
||||
static bool is_heap_region(int idx) {
|
||||
CDS_JAVA_HEAP_ONLY(return (idx >= MetaspaceShared::first_closed_archive_heap_region &&
|
||||
idx <= MetaspaceShared::last_open_archive_heap_region));
|
||||
NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
}
|
||||
static bool is_closed_archive_heap_region(int idx) {
|
||||
CDS_JAVA_HEAP_ONLY(return (idx >= MetaspaceShared::first_closed_archive_heap_region &&
|
||||
idx <= MetaspaceShared::last_closed_archive_heap_region));
|
||||
NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
}
|
||||
static bool is_open_archive_heap_region(int idx) {
|
||||
CDS_JAVA_HEAP_ONLY(return (idx >= MetaspaceShared::first_open_archive_heap_region &&
|
||||
idx <= MetaspaceShared::last_open_archive_heap_region));
|
||||
NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
}
|
||||
|
||||
static void set_closed_archive_heap_region_mapped() {
|
||||
CDS_JAVA_HEAP_ONLY(_closed_archive_heap_region_mapped = true);
|
||||
NOT_CDS_JAVA_HEAP_RETURN;
|
||||
}
|
||||
static bool closed_archive_heap_region_mapped() {
|
||||
CDS_JAVA_HEAP_ONLY(return _closed_archive_heap_region_mapped);
|
||||
NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
}
|
||||
static void set_open_archive_heap_region_mapped() {
|
||||
CDS_JAVA_HEAP_ONLY(_open_archive_heap_region_mapped = true);
|
||||
NOT_CDS_JAVA_HEAP_RETURN;
|
||||
@ -283,15 +340,8 @@ class HeapShared: AllStatic {
|
||||
static void patch_archived_heap_embedded_pointers(MemRegion mem, address oopmap,
|
||||
size_t oopmap_in_bits) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
|
||||
static void init_archivable_static_fields(Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static void archive_object_subgraphs(Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static void init_subgraph_entry_fields(Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static void write_subgraph_info_table() NOT_CDS_JAVA_HEAP_RETURN;
|
||||
static void serialize_subgraph_info_table_header(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN;
|
||||
|
||||
#if INCLUDE_CDS_JAVA_HEAP
|
||||
static ResourceBitMap calculate_oopmap(MemRegion region);
|
||||
static oop archive_reachable_objects_from(int level, KlassSubGraphInfo* subgraph_info, oop orig_obj, TRAPS);
|
||||
static void verify_subgraph_from(oop orig_obj) PRODUCT_RETURN;
|
||||
#endif
|
||||
};
|
||||
#endif // SHARE_VM_MEMORY_HEAPSHARED_HPP
|
||||
|
||||
@ -86,8 +86,8 @@ size_t MetaspaceShared::_core_spaces_size = 0;
|
||||
// md - misc data (the c++ vtables)
|
||||
// od - optional data (original class files)
|
||||
//
|
||||
// s0 - shared strings(closed archive heap space) #0
|
||||
// s1 - shared strings(closed archive heap space) #1 (may be empty)
|
||||
// ca0 - closed archive heap space #0
|
||||
// ca1 - closed archive heap space #1 (may be empty)
|
||||
// oa0 - open archive heap space #0
|
||||
// oa1 - open archive heap space #1 (may be empty)
|
||||
//
|
||||
@ -198,7 +198,7 @@ public:
|
||||
|
||||
|
||||
DumpRegion _mc_region("mc"), _ro_region("ro"), _rw_region("rw"), _md_region("md"), _od_region("od");
|
||||
size_t _total_string_region_size = 0, _total_open_archive_region_size = 0;
|
||||
size_t _total_closed_archive_region_size = 0, _total_open_archive_region_size = 0;
|
||||
|
||||
char* MetaspaceShared::misc_code_space_alloc(size_t num_bytes) {
|
||||
return _mc_region.allocate(num_bytes);
|
||||
@ -1274,9 +1274,8 @@ public:
|
||||
// NOTE: after this point, we shouldn't have any globals that can reach the old
|
||||
// objects.
|
||||
|
||||
// We cannot use any of the objects in the heap anymore (except for the objects
|
||||
// in the CDS shared string regions) because their headers no longer point to
|
||||
// valid Klasses.
|
||||
// We cannot use any of the objects in the heap anymore (except for the
|
||||
// shared strings) because their headers no longer point to valid Klasses.
|
||||
}
|
||||
|
||||
static void iterate_roots(MetaspaceClosure* it) {
|
||||
@ -1491,11 +1490,11 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||
write_region(mapinfo, MetaspaceShared::md, &_md_region, /*read_only=*/false,/*allow_exec=*/false);
|
||||
write_region(mapinfo, MetaspaceShared::od, &_od_region, /*read_only=*/true, /*allow_exec=*/false);
|
||||
|
||||
_total_string_region_size = mapinfo->write_archive_heap_regions(
|
||||
_total_closed_archive_region_size = mapinfo->write_archive_heap_regions(
|
||||
_closed_archive_heap_regions,
|
||||
_closed_archive_heap_oopmaps,
|
||||
MetaspaceShared::first_string,
|
||||
MetaspaceShared::max_strings);
|
||||
MetaspaceShared::first_closed_archive_heap_region,
|
||||
MetaspaceShared::max_closed_archive_heap_region);
|
||||
_total_open_archive_region_size = mapinfo->write_archive_heap_regions(
|
||||
_open_archive_heap_regions,
|
||||
_open_archive_heap_oopmaps,
|
||||
@ -1529,12 +1528,12 @@ void VM_PopulateDumpSharedSpace::print_region_stats() {
|
||||
const size_t total_reserved = _ro_region.reserved() + _rw_region.reserved() +
|
||||
_mc_region.reserved() + _md_region.reserved() +
|
||||
_od_region.reserved() +
|
||||
_total_string_region_size +
|
||||
_total_closed_archive_region_size +
|
||||
_total_open_archive_region_size;
|
||||
const size_t total_bytes = _ro_region.used() + _rw_region.used() +
|
||||
_mc_region.used() + _md_region.used() +
|
||||
_od_region.used() +
|
||||
_total_string_region_size +
|
||||
_total_closed_archive_region_size +
|
||||
_total_open_archive_region_size;
|
||||
const double total_u_perc = percent_of(total_bytes, total_reserved);
|
||||
|
||||
@ -1543,7 +1542,7 @@ void VM_PopulateDumpSharedSpace::print_region_stats() {
|
||||
_ro_region.print(total_reserved);
|
||||
_md_region.print(total_reserved);
|
||||
_od_region.print(total_reserved);
|
||||
print_heap_region_stats(_closed_archive_heap_regions, "st", total_reserved);
|
||||
print_heap_region_stats(_closed_archive_heap_regions, "ca", total_reserved);
|
||||
print_heap_region_stats(_open_archive_heap_regions, "oa", total_reserved);
|
||||
|
||||
tty->print_cr("total : " SIZE_FORMAT_W(9) " [100.0%% of total] out of " SIZE_FORMAT_W(9) " bytes [%5.1f%% used]",
|
||||
@ -1715,7 +1714,7 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
|
||||
tty->print_cr("Rewriting and linking classes: done");
|
||||
|
||||
SystemDictionary::clear_invoke_method_table();
|
||||
HeapShared::init_archivable_static_fields(THREAD);
|
||||
HeapShared::init_subgraph_entry_fields(THREAD);
|
||||
|
||||
VM_PopulateDumpSharedSpace op;
|
||||
VMThread::execute(&op);
|
||||
|
||||
@ -76,13 +76,14 @@ class MetaspaceShared : AllStatic {
|
||||
num_non_heap_spaces = od + 1,
|
||||
|
||||
// mapped java heap regions
|
||||
first_string = od + 1, // index of first string region
|
||||
max_strings = 2, // max number of string regions in string space
|
||||
last_string = first_string + max_strings - 1,
|
||||
first_open_archive_heap_region = first_string + max_strings,
|
||||
first_closed_archive_heap_region = od + 1,
|
||||
max_closed_archive_heap_region = 2,
|
||||
last_closed_archive_heap_region = first_closed_archive_heap_region + max_closed_archive_heap_region - 1,
|
||||
first_open_archive_heap_region = last_closed_archive_heap_region + 1,
|
||||
max_open_archive_heap_region = 2,
|
||||
last_open_archive_heap_region = first_open_archive_heap_region + max_open_archive_heap_region - 1,
|
||||
|
||||
last_valid_region = first_open_archive_heap_region + max_open_archive_heap_region - 1,
|
||||
last_valid_region = last_open_archive_heap_region,
|
||||
n_regions = last_valid_region + 1 // total number of regions
|
||||
};
|
||||
|
||||
@ -131,23 +132,6 @@ class MetaspaceShared : AllStatic {
|
||||
// Return true if given address is in the shared region corresponding to the idx
|
||||
static bool is_in_shared_region(const void* p, int idx) NOT_CDS_RETURN_(false);
|
||||
|
||||
static bool is_heap_region(int idx) {
|
||||
CDS_JAVA_HEAP_ONLY(return (idx >= MetaspaceShared::first_string &&
|
||||
idx < MetaspaceShared::first_open_archive_heap_region +
|
||||
MetaspaceShared::max_open_archive_heap_region));
|
||||
NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
}
|
||||
static bool is_string_region(int idx) {
|
||||
CDS_JAVA_HEAP_ONLY(return (idx >= MetaspaceShared::first_string &&
|
||||
idx < MetaspaceShared::first_string + MetaspaceShared::max_strings));
|
||||
NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
}
|
||||
static bool is_open_archive_heap_region(int idx) {
|
||||
CDS_JAVA_HEAP_ONLY(return (idx >= MetaspaceShared::first_open_archive_heap_region &&
|
||||
idx < MetaspaceShared::first_open_archive_heap_region +
|
||||
MetaspaceShared::max_open_archive_heap_region));
|
||||
NOT_CDS_JAVA_HEAP_RETURN_(false);
|
||||
}
|
||||
static bool is_in_trampoline_frame(address addr) NOT_CDS_RETURN_(false);
|
||||
|
||||
static void allocate_cpp_vtable_clones();
|
||||
|
||||
@ -1774,7 +1774,7 @@ WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
|
||||
WB_END
|
||||
|
||||
WB_ENTRY(jboolean, WB_AreSharedStringsIgnored(JNIEnv* env))
|
||||
return !StringTable::shared_string_mapped();
|
||||
return !HeapShared::closed_archive_heap_region_mapped();
|
||||
WB_END
|
||||
|
||||
WB_ENTRY(jobject, WB_GetResolvedReferences(JNIEnv* env, jobject wb, jclass clazz))
|
||||
|
||||
@ -992,6 +992,12 @@ public final class Integer extends Number implements Comparable<Integer> {
|
||||
* During VM initialization, java.lang.Integer.IntegerCache.high property
|
||||
* may be set and saved in the private system properties in the
|
||||
* jdk.internal.misc.VM class.
|
||||
*
|
||||
* WARNING: The cache is archived with CDS and reloaded from the shared
|
||||
* archive at runtime. The archived cache (Integer[]) and Integer objects
|
||||
* reside in the closed archive heap regions. Care should be taken when
|
||||
* changing the implementation and the cache array should not be assigned
|
||||
* with new Integer object(s) after initialization.
|
||||
*/
|
||||
|
||||
private static class IntegerCache {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user