8236847: CDS archive with 4K alignment unusable on machines with 64k pages
Reviewed-by: iklam, stuefe, erikj, ihse
This commit is contained in:
parent
273f8bdf5f
commit
3820ab9e82
@ -248,6 +248,7 @@ JDKOPT_ENABLE_DISABLE_GENERATE_CLASSLIST
|
||||
JDKOPT_EXCLUDE_TRANSLATIONS
|
||||
JDKOPT_ENABLE_DISABLE_MANPAGES
|
||||
JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE
|
||||
JDKOPT_ENABLE_DISABLE_COMPATIBLE_CDS_ALIGNMENT
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2021, 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
|
||||
@ -585,6 +585,30 @@ AC_DEFUN([JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE],
|
||||
AC_SUBST(BUILD_CDS_ARCHIVE)
|
||||
])
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Enable the alternative CDS core region alignment
|
||||
#
|
||||
AC_DEFUN([JDKOPT_ENABLE_DISABLE_COMPATIBLE_CDS_ALIGNMENT],
|
||||
[
|
||||
UTIL_ARG_ENABLE(NAME: compatible-cds-alignment, DEFAULT: false,
|
||||
RESULT: ENABLE_COMPATIBLE_CDS_ALIGNMENT,
|
||||
DESC: [enable use alternative compatible cds core region alignment],
|
||||
DEFAULT_DESC: [disabled],
|
||||
CHECKING_MSG: [if compatible cds region alignment enabled],
|
||||
CHECK_AVAILABLE: [
|
||||
AC_MSG_CHECKING([if CDS archive is available])
|
||||
if test "x$BUILD_CDS_ARCHIVE" = "xfalse"; then
|
||||
AVAILABLE=false
|
||||
AC_MSG_RESULT([no (CDS is disabled)])
|
||||
else
|
||||
AVAILABLE=true
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
])
|
||||
AC_SUBST(ENABLE_COMPATIBLE_CDS_ALIGNMENT)
|
||||
])
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Disallow any output from containing absolute paths from the build system.
|
||||
|
@ -349,6 +349,8 @@ BUILD_MANPAGES := @BUILD_MANPAGES@
|
||||
|
||||
BUILD_CDS_ARCHIVE := @BUILD_CDS_ARCHIVE@
|
||||
|
||||
ENABLE_COMPATIBLE_CDS_ALIGNMENT := @ENABLE_COMPATIBLE_CDS_ALIGNMENT@
|
||||
|
||||
ALLOW_ABSOLUTE_PATHS_IN_OUTPUT := @ALLOW_ABSOLUTE_PATHS_IN_OUTPUT@
|
||||
|
||||
# The boot jdk to use. This is overridden in bootcycle-spec.gmk. Make sure to keep
|
||||
|
@ -441,6 +441,7 @@ var getJibProfilesProfiles = function (input, common, data) {
|
||||
dependencies: ["devkit", "gtest", "pandoc"],
|
||||
configure_args: concat(common.configure_args_64bit, "--with-zlib=system",
|
||||
"--with-macosx-version-max=10.12.00",
|
||||
"--enable-compatible-cds-alignment",
|
||||
// Use system SetFile instead of the one in the devkit as the
|
||||
// devkit one may not work on Catalina.
|
||||
"SETFILE=/usr/bin/SetFile"),
|
||||
@ -477,6 +478,7 @@ var getJibProfilesProfiles = function (input, common, data) {
|
||||
dependencies: ["devkit", "gtest", "build_devkit", "pandoc"],
|
||||
configure_args: [
|
||||
"--openjdk-target=aarch64-linux-gnu",
|
||||
"--enable-compatible-cds-alignment",
|
||||
],
|
||||
},
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2013, 2021, 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
|
||||
@ -99,3 +99,7 @@ endif
|
||||
ifneq ($(HOTSPOT_OVERRIDE_LIBPATH), )
|
||||
JVM_CFLAGS += -DOVERRIDE_LIBPATH='"$(HOTSPOT_OVERRIDE_LIBPATH)"'
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_COMPATIBLE_CDS_ALIGNMENT), true)
|
||||
JVM_CFLAGS += -DCOMPATIBLE_CDS_ALIGNMENT
|
||||
endif
|
||||
|
@ -25,6 +25,12 @@
|
||||
#ifndef OS_CPU_BSD_X86_OS_BSD_X86_HPP
|
||||
#define OS_CPU_BSD_X86_OS_BSD_X86_HPP
|
||||
|
||||
// Core region alignment is 16K to be able to run binaries built on MacOS x64
|
||||
// on MacOS aarch64.
|
||||
#if defined(__APPLE__) && defined(COMPATIBLE_CDS_ALIGNMENT)
|
||||
#define CDS_CORE_REGION_ALIGNMENT (16*K)
|
||||
#endif
|
||||
|
||||
static void setup_fpu();
|
||||
static bool supports_sse();
|
||||
static juint cpu_microcode_revision();
|
||||
|
@ -26,6 +26,10 @@
|
||||
#ifndef OS_CPU_LINUX_AARCH64_OS_LINUX_AARCH64_HPP
|
||||
#define OS_CPU_LINUX_AARCH64_OS_LINUX_AARCH64_HPP
|
||||
|
||||
#if defined(COMPATIBLE_CDS_ALIGNMENT)
|
||||
#define CDS_CORE_REGION_ALIGNMENT (64*K)
|
||||
#endif
|
||||
|
||||
static void setup_fpu();
|
||||
|
||||
static bool is_allocatable(size_t bytes);
|
||||
|
@ -327,19 +327,19 @@ size_t ArchiveBuilder::estimate_archive_size() {
|
||||
total += _estimated_hashtable_bytes;
|
||||
|
||||
// allow fragmentation at the end of each dump region
|
||||
total += _total_dump_regions * reserve_alignment();
|
||||
total += _total_dump_regions * MetaspaceShared::core_region_alignment();
|
||||
|
||||
log_info(cds)("_estimated_hashtable_bytes = " SIZE_FORMAT " + " SIZE_FORMAT " = " SIZE_FORMAT,
|
||||
symbol_table_est, dictionary_est, _estimated_hashtable_bytes);
|
||||
log_info(cds)("_estimated_metaspaceobj_bytes = " SIZE_FORMAT, _estimated_metaspaceobj_bytes);
|
||||
log_info(cds)("total estimate bytes = " SIZE_FORMAT, total);
|
||||
|
||||
return align_up(total, reserve_alignment());
|
||||
return align_up(total, MetaspaceShared::core_region_alignment());
|
||||
}
|
||||
|
||||
address ArchiveBuilder::reserve_buffer() {
|
||||
size_t buffer_size = estimate_archive_size();
|
||||
ReservedSpace rs(buffer_size);
|
||||
ReservedSpace rs(buffer_size, MetaspaceShared::core_region_alignment(), false);
|
||||
if (!rs.is_reserved()) {
|
||||
log_error(cds)("Failed to reserve " SIZE_FORMAT " bytes of output buffer.", buffer_size);
|
||||
vm_direct_exit(0);
|
||||
@ -377,7 +377,7 @@ address ArchiveBuilder::reserve_buffer() {
|
||||
|
||||
// At run time, we will mmap the dynamic archive at my_archive_requested_bottom
|
||||
_requested_static_archive_top = _requested_static_archive_bottom + static_archive_size;
|
||||
my_archive_requested_bottom = align_up(_requested_static_archive_top, MetaspaceShared::reserved_space_alignment());
|
||||
my_archive_requested_bottom = align_up(_requested_static_archive_top, MetaspaceShared::core_region_alignment());
|
||||
|
||||
_requested_dynamic_archive_bottom = my_archive_requested_bottom;
|
||||
}
|
||||
|
@ -223,9 +223,8 @@ private:
|
||||
static ArchiveBuilder* _current;
|
||||
|
||||
public:
|
||||
// Use this when you allocate space with MetaspaceShare::read_only_space_alloc()
|
||||
// outside of ArchiveBuilder::dump_{rw,ro}_region. These are usually for misc tables
|
||||
// that are allocated in the RO space.
|
||||
// Use this when you allocate space outside of ArchiveBuilder::dump_{rw,ro}_region.
|
||||
// These are usually for misc tables that are allocated in the RO space.
|
||||
class OtherROAllocMark {
|
||||
char* _oldtop;
|
||||
public:
|
||||
@ -265,10 +264,6 @@ protected:
|
||||
|
||||
size_t estimate_archive_size();
|
||||
|
||||
static size_t reserve_alignment() {
|
||||
return os::vm_allocation_granularity();
|
||||
}
|
||||
|
||||
void start_dump_space(DumpRegion* next);
|
||||
void verify_estimate_size(size_t estimate, const char* which);
|
||||
|
||||
|
@ -246,7 +246,7 @@ void DumpRegion::init(ReservedSpace* rs, VirtualSpace* vs) {
|
||||
|
||||
void DumpRegion::pack(DumpRegion* next) {
|
||||
assert(!is_packed(), "sanity");
|
||||
_end = (char*)align_up(_top, MetaspaceShared::reserved_space_alignment());
|
||||
_end = (char*)align_up(_top, MetaspaceShared::core_region_alignment());
|
||||
_is_packed = true;
|
||||
if (next != NULL) {
|
||||
next->_rs = _rs;
|
||||
|
@ -47,12 +47,6 @@
|
||||
|
||||
|
||||
class DynamicArchiveBuilder : public ArchiveBuilder {
|
||||
public:
|
||||
|
||||
static size_t reserve_alignment() {
|
||||
return os::vm_allocation_granularity();
|
||||
}
|
||||
|
||||
public:
|
||||
void mark_pointer(address* ptr_loc) {
|
||||
ArchivePtrMarker::mark_pointer(ptr_loc);
|
||||
@ -179,7 +173,7 @@ void DynamicArchiveBuilder::init_header() {
|
||||
for (int i = 0; i < MetaspaceShared::n_regions; i++) {
|
||||
_header->set_base_region_crc(i, base_info->space_crc(i));
|
||||
}
|
||||
_header->populate(base_info, os::vm_allocation_granularity());
|
||||
_header->populate(base_info, base_info->core_region_alignment());
|
||||
}
|
||||
|
||||
void DynamicArchiveBuilder::release_header() {
|
||||
|
@ -198,18 +198,18 @@ FileMapInfo::~FileMapInfo() {
|
||||
}
|
||||
}
|
||||
|
||||
void FileMapInfo::populate_header(size_t alignment) {
|
||||
header()->populate(this, alignment);
|
||||
void FileMapInfo::populate_header(size_t core_region_alignment) {
|
||||
header()->populate(this, core_region_alignment);
|
||||
}
|
||||
|
||||
void FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
|
||||
void FileMapHeader::populate(FileMapInfo* mapinfo, size_t core_region_alignment) {
|
||||
if (DynamicDumpSharedSpaces) {
|
||||
_magic = CDS_DYNAMIC_ARCHIVE_MAGIC;
|
||||
} else {
|
||||
_magic = CDS_ARCHIVE_MAGIC;
|
||||
}
|
||||
_version = CURRENT_CDS_ARCHIVE_VERSION;
|
||||
_alignment = alignment;
|
||||
_core_region_alignment = core_region_alignment;
|
||||
_obj_alignment = ObjectAlignmentInBytes;
|
||||
_compact_strings = CompactStrings;
|
||||
if (HeapShared::is_heap_object_archiving_allowed()) {
|
||||
@ -267,7 +267,7 @@ void FileMapHeader::print(outputStream* st) {
|
||||
st->print_cr("============ end regions ======== ");
|
||||
|
||||
st->print_cr("- header_size: " SIZE_FORMAT, _header_size);
|
||||
st->print_cr("- alignment: " SIZE_FORMAT, _alignment);
|
||||
st->print_cr("- core_region_alignment: " SIZE_FORMAT, _core_region_alignment);
|
||||
st->print_cr("- obj_alignment: %d", _obj_alignment);
|
||||
st->print_cr("- narrow_oop_base: " INTPTR_FORMAT, p2i(_narrow_oop_base));
|
||||
st->print_cr("- narrow_oop_base: " INTPTR_FORMAT, p2i(_narrow_oop_base));
|
||||
@ -1225,7 +1225,7 @@ void FileMapInfo::open_for_write(const char* path) {
|
||||
header_bytes += strlen(Arguments::GetSharedArchivePath()) + 1;
|
||||
}
|
||||
|
||||
header_bytes = align_up(header_bytes, os::vm_allocation_granularity());
|
||||
header_bytes = align_up(header_bytes, MetaspaceShared::core_region_alignment());
|
||||
_file_offset = header_bytes;
|
||||
seek_to_position(_file_offset);
|
||||
}
|
||||
@ -1251,7 +1251,7 @@ void FileMapInfo::write_header() {
|
||||
}
|
||||
|
||||
size_t FileMapRegion::used_aligned() const {
|
||||
return align_up(used(), os::vm_allocation_granularity());
|
||||
return align_up(used(), MetaspaceShared::core_region_alignment());
|
||||
}
|
||||
|
||||
void FileMapRegion::init(int region_index, size_t mapping_offset, size_t size, bool read_only,
|
||||
@ -1456,7 +1456,7 @@ void FileMapInfo::write_bytes(const void* buffer, size_t nbytes) {
|
||||
|
||||
bool FileMapInfo::is_file_position_aligned() const {
|
||||
return _file_offset == align_up(_file_offset,
|
||||
os::vm_allocation_granularity());
|
||||
MetaspaceShared::core_region_alignment());
|
||||
}
|
||||
|
||||
// Align file position to an allocation unit boundary.
|
||||
@ -1464,7 +1464,7 @@ bool FileMapInfo::is_file_position_aligned() const {
|
||||
void FileMapInfo::align_file_position() {
|
||||
assert(_file_open, "must be");
|
||||
size_t new_file_offset = align_up(_file_offset,
|
||||
os::vm_allocation_granularity());
|
||||
MetaspaceShared::core_region_alignment());
|
||||
if (new_file_offset != _file_offset) {
|
||||
_file_offset = new_file_offset;
|
||||
// Seek one byte back from the target and write a byte to insure
|
||||
@ -1507,8 +1507,7 @@ bool FileMapInfo::remap_shared_readonly_as_readwrite() {
|
||||
// the space is already readwrite so we are done
|
||||
return true;
|
||||
}
|
||||
size_t used = si->used();
|
||||
size_t size = align_up(used, os::vm_allocation_granularity());
|
||||
size_t size = si->used_aligned();
|
||||
if (!open_for_read()) {
|
||||
return false;
|
||||
}
|
||||
@ -2088,8 +2087,7 @@ void FileMapInfo::unmap_region(int i) {
|
||||
assert(!HeapShared::is_heap_region(i), "sanity");
|
||||
FileMapRegion* si = space_at(i);
|
||||
char* mapped_base = si->mapped_base();
|
||||
size_t used = si->used();
|
||||
size_t size = align_up(used, os::vm_allocation_granularity());
|
||||
size_t size = si->used_aligned();
|
||||
|
||||
if (mapped_base != NULL) {
|
||||
if (size > 0 && si->mapped_from_file()) {
|
||||
|
@ -154,7 +154,7 @@ public:
|
||||
size_t mapping_offset() const { return _mapping_offset; }
|
||||
size_t mapping_end_offset() const { return _mapping_offset + used_aligned(); }
|
||||
size_t used() const { return _used; }
|
||||
size_t used_aligned() const; // aligned up to os::vm_allocation_granularity()
|
||||
size_t used_aligned() const; // aligned up to MetaspaceShared::core_region_alignment()
|
||||
char* mapped_base() const { assert_is_not_heap_region(); return _mapped_base; }
|
||||
char* mapped_end() const { return mapped_base() + used_aligned(); }
|
||||
bool read_only() const { return _read_only != 0; }
|
||||
@ -187,7 +187,7 @@ class FileMapHeader: private CDSFileMapHeaderBase {
|
||||
// The following fields record the states of the VM during dump time.
|
||||
// They are compared with the runtime states to see if the archive
|
||||
// can be used.
|
||||
size_t _alignment; // how shared archive should be aligned
|
||||
size_t _core_region_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
|
||||
@ -251,7 +251,7 @@ public:
|
||||
// Accessors -- fields declared in FileMapHeader
|
||||
|
||||
size_t header_size() const { return _header_size; }
|
||||
size_t alignment() const { return _alignment; }
|
||||
size_t core_region_alignment() const { return _core_region_alignment; }
|
||||
int obj_alignment() const { return _obj_alignment; }
|
||||
address narrow_oop_base() const { return _narrow_oop_base; }
|
||||
int narrow_oop_shift() const { return _narrow_oop_shift; }
|
||||
@ -312,7 +312,7 @@ public:
|
||||
return FileMapRegion::cast(&_space[i]);
|
||||
}
|
||||
|
||||
void populate(FileMapInfo* info, size_t alignment);
|
||||
void populate(FileMapInfo* info, size_t core_region_alignment);
|
||||
|
||||
static bool is_valid_region(int region) {
|
||||
return (0 <= region && region < NUM_CDS_REGIONS);
|
||||
@ -378,17 +378,17 @@ public:
|
||||
int compute_header_crc() const { return header()->compute_crc(); }
|
||||
void set_header_crc(int crc) { header()->set_crc(crc); }
|
||||
int space_crc(int i) const { return space_at(i)->crc(); }
|
||||
void populate_header(size_t alignment);
|
||||
void populate_header(size_t core_region_alignment);
|
||||
bool validate_header();
|
||||
void invalidate();
|
||||
int crc() const { return header()->crc(); }
|
||||
int version() const { return header()->version(); }
|
||||
size_t alignment() const { return header()->alignment(); }
|
||||
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(); }
|
||||
size_t core_region_alignment() const { return header()->core_region_alignment(); }
|
||||
|
||||
CompressedOops::Mode narrow_oop_mode() const { return header()->narrow_oop_mode(); }
|
||||
jshort app_module_paths_start_index() const { return header()->app_module_paths_start_index(); }
|
||||
|
@ -120,7 +120,21 @@ char* MetaspaceShared::symbol_space_alloc(size_t num_bytes) {
|
||||
return _symbol_region.allocate(num_bytes);
|
||||
}
|
||||
|
||||
size_t MetaspaceShared::reserved_space_alignment() { return os::vm_allocation_granularity(); }
|
||||
// os::vm_allocation_granularity() is usually 4K for most OSes. However, on Linux/aarch64,
|
||||
// it can be either 4K or 64K and on Macosx-arm it is 16K. To generate archives that are
|
||||
// compatible for both settings, an alternative cds core region alignment can be enabled
|
||||
// at building time:
|
||||
// --enable-compactible-cds-alignment
|
||||
// Upon successful configuration, the compactible alignment then can be defined as in:
|
||||
// os_linux_aarch64.hpp
|
||||
// which is the highest page size configured on the platform.
|
||||
size_t MetaspaceShared::core_region_alignment() {
|
||||
#if defined(CDS_CORE_REGION_ALIGNMENT)
|
||||
return CDS_CORE_REGION_ALIGNMENT;
|
||||
#else
|
||||
return (size_t)os::vm_allocation_granularity();
|
||||
#endif // CDS_CORE_REGION_ALIGNMENT
|
||||
}
|
||||
|
||||
static bool shared_base_valid(char* shared_base) {
|
||||
#ifdef _LP64
|
||||
@ -133,7 +147,7 @@ static bool shared_base_valid(char* shared_base) {
|
||||
static bool shared_base_too_high(char* specified_base, char* aligned_base, size_t cds_max) {
|
||||
if (specified_base != NULL && aligned_base < specified_base) {
|
||||
// SharedBaseAddress is very high (e.g., 0xffffffffffffff00) so
|
||||
// align_up(SharedBaseAddress, MetaspaceShared::reserved_space_alignment()) has wrapped around.
|
||||
// align_up(SharedBaseAddress, MetaspaceShared::core_region_alignment()) has wrapped around.
|
||||
return true;
|
||||
}
|
||||
if (max_uintx - uintx(aligned_base) < uintx(cds_max)) {
|
||||
@ -146,7 +160,7 @@ static bool shared_base_too_high(char* specified_base, char* aligned_base, size_
|
||||
|
||||
static char* compute_shared_base(size_t cds_max) {
|
||||
char* specified_base = (char*)SharedBaseAddress;
|
||||
char* aligned_base = align_up(specified_base, MetaspaceShared::reserved_space_alignment());
|
||||
char* aligned_base = align_up(specified_base, MetaspaceShared::core_region_alignment());
|
||||
|
||||
const char* err = NULL;
|
||||
if (shared_base_too_high(specified_base, aligned_base, cds_max)) {
|
||||
@ -162,7 +176,7 @@ static char* compute_shared_base(size_t cds_max) {
|
||||
p2i((void*)Arguments::default_SharedBaseAddress()));
|
||||
|
||||
specified_base = (char*)Arguments::default_SharedBaseAddress();
|
||||
aligned_base = align_up(specified_base, MetaspaceShared::reserved_space_alignment());
|
||||
aligned_base = align_up(specified_base, MetaspaceShared::core_region_alignment());
|
||||
|
||||
// Make sure the default value of SharedBaseAddress specified in globals.hpp is sane.
|
||||
assert(!shared_base_too_high(specified_base, aligned_base, cds_max), "Sanity");
|
||||
@ -172,11 +186,11 @@ static char* compute_shared_base(size_t cds_max) {
|
||||
|
||||
void MetaspaceShared::initialize_for_static_dump() {
|
||||
assert(DumpSharedSpaces, "should be called for dump time only");
|
||||
|
||||
log_info(cds)("Core region alignment: " SIZE_FORMAT, core_region_alignment());
|
||||
// The max allowed size for CDS archive. We use this to limit SharedBaseAddress
|
||||
// to avoid address space wrap around.
|
||||
size_t cds_max;
|
||||
const size_t reserve_alignment = MetaspaceShared::reserved_space_alignment();
|
||||
const size_t reserve_alignment = core_region_alignment();
|
||||
|
||||
#ifdef _LP64
|
||||
const uint64_t UnscaledClassSpaceMax = (uint64_t(max_juint) + 1);
|
||||
@ -491,7 +505,7 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||
|
||||
// Write the archive file
|
||||
FileMapInfo* mapinfo = new FileMapInfo(true);
|
||||
mapinfo->populate_header(os::vm_allocation_granularity());
|
||||
mapinfo->populate_header(MetaspaceShared::core_region_alignment());
|
||||
mapinfo->set_serialized_data(serialized_data);
|
||||
mapinfo->set_cloned_vtables(cloned_vtables);
|
||||
mapinfo->open_for_write();
|
||||
@ -854,6 +868,7 @@ void MetaspaceShared::initialize_runtime_shared_and_meta_spaces() {
|
||||
FileMapInfo* dynamic_mapinfo = NULL;
|
||||
|
||||
if (static_mapinfo != NULL) {
|
||||
log_info(cds)("Core region alignment: " SIZE_FORMAT, static_mapinfo->core_region_alignment());
|
||||
dynamic_mapinfo = open_dynamic_archive();
|
||||
|
||||
// First try to map at the requested address
|
||||
@ -974,7 +989,7 @@ MapArchiveResult MetaspaceShared::map_archives(FileMapInfo* static_mapinfo, File
|
||||
assert(class_space_rs.base() >= archive_space_rs.end(),
|
||||
"class space should follow the cds archive space");
|
||||
assert(is_aligned(archive_space_rs.base(),
|
||||
MetaspaceShared::reserved_space_alignment()),
|
||||
core_region_alignment()),
|
||||
"Archive space misaligned");
|
||||
assert(is_aligned(class_space_rs.base(),
|
||||
Metaspace::reserve_alignment()),
|
||||
@ -982,9 +997,9 @@ MapArchiveResult MetaspaceShared::map_archives(FileMapInfo* static_mapinfo, File
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
log_debug(cds)("Reserved archive_space_rs [" INTPTR_FORMAT " - " INTPTR_FORMAT "] (" SIZE_FORMAT ") bytes",
|
||||
log_info(cds)("Reserved archive_space_rs [" INTPTR_FORMAT " - " INTPTR_FORMAT "] (" SIZE_FORMAT ") bytes",
|
||||
p2i(archive_space_rs.base()), p2i(archive_space_rs.end()), archive_space_rs.size());
|
||||
log_debug(cds)("Reserved class_space_rs [" INTPTR_FORMAT " - " INTPTR_FORMAT "] (" SIZE_FORMAT ") bytes",
|
||||
log_info(cds)("Reserved class_space_rs [" INTPTR_FORMAT " - " INTPTR_FORMAT "] (" SIZE_FORMAT ") bytes",
|
||||
p2i(class_space_rs.base()), p2i(class_space_rs.end()), class_space_rs.size());
|
||||
|
||||
if (MetaspaceShared::use_windows_memory_mapping()) {
|
||||
@ -1146,7 +1161,7 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
|
||||
ReservedSpace& class_space_rs) {
|
||||
|
||||
address const base_address = (address) (use_archive_base_addr ? static_mapinfo->requested_base_address() : NULL);
|
||||
const size_t archive_space_alignment = MetaspaceShared::reserved_space_alignment();
|
||||
const size_t archive_space_alignment = core_region_alignment();
|
||||
|
||||
// Size and requested location of the archive_space_rs (for both static and dynamic archives)
|
||||
assert(static_mapinfo->mapping_base_offset() == 0, "Must be");
|
||||
@ -1204,8 +1219,7 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
|
||||
const size_t gap_size = ccs_begin_offset - archive_space_size;
|
||||
|
||||
const size_t total_range_size =
|
||||
align_up(archive_space_size + gap_size + class_space_size,
|
||||
os::vm_allocation_granularity());
|
||||
align_up(archive_space_size + gap_size + class_space_size, core_region_alignment());
|
||||
|
||||
assert(total_range_size > ccs_begin_offset, "must be");
|
||||
if (use_windows_memory_mapping() && use_archive_base_addr) {
|
||||
@ -1248,7 +1262,7 @@ char* MetaspaceShared::reserve_address_space_for_archives(FileMapInfo* static_ma
|
||||
// Now split up the space into ccs and cds archive. For simplicity, just leave
|
||||
// the gap reserved at the end of the archive space. Do not do real splitting.
|
||||
archive_space_rs = total_space_rs.first_part(ccs_begin_offset,
|
||||
(size_t)os::vm_allocation_granularity());
|
||||
(size_t)archive_space_alignment);
|
||||
class_space_rs = total_space_rs.last_part(ccs_begin_offset);
|
||||
MemTracker::record_virtual_memory_split_reserved(total_space_rs.base(), total_space_rs.size(),
|
||||
ccs_begin_offset);
|
||||
@ -1299,10 +1313,9 @@ MapArchiveResult MetaspaceShared::map_archive(FileMapInfo* mapinfo, char* mapped
|
||||
}
|
||||
|
||||
mapinfo->set_is_mapped(false);
|
||||
|
||||
if (mapinfo->alignment() != (size_t)os::vm_allocation_granularity()) {
|
||||
log_info(cds)("Unable to map CDS archive -- os::vm_allocation_granularity() expected: " SIZE_FORMAT
|
||||
" actual: %d", mapinfo->alignment(), os::vm_allocation_granularity());
|
||||
if (mapinfo->core_region_alignment() != (size_t)core_region_alignment()) {
|
||||
log_info(cds)("Unable to map CDS archive -- core_region_alignment() expected: " SIZE_FORMAT
|
||||
" actual: " SIZE_FORMAT, mapinfo->core_region_alignment(), core_region_alignment());
|
||||
return MAP_ARCHIVE_OTHER_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -133,7 +133,9 @@ class MetaspaceShared : AllStatic {
|
||||
static bool linking_required(InstanceKlass* ik) NOT_CDS_RETURN_(false);
|
||||
|
||||
#if INCLUDE_CDS
|
||||
static size_t reserved_space_alignment();
|
||||
// Alignment for the 3 core CDS regions (MC/RW/RO) only.
|
||||
// (Heap region alignments are decided by GC).
|
||||
static size_t core_region_alignment();
|
||||
static void rewrite_nofast_bytecodes_and_calculate_fingerprints(Thread* thread, InstanceKlass* ik);
|
||||
#endif
|
||||
|
||||
|
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @requires vm.cds
|
||||
* @requires vm.gc != "Z"
|
||||
* @summary Testing handling of CDS region alignment
|
||||
* @comment ZGC may exit the VM if -XX:+UseLargePages is specified but
|
||||
* unavailable. Since this test is independent of the actual GC type, let's
|
||||
* disable it if ZGC is used.
|
||||
* @bug 8236847
|
||||
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes
|
||||
* @build Hello
|
||||
* @run driver ClassFileInstaller -jar hello.jar Hello
|
||||
* @run driver SharedRegionAlignmentTest
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
|
||||
public class SharedRegionAlignmentTest {
|
||||
static String appJar = ClassFileInstaller.getJarPath("hello.jar");
|
||||
static String mainClass = "Hello";
|
||||
static String logArg = "-Xlog:cds";
|
||||
|
||||
static void testCombo() throws Exception {
|
||||
// Test the following combinations:
|
||||
// Dump (3 combinations): largePageArgs
|
||||
// Run (3 combinations): largePageArgs
|
||||
String UseLargePages = "-XX:+UseLargePages";
|
||||
|
||||
String [][] largePageArgs = {
|
||||
{}, // default
|
||||
{UseLargePages}
|
||||
};
|
||||
|
||||
final String logFor64K = "core_region_alignment = 65535";
|
||||
|
||||
int dumpCase = 0;
|
||||
for (String[] dumpLP: largePageArgs) {
|
||||
dumpCase ++;
|
||||
System.out.println("============================================================");
|
||||
System.out.println("dump case (" + dumpCase + "): " + formatLargePageArgs(dumpLP));
|
||||
System.out.println("============================================================");
|
||||
|
||||
OutputAnalyzer out = TestCommon.dump(appJar,
|
||||
TestCommon.list(mainClass),
|
||||
TestCommon.concat(dumpLP, logArg));
|
||||
out.shouldContain("Dumping shared data to file");
|
||||
boolean is_aligned_64k = out.getStdout().contains(logFor64K);
|
||||
|
||||
int runCase = 0;
|
||||
for (String[] runLP: largePageArgs) {
|
||||
runCase++;
|
||||
System.out.println("--------------------------------------------------");
|
||||
System.out.println("run case (" + dumpCase + "." + runCase + "):" + formatLargePageArgs(runLP));
|
||||
System.out.println("--------------------------------------------------");
|
||||
|
||||
TestCommon.run(TestCommon.concat(runLP, "-cp", appJar, logArg, mainClass))
|
||||
.assertNormalExit(output -> {
|
||||
if (is_aligned_64k) {
|
||||
output.shouldContain(logFor64K);
|
||||
}
|
||||
output.shouldContain("Hello World");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static String formatLargePageArgs(String args[]) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String a : args) {
|
||||
sb.append(" ");
|
||||
sb.append(a);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
testCombo();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user