8174986: CDS archived java heap region may not compatible with AOT

Always uses LogKlassAlignmentInBytes for narrow_klass_shift when CDS is enabled.

Reviewed-by: iklam, ccheung
This commit is contained in:
Jiangli Zhou 2017-10-06 19:33:27 -04:00
parent e24a5bc2ff
commit 3ccd60110d
6 changed files with 89 additions and 59 deletions

View File

@ -182,6 +182,7 @@ void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment
_obj_alignment = ObjectAlignmentInBytes;
_compact_strings = CompactStrings;
_narrow_oop_mode = Universe::narrow_oop_mode();
_narrow_oop_base = Universe::narrow_oop_base();
_narrow_oop_shift = Universe::narrow_oop_shift();
_max_heap_size = MaxHeapSize;
_narrow_klass_base = Universe::narrow_klass_base();
@ -687,8 +688,14 @@ static int num_open_archive_heap_ranges = 0;
// open archive objects.
void FileMapInfo::map_heap_regions() {
if (MetaspaceShared::is_heap_object_archiving_allowed()) {
log_info(cds)("Archived narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
narrow_oop_mode(), p2i(narrow_oop_base()), narrow_oop_shift());
log_info(cds)("Archived narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
p2i(narrow_klass_base()), narrow_klass_shift());
// Check that all the narrow oop and klass encodings match the archive
if (narrow_oop_mode() != Universe::narrow_oop_mode() ||
narrow_oop_base() != Universe::narrow_oop_base() ||
narrow_oop_shift() != Universe::narrow_oop_shift() ||
narrow_klass_base() != Universe::narrow_klass_base() ||
narrow_klass_shift() != Universe::narrow_klass_shift()) {
@ -697,6 +704,11 @@ void FileMapInfo::map_heap_regions() {
"The current CompressedOops/CompressedClassPointers encoding differs from "
"that archived due to heap size change. The archive was dumped using max heap "
"size " UINTX_FORMAT "M.", max_heap_size()/M);
log_info(cds)("Current narrow_oop_mode = %d, narrow_oop_base = " PTR_FORMAT ", narrow_oop_shift = %d",
Universe::narrow_oop_mode(), p2i(Universe::narrow_oop_base()),
Universe::narrow_oop_shift());
log_info(cds)("Current narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",
p2i(Universe::narrow_klass_base()), Universe::narrow_klass_shift());
}
} else {
// First, map string regions as closed archive heap regions.

View File

@ -112,6 +112,7 @@ public:
int _version; // (from enum, above.)
size_t _alignment; // how shared archive should be aligned
int _obj_alignment; // value of ObjectAlignmentInBytes
address _narrow_oop_base; // compressed oop encoding base
int _narrow_oop_shift; // compressed oop encoding shift
bool _compact_strings; // value of CompactStrings
uintx _max_heap_size; // java max heap size during dumping
@ -203,12 +204,13 @@ public:
int version() { return _header->_version; }
size_t alignment() { return _header->_alignment; }
Universe::NARROW_OOP_MODE narrow_oop_mode() { return _header->_narrow_oop_mode; }
int narrow_oop_shift() { return _header->_narrow_oop_shift; }
uintx max_heap_size() { return _header->_max_heap_size; }
address narrow_klass_base() const { return _header->_narrow_klass_base; }
address narrow_oop_base() const { return _header->_narrow_oop_base; }
int narrow_oop_shift() const { return _header->_narrow_oop_shift; }
uintx max_heap_size() const { return _header->_max_heap_size; }
address narrow_klass_base() const { return _header->_narrow_klass_base; }
int narrow_klass_shift() const { return _header->_narrow_klass_shift; }
struct FileMapHeader* header() { return _header; }
char* misc_data_patching_start() { return _header->_misc_data_patching_start; }
struct FileMapHeader* header() { return _header; }
char* misc_data_patching_start() { return _header->_misc_data_patching_start; }
void set_misc_data_patching_start(char* p) { _header->_misc_data_patching_start = p; }
char* read_only_tables_start() { return _header->_read_only_tables_start; }
void set_read_only_tables_start(char* p) { _header->_read_only_tables_start = p; }

View File

@ -3103,10 +3103,16 @@ void Metaspace::set_narrow_klass_base_and_shift(address metaspace_base, address
Universe::set_narrow_klass_base(lower_base);
if ((uint64_t)(higher_address - lower_base) <= UnscaledClassSpaceMax) {
// CDS uses LogKlassAlignmentInBytes for narrow_klass_shift. See
// MetaspaceShared::initialize_dumptime_shared_and_meta_spaces() for
// how dump time narrow_klass_shift is set. Although, CDS can work
// with zero-shift mode also, to be consistent with AOT it uses
// LogKlassAlignmentInBytes for klass shift so archived java heap objects
// can be used at same time as AOT code.
if (!UseSharedSpaces
&& (uint64_t)(higher_address - lower_base) <= UnscaledClassSpaceMax) {
Universe::set_narrow_klass_shift(0);
} else {
assert(!UseSharedSpaces, "Cannot shift with UseSharedSpaces");
Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes);
}
AOTLoader::set_narrow_klass_shift();
@ -3325,50 +3331,25 @@ void Metaspace::global_initialize() {
#if INCLUDE_CDS
if (DumpSharedSpaces) {
MetaspaceShared::initialize_shared_rs();
MetaspaceShared::initialize_dumptime_shared_and_meta_spaces();
} else if (UseSharedSpaces) {
// If using shared space, open the file that contains the shared space
// and map in the memory before initializing the rest of metaspace (so
// the addresses don't conflict)
address cds_address = NULL;
FileMapInfo* mapinfo = new FileMapInfo();
// Open the shared archive file, read and validate the header. If
// initialization fails, shared spaces [UseSharedSpaces] are
// disabled and the file is closed.
// Map in spaces now also
if (mapinfo->initialize() && MetaspaceShared::map_shared_spaces(mapinfo)) {
size_t cds_total = MetaspaceShared::core_spaces_size();
cds_address = (address)mapinfo->header()->region_addr(0);
#ifdef _LP64
if (using_class_space()) {
char* cds_end = (char*)(cds_address + cds_total);
cds_end = (char *)align_up(cds_end, _reserve_alignment);
// If UseCompressedClassPointers is set then allocate the metaspace area
// above the heap and above the CDS area (if it exists).
allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address);
// map_heap_regions() compares the current narrow oop and klass encodings
// with the archived ones, so it must be done after all encodings are determined.
mapinfo->map_heap_regions();
}
#endif // _LP64
} else {
assert(!mapinfo->is_open() && !UseSharedSpaces,
"archive file not closed or shared spaces not disabled.");
}
// If any of the archived space fails to map, UseSharedSpaces
// is reset to false. Fall through to the
// (!DumpSharedSpaces && !UseSharedSpaces) case to set up class
// metaspace.
MetaspaceShared::initialize_runtime_shared_and_meta_spaces();
}
#endif // INCLUDE_CDS
if (!DumpSharedSpaces && !UseSharedSpaces)
#endif // INCLUDE_CDS
{
#ifdef _LP64
if (!UseSharedSpaces && using_class_space()) {
if (DumpSharedSpaces) {
// Already initialized inside MetaspaceShared::initialize_shared_rs()
} else {
if (using_class_space()) {
char* base = (char*)align_up(Universe::heap()->reserved_region().end(), _reserve_alignment);
allocate_metaspace_compressed_klass_ptrs(base, 0);
}
}
#endif // _LP64
}
// Initialize these before initializing the VirtualSpaceList
_first_chunk_word_size = InitialBootClassLoaderMetaspaceSize / BytesPerWord;

View File

@ -179,6 +179,10 @@ class Metaspace : public CHeapObj<mtClass> {
assert(DumpSharedSpaces, "sanity");
DEBUG_ONLY(_frozen = true;)
}
#ifdef _LP64
static void allocate_metaspace_compressed_klass_ptrs(char* requested_addr, address cds_base);
#endif
private:
#ifdef _LP64
@ -187,8 +191,6 @@ class Metaspace : public CHeapObj<mtClass> {
// Returns true if can use CDS with metaspace allocated as specified address.
static bool can_use_cds_with_metaspace_addr(char* metaspace_base, address cds_base);
static void allocate_metaspace_compressed_klass_ptrs(char* requested_addr, address cds_base);
static void initialize_class_space(ReservedSpace rs);
#endif
size_t class_chunk_size(size_t word_size);

View File

@ -214,7 +214,42 @@ char* MetaspaceShared::read_only_space_alloc(size_t num_bytes) {
return _ro_region.allocate(num_bytes);
}
void MetaspaceShared::initialize_shared_rs() {
void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
assert(UseSharedSpaces, "Must be called when UseSharedSpaces is enabled");
// If using shared space, open the file that contains the shared space
// and map in the memory before initializing the rest of metaspace (so
// the addresses don't conflict)
address cds_address = NULL;
FileMapInfo* mapinfo = new FileMapInfo();
// Open the shared archive file, read and validate the header. If
// initialization fails, shared spaces [UseSharedSpaces] are
// disabled and the file is closed.
// Map in spaces now also
if (mapinfo->initialize() && map_shared_spaces(mapinfo)) {
size_t cds_total = core_spaces_size();
cds_address = (address)mapinfo->header()->region_addr(0);
#ifdef _LP64
if (Metaspace::using_class_space()) {
char* cds_end = (char*)(cds_address + cds_total);
cds_end = (char *)align_up(cds_end, Metaspace::reserve_alignment());
// If UseCompressedClassPointers is set then allocate the metaspace area
// above the heap and above the CDS area (if it exists).
Metaspace::allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address);
// map_heap_regions() compares the current narrow oop and klass encodings
// with the archived ones, so it must be done after all encodings are determined.
mapinfo->map_heap_regions();
}
#endif // _LP64
} else {
assert(!mapinfo->is_open() && !UseSharedSpaces,
"archive file not closed or shared spaces not disabled.");
}
}
void MetaspaceShared::initialize_dumptime_shared_and_meta_spaces() {
assert(DumpSharedSpaces, "should be called for dump time only");
const size_t reserve_alignment = Metaspace::reserve_alignment();
bool large_pages = false; // No large pages when dumping the CDS archive.
char* shared_base = (char*)align_up((char*)SharedBaseAddress, reserve_alignment);
@ -223,12 +258,12 @@ void MetaspaceShared::initialize_shared_rs() {
// On 64-bit VM, the heap and class space layout will be the same as if
// you're running in -Xshare:on mode:
//
// +-- SharedBaseAddress (default = 0x800000000)
// v
// +-..---------+----+ ... +----+----+----+----+----+---------------+
// | Heap | ST | | MC | RW | RO | MD | OD | class space |
// +-..---------+----+ ... +----+----+----+----+----+---------------+
// |<--MaxHeapSize->| |<-- UnscaledClassSpaceMax = 4GB ------->|
// +-- SharedBaseAddress (default = 0x800000000)
// v
// +-..---------+---------+ ... +----+----+----+----+----+---------------+
// | Heap | Archive | | MC | RW | RO | MD | OD | class space |
// +-..---------+---------+ ... +----+----+----+----+----+---------------+
// |<-- MaxHeapSize -->| |<-- UnscaledClassSpaceMax = 4GB ------->|
//
const uint64_t UnscaledClassSpaceMax = (uint64_t(max_juint) + 1);
const size_t cds_total = align_down(UnscaledClassSpaceMax, reserve_alignment);
@ -268,12 +303,9 @@ void MetaspaceShared::initialize_shared_rs() {
// Set up compress class pointers.
Universe::set_narrow_klass_base((address)_shared_rs.base());
if (UseAOT || cds_total > UnscaledClassSpaceMax) {
// AOT forces narrow_klass_shift=LogKlassAlignmentInBytes
Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes);
} else {
Universe::set_narrow_klass_shift(0);
}
// Set narrow_klass_shift to be LogKlassAlignmentInBytes. This is consistent
// with AOT.
Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes);
Metaspace::initialize_class_space(tmp_class_space);
tty->print_cr("narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d",

View File

@ -146,7 +146,8 @@ class MetaspaceShared : AllStatic {
static size_t core_spaces_size() {
return _core_spaces_size;
}
static void initialize_shared_rs() NOT_CDS_RETURN;
static void initialize_dumptime_shared_and_meta_spaces() NOT_CDS_RETURN;
static void initialize_runtime_shared_and_meta_spaces() NOT_CDS_RETURN;
// Delta of this object from the bottom of the archive.
static uintx object_delta(void* obj) {