8253909: Implement detailed map file for CDS

Reviewed-by: stuefe, ccheung
This commit is contained in:
Ioi Lam 2020-10-08 06:55:42 +00:00
parent 7733a0e76b
commit d1e94eebdd
10 changed files with 377 additions and 61 deletions

@ -98,6 +98,7 @@
LOG_TAG(loader) \
LOG_TAG(logging) \
LOG_TAG(malloc) \
LOG_TAG(map) \
LOG_TAG(mark) \
LOG_TAG(marking) \
LOG_TAG(membername) \

@ -26,11 +26,13 @@
#include "classfile/classLoaderDataShared.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "logging/log.hpp"
#include "logging/logMessage.hpp"
#include "logging/logStream.hpp"
#include "memory/allStatic.hpp"
#include "memory/archiveBuilder.hpp"
#include "memory/archiveUtils.hpp"
#include "memory/cppVtables.hpp"
#include "memory/dumpAllocStats.hpp"
#include "memory/memRegion.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
@ -134,7 +136,7 @@ void ArchiveBuilder::SourceObjList::relocate(int i, ArchiveBuilder* builder) {
_ptrmap.iterate(&relocator, start, end);
}
ArchiveBuilder::ArchiveBuilder(DumpRegion* rw_region, DumpRegion* ro_region)
ArchiveBuilder::ArchiveBuilder(DumpRegion* mc_region, DumpRegion* rw_region, DumpRegion* ro_region)
: _rw_src_objs(), _ro_src_objs(), _src_obj_table(INITIAL_TABLE_SIZE) {
assert(_singleton == NULL, "must be");
_singleton = this;
@ -148,6 +150,7 @@ ArchiveBuilder::ArchiveBuilder(DumpRegion* rw_region, DumpRegion* ro_region)
_num_type_array_klasses = 0;
_alloc_stats = new (ResourceObj::C_HEAP, mtClassShared) DumpAllocStats;
_mc_region = mc_region;
_rw_region = rw_region;
_ro_region = ro_region;
@ -294,13 +297,13 @@ void ArchiveBuilder::iterate_sorted_roots(MetaspaceClosure* it, bool is_relocati
// original symbols.
int num_symbols = _symbols->length();
for (i = 0; i < num_symbols; i++) {
it->push(&_symbols->at(i));
it->push(_symbols->adr_at(i));
}
}
int num_klasses = _klasses->length();
for (i = 0; i < num_klasses; i++) {
it->push(&_klasses->at(i));
it->push(_klasses->adr_at(i));
}
iterate_roots(it, is_relocating_pointers);
@ -592,6 +595,200 @@ void ArchiveBuilder::make_klasses_shareable() {
}
}
// Write detailed info to a mapfile to analyze contents of the archive.
// static dump:
// java -Xshare:dump -Xlog:cds+map=trace:file=cds.map:none:filesize=0
// dynamic dump:
// java -cp MyApp.jar -XX:ArchiveClassesAtExit=MyApp.jsa \
// -Xlog:cds+map=trace:file=cds.map:none:filesize=0 MyApp
//
// We need to do some address translation because the buffers used at dump time may be mapped to
// a different location at runtime. At dump time, the buffers may be at arbitrary locations
// picked by the OS. At runtime, we try to map at a fixed location (SharedBaseAddress). For
// consistency, we log everything using runtime addresses.
class ArchiveBuilder::CDSMapLogger : AllStatic {
static intx buffer_to_runtime_delta() {
// Translate the buffers used by the MC/RW/RO regions to their eventual locations
// at runtime.
return _buffer_to_target_delta + MetaspaceShared::final_delta();
}
// mc/rw/ro regions only
static void write_dump_region(const char* name, DumpRegion* region) {
address region_base = address(region->base());
address region_top = address(region->top());
write_region(name, region_base, region_top, region_base + buffer_to_runtime_delta());
}
#define _LOG_PREFIX PTR_FORMAT ": @@ %-17s %d"
static void write_klass(Klass* k, address runtime_dest, const char* type_name, int bytes, Thread* THREAD) {
ResourceMark rm(THREAD);
log_debug(cds, map)(_LOG_PREFIX " %s",
p2i(runtime_dest), type_name, bytes, k->external_name());
}
static void write_method(Method* m, address runtime_dest, const char* type_name, int bytes, Thread* THREAD) {
ResourceMark rm(THREAD);
log_debug(cds, map)(_LOG_PREFIX " %s",
p2i(runtime_dest), type_name, bytes, m->external_name());
}
// rw/ro regions only
static void write_objects(DumpRegion* region, const ArchiveBuilder::SourceObjList* src_objs) {
address last_obj_base = address(region->base());
address last_obj_end = address(region->base());
address region_end = address(region->end());
Thread* THREAD = Thread::current();
for (int i = 0; i < src_objs->objs()->length(); i++) {
SourceObjInfo* src_info = src_objs->at(i);
address src = src_info->orig_obj();
address dest = src_info->dumped_addr();
write_data(last_obj_base, dest, last_obj_base + buffer_to_runtime_delta());
address runtime_dest = dest + buffer_to_runtime_delta();
int bytes = src_info->size_in_bytes();
MetaspaceObj::Type type = src_info->msotype();
const char* type_name = MetaspaceObj::type_name(type);
switch (type) {
case MetaspaceObj::ClassType:
write_klass((Klass*)src, runtime_dest, type_name, bytes, THREAD);
break;
case MetaspaceObj::ConstantPoolType:
write_klass(((ConstantPool*)src)->pool_holder(),
runtime_dest, type_name, bytes, THREAD);
break;
case MetaspaceObj::ConstantPoolCacheType:
write_klass(((ConstantPoolCache*)src)->constant_pool()->pool_holder(),
runtime_dest, type_name, bytes, THREAD);
break;
case MetaspaceObj::MethodType:
write_method((Method*)src, runtime_dest, type_name, bytes, THREAD);
break;
case MetaspaceObj::ConstMethodType:
write_method(((ConstMethod*)src)->method(), runtime_dest, type_name, bytes, THREAD);
break;
case MetaspaceObj::SymbolType:
{
ResourceMark rm(THREAD);
Symbol* s = (Symbol*)src;
log_debug(cds, map)(_LOG_PREFIX " %s", p2i(runtime_dest), type_name, bytes,
s->as_quoted_ascii());
}
break;
default:
log_debug(cds, map)(_LOG_PREFIX, p2i(runtime_dest), type_name, bytes);
break;
}
last_obj_base = dest;
last_obj_end = dest + bytes;
}
write_data(last_obj_base, last_obj_end, last_obj_base + buffer_to_runtime_delta());
if (last_obj_end < region_end) {
log_debug(cds, map)(PTR_FORMAT ": @@ Misc data " SIZE_FORMAT " bytes",
p2i(last_obj_end + buffer_to_runtime_delta()),
size_t(region_end - last_obj_end));
write_data(last_obj_end, region_end, last_obj_end + buffer_to_runtime_delta());
}
}
#undef _LOG_PREFIX
// Write information about a region, whose address at dump time is [base .. top). At
// runtime, this region will be mapped to runtime_base. runtime_base is 0 if this
// region will be mapped at os-selected addresses (such as the bitmap region), or will
// be accessed with os::read (the header).
static void write_region(const char* name, address base, address top, address runtime_base) {
size_t size = top - base;
base = runtime_base;
top = runtime_base + size;
log_info(cds, map)("[%-18s " PTR_FORMAT " - " PTR_FORMAT " " SIZE_FORMAT_W(9) " bytes]",
name, p2i(base), p2i(top), size);
}
// open and closed archive regions
static void write_heap_region(const char* which, GrowableArray<MemRegion> *regions) {
for (int i = 0; i < regions->length(); i++) {
address start = address(regions->at(i).start());
address end = address(regions->at(i).end());
write_region(which, start, end, start);
write_data(start, end, start);
}
}
// Dump all the data [base...top). Pretend that the base address
// will be mapped to runtime_base at run-time.
static void write_data(address base, address top, address runtime_base) {
assert(top >= base, "must be");
LogStreamHandle(Trace, cds, map) lsh;
if (lsh.is_enabled()) {
os::print_hex_dump(&lsh, base, top, sizeof(address), 32, runtime_base);
}
}
static void write_header(FileMapInfo* mapinfo) {
LogStreamHandle(Info, cds, map) lsh;
if (lsh.is_enabled()) {
mapinfo->print(&lsh);
}
}
public:
static void write(ArchiveBuilder* builder, FileMapInfo* mapinfo,
GrowableArray<MemRegion> *closed_heap_regions,
GrowableArray<MemRegion> *open_heap_regions,
char* bitmap, size_t bitmap_size_in_bytes) {
log_info(cds, map)("%s CDS archive map for %s", DumpSharedSpaces ? "Static" : "Dynamic", mapinfo->full_path());
address header = address(mapinfo->header());
address header_end = header + mapinfo->header()->header_size();
write_region("header", header, header_end, 0);
write_header(mapinfo);
write_data(header, header_end, 0);
DumpRegion* mc_region = builder->_mc_region;
DumpRegion* rw_region = builder->_rw_region;
DumpRegion* ro_region = builder->_ro_region;
address mc = address(mc_region->base());
address mc_end = address(mc_region->end());
write_dump_region("mc region", mc_region);
write_data(mc, mc_end, mc + buffer_to_runtime_delta());
write_dump_region("rw region", rw_region);
write_objects(rw_region, &builder->_rw_src_objs);
write_dump_region("ro region", ro_region);
write_objects(ro_region, &builder->_ro_src_objs);
address bitmap_end = address(bitmap + bitmap_size_in_bytes);
write_region("bitmap", address(bitmap), bitmap_end, 0);
write_data(header, header_end, 0);
if (closed_heap_regions != NULL) {
write_heap_region("closed heap region", closed_heap_regions);
}
if (open_heap_regions != NULL) {
write_heap_region("open heap region", open_heap_regions);
}
log_info(cds, map)("[End of CDS archive map]");
}
};
void ArchiveBuilder::write_cds_map_to_log(FileMapInfo* mapinfo,
GrowableArray<MemRegion> *closed_heap_regions,
GrowableArray<MemRegion> *open_heap_regions,
char* bitmap, size_t bitmap_size_in_bytes) {
if (log_is_enabled(Info, cds, map)) {
CDSMapLogger::write(this, mapinfo, closed_heap_regions, open_heap_regions,
bitmap, bitmap_size_in_bytes);
}
}
void ArchiveBuilder::print_stats(int ro_all, int rw_all, int mc_all) {
_alloc_stats->print_stats(ro_all, rw_all, mc_all);
}

@ -34,9 +34,11 @@
#include "utilities/resourceHash.hpp"
class CHeapBitMap;
class Klass;
class Symbol;
class DumpAllocStats;
class FileMapInfo;
class Klass;
class MemRegion;
class Symbol;
class ArchiveBuilder : public StackObj {
public:
@ -68,11 +70,18 @@ private:
uintx _ptrmap_end; // The bit-offset of the end of this object (exclusive)
bool _read_only;
FollowMode _follow_mode;
int _size_in_bytes;
MetaspaceObj::Type _msotype;
address _dumped_addr; // Address this->obj(), as used by the dumped archive.
address _orig_obj; // The value of the original object (_ref->obj()) when this
// SourceObjInfo was created. Note that _ref->obj() may change
// later if _ref is relocated.
public:
SourceObjInfo(MetaspaceClosure::Ref* ref, bool read_only, FollowMode follow_mode) :
_ref(ref), _ptrmap_start(0), _ptrmap_end(0), _read_only(read_only), _follow_mode(follow_mode) {
_ref(ref), _ptrmap_start(0), _ptrmap_end(0), _read_only(read_only), _follow_mode(follow_mode),
_size_in_bytes(ref->size() * BytesPerWord), _msotype(ref->msotype()),
_orig_obj(ref->obj()) {
if (follow_mode == point_to_it) {
_dumped_addr = ref->obj();
} else {
@ -93,8 +102,10 @@ private:
uintx ptrmap_start() const { return _ptrmap_start; } // inclusive
uintx ptrmap_end() const { return _ptrmap_end; } // exclusive
bool read_only() const { return _read_only; }
int size_in_bytes() const { return _ref->size() * BytesPerWord; }
int size_in_bytes() const { return _size_in_bytes; }
address orig_obj() const { return _orig_obj; }
address dumped_addr() const { return _dumped_addr; }
MetaspaceObj::Type msotype() const { return _msotype; }
// convenience accessor
address obj() const { return ref()->obj(); }
@ -127,9 +138,12 @@ private:
}
};
class CDSMapLogger;
static const int INITIAL_TABLE_SIZE = 15889;
static const int MAX_TABLE_SIZE = 1000000;
DumpRegion* _mc_region;
DumpRegion* _rw_region;
DumpRegion* _ro_region;
@ -180,19 +194,12 @@ private:
bool is_excluded(Klass* k);
void clean_up_src_obj_table();
protected:
virtual void iterate_roots(MetaspaceClosure* it, bool is_relocating_pointers) = 0;
// Conservative estimate for number of bytes needed for:
size_t _estimated_metsapceobj_bytes; // all archived MetsapceObj's.
void set_dump_regions(DumpRegion* rw_region, DumpRegion* ro_region) {
assert(_rw_region == NULL && _ro_region == NULL, "do not change");
_rw_region = rw_region;
_ro_region = ro_region;
}
protected:
DumpRegion* _current_dump_space;
address _alloc_bottom;
@ -225,7 +232,7 @@ public:
}
public:
ArchiveBuilder(DumpRegion* rw_region, DumpRegion* ro_region);
ArchiveBuilder(DumpRegion* mc_region, DumpRegion* rw_region, DumpRegion* ro_region);
~ArchiveBuilder();
void gather_klasses_and_symbols();
@ -240,6 +247,11 @@ public:
void relocate_pointers();
void relocate_well_known_klasses();
void make_klasses_shareable();
void write_cds_map_to_log(FileMapInfo* mapinfo,
GrowableArray<MemRegion> *closed_heap_regions,
GrowableArray<MemRegion> *open_heap_regions,
char* bitmap, size_t bitmap_size_in_bytes);
address get_dumped_addr(address src_obj) const;
// All klasses and symbols that will be copied into the archive

@ -123,7 +123,9 @@ public:
}
public:
DynamicArchiveBuilder() : ArchiveBuilder(NULL, NULL) {
DynamicArchiveBuilder() : ArchiveBuilder(MetaspaceShared::misc_code_dump_space(),
MetaspaceShared::read_write_dump_space(),
MetaspaceShared::read_only_dump_space()) {
_estimated_hashtable_bytes = 0;
_estimated_trampoline_bytes = 0;
@ -177,7 +179,6 @@ public:
// rw space starts ...
address reserved_bottom = reserve_space_and_init_buffer_to_target_delta();
set_dump_regions(MetaspaceShared::read_write_dump_space(), MetaspaceShared::read_only_dump_space());
init_header(reserved_bottom);
CHeapBitMap ptrmap;
@ -566,12 +567,17 @@ void DynamicArchiveBuilder::write_archive(char* serialized_data) {
// Now write the archived data including the file offsets.
const char* archive_name = Arguments::GetSharedDynamicArchivePath();
dynamic_info->open_for_write(archive_name);
MetaspaceShared::write_core_archive_regions(dynamic_info, NULL, NULL);
size_t bitmap_size_in_bytes;
char* bitmap = MetaspaceShared::write_core_archive_regions(dynamic_info, NULL, NULL, bitmap_size_in_bytes);
dynamic_info->set_final_requested_base((char*)MetaspaceShared::requested_base_address());
dynamic_info->set_header_crc(dynamic_info->compute_header_crc());
dynamic_info->write_header();
dynamic_info->close();
write_cds_map_to_log(dynamic_info, NULL, NULL,
bitmap, bitmap_size_in_bytes);
FREE_C_HEAP_ARRAY(char, bitmap);
address base = to_target(_alloc_bottom);
address top = address(current_dump_space()->top()) + _buffer_to_target_delta;
size_t file_size = pointer_delta(top, base, sizeof(char));

@ -60,6 +60,7 @@
#include "utilities/bitMap.inline.hpp"
#include "utilities/classpathStream.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/ostream.hpp"
#if INCLUDE_G1GC
#include "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/heapRegion.hpp"
@ -248,6 +249,56 @@ void FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
}
}
void FileMapHeader::print(outputStream* st) {
ResourceMark rm;
st->print_cr("- magic: 0x%08x", _magic);
st->print_cr("- crc: 0x%08x", _crc);
st->print_cr("- version: %d", _version);
for (int i = 0; i < NUM_CDS_REGIONS; i++) {
FileMapRegion* si = space_at(i);
si->print(st, i);
}
st->print_cr("============ end regions ======== ");
st->print_cr("- header_size: " SIZE_FORMAT, _header_size);
st->print_cr("- alignment: " SIZE_FORMAT, _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));
st->print_cr("- narrow_oop_shift %d", _narrow_oop_shift);
st->print_cr("- compact_strings: %d", _compact_strings);
st->print_cr("- max_heap_size: " UINTX_FORMAT, _max_heap_size);
st->print_cr("- narrow_oop_mode: %d", _narrow_oop_mode);
st->print_cr("- narrow_klass_shift: %d", _narrow_klass_shift);
st->print_cr("- compressed_oops: %d", _compressed_oops);
st->print_cr("- compressed_class_ptrs: %d", _compressed_class_ptrs);
st->print_cr("- cloned_vtables_offset: " SIZE_FORMAT_HEX, _cloned_vtables_offset);
st->print_cr("- serialized_data_offset: " SIZE_FORMAT_HEX, _serialized_data_offset);
st->print_cr("- i2i_entry_code_buffers_offset: " SIZE_FORMAT_HEX, _i2i_entry_code_buffers_offset);
st->print_cr("- i2i_entry_code_buffers_size: " SIZE_FORMAT, _i2i_entry_code_buffers_size);
st->print_cr("- heap_end: " INTPTR_FORMAT, p2i(_heap_end));
st->print_cr("- base_archive_is_default: %d", _base_archive_is_default);
st->print_cr("- jvm_ident: %s", _jvm_ident);
st->print_cr("- base_archive_name_size: " SIZE_FORMAT, _base_archive_name_size);
st->print_cr("- shared_path_table_offset: " SIZE_FORMAT_HEX, _shared_path_table_offset);
st->print_cr("- shared_path_table_size: %d", _shared_path_table_size);
st->print_cr("- app_class_paths_start_index: %d", _app_class_paths_start_index);
st->print_cr("- app_module_paths_start_index: %d", _app_module_paths_start_index);
st->print_cr("- num_module_paths: %d", _num_module_paths);
st->print_cr("- max_used_path_index: %d", _max_used_path_index);
st->print_cr("- verify_local: %d", _verify_local);
st->print_cr("- verify_remote: %d", _verify_remote);
st->print_cr("- has_platform_or_app_classes: %d", _has_platform_or_app_classes);
st->print_cr("- requested_base_address: " INTPTR_FORMAT, p2i(_requested_base_address));
st->print_cr("- mapped_base_address: " INTPTR_FORMAT, p2i(_mapped_base_address));
st->print_cr("- allow_archiving_with_java_agent:%d", _allow_archiving_with_java_agent);
st->print_cr("- use_optimized_module_handling: %d", _use_optimized_module_handling);
st->print_cr("- use_full_module_graph %d", _use_full_module_graph);
st->print_cr("- ptrmap_size_in_bits: " SIZE_FORMAT, _ptrmap_size_in_bits);
}
void SharedClassPathEntry::init_as_non_existent(const char* path, TRAPS) {
_type = non_existent_entry;
set_name(path, THREAD);
@ -1229,9 +1280,32 @@ void FileMapRegion::init(int region_index, char* base, size_t size, bool read_on
_mapped_base = NULL;
}
static const char* region_names[] = {
"mc", "rw", "ro", "bm", "ca0", "ca1", "oa0", "oa1"
};
static const char* region_name(int region_index) {
static const char* names[] = {
"mc", "rw", "ro", "bm", "ca0", "ca1", "oa0", "oa1"
};
const int num_regions = sizeof(names)/sizeof(names[0]);
assert(0 <= region_index && region_index < num_regions, "sanity");
return names[region_index];
}
void FileMapRegion::print(outputStream* st, int region_index) {
st->print_cr("============ region ============= %d \"%s\"", region_index, region_name(region_index));
st->print_cr("- crc: 0x%08x", _crc);
st->print_cr("- read_only: %d", _read_only);
st->print_cr("- allow_exec: %d", _allow_exec);
st->print_cr("- is_heap_region: %d", _is_heap_region);
st->print_cr("- is_bitmap_region: %d", _is_bitmap_region);
st->print_cr("- mapped_from_file: %d", _mapped_from_file);
st->print_cr("- file_offset: " SIZE_FORMAT_HEX, _file_offset);
st->print_cr("- mapping_offset: " SIZE_FORMAT_HEX, _mapping_offset);
st->print_cr("- used: " SIZE_FORMAT, _used);
st->print_cr("- oopmap_offset: " SIZE_FORMAT_HEX, _oopmap_offset);
st->print_cr("- oopmap_size_in_bits: " SIZE_FORMAT, _oopmap_size_in_bits);
st->print_cr("- mapped_base: " INTPTR_FORMAT, p2i(_mapped_base));
}
void FileMapInfo::write_region(int region, char* base, size_t size,
bool read_only, bool allow_exec) {
@ -1240,9 +1314,6 @@ void FileMapInfo::write_region(int region, char* base, size_t size,
FileMapRegion* si = space_at(region);
char* target_base;
const int num_regions = sizeof(region_names)/sizeof(region_names[0]);
assert(0 <= region && region < num_regions, "sanity");
if (region == MetaspaceShared::bm) {
target_base = NULL; // always NULL for bm region.
} else {
@ -1261,7 +1332,7 @@ void FileMapInfo::write_region(int region, char* base, size_t size,
log_debug(cds)("Shared file region (%-3s) %d: " SIZE_FORMAT_W(8)
" bytes, addr " INTPTR_FORMAT " file offset " SIZE_FORMAT_HEX_W(08)
" crc 0x%08x",
region_names[region], region, size, p2i(requested_base), _file_offset, crc);
region_name(region), region, size, p2i(requested_base), _file_offset, crc);
}
si->init(region, target_base, size, read_only, allow_exec, crc);
@ -1278,28 +1349,28 @@ size_t FileMapInfo::set_oopmaps_offset(GrowableArray<ArchiveHeapOopmapInfo>* oop
return curr_size;
}
size_t FileMapInfo::write_oopmaps(GrowableArray<ArchiveHeapOopmapInfo>* oopmaps, size_t curr_offset, uintptr_t* buffer) {
size_t FileMapInfo::write_oopmaps(GrowableArray<ArchiveHeapOopmapInfo>* oopmaps, size_t curr_offset, char* buffer) {
for (int i = 0; i < oopmaps->length(); i++) {
memcpy(((char*)buffer) + curr_offset, oopmaps->at(i)._oopmap, oopmaps->at(i)._oopmap_size_in_bytes);
memcpy(buffer + curr_offset, oopmaps->at(i)._oopmap, oopmaps->at(i)._oopmap_size_in_bytes);
curr_offset += oopmaps->at(i)._oopmap_size_in_bytes;
}
return curr_offset;
}
void FileMapInfo::write_bitmap_region(const CHeapBitMap* ptrmap,
GrowableArray<ArchiveHeapOopmapInfo>* closed_oopmaps,
GrowableArray<ArchiveHeapOopmapInfo>* open_oopmaps) {
ResourceMark rm;
char* FileMapInfo::write_bitmap_region(const CHeapBitMap* ptrmap,
GrowableArray<ArchiveHeapOopmapInfo>* closed_oopmaps,
GrowableArray<ArchiveHeapOopmapInfo>* open_oopmaps,
size_t &size_in_bytes) {
size_t size_in_bits = ptrmap->size();
size_t size_in_bytes = ptrmap->size_in_bytes();
size_in_bytes = ptrmap->size_in_bytes();
if (closed_oopmaps != NULL && open_oopmaps != NULL) {
size_in_bytes = set_oopmaps_offset(closed_oopmaps, size_in_bytes);
size_in_bytes = set_oopmaps_offset(open_oopmaps, size_in_bytes);
}
uintptr_t* buffer = (uintptr_t*)NEW_RESOURCE_ARRAY(char, size_in_bytes);
ptrmap->write_to(buffer, ptrmap->size_in_bytes());
char* buffer = NEW_C_HEAP_ARRAY(char, size_in_bytes, mtClassShared);
ptrmap->write_to((BitMap::bm_word_t*)buffer, ptrmap->size_in_bytes());
header()->set_ptrmap_size_in_bits(size_in_bits);
if (closed_oopmaps != NULL && open_oopmaps != NULL) {
@ -1308,6 +1379,7 @@ void FileMapInfo::write_bitmap_region(const CHeapBitMap* ptrmap,
}
write_region(MetaspaceShared::bm, (char*)buffer, size_in_bytes, /*read_only=*/true, /*allow_exec=*/false);
return buffer;
}
// Write out the given archive heap memory regions. GC code combines multiple

@ -44,6 +44,7 @@
static const int JVM_IDENT_MAX = 256;
class CHeapBitMap;
class outputStream;
class SharedClassPathEntry {
enum {
@ -175,6 +176,8 @@ public:
_oopmap_offset = oopmap_offset;
_oopmap_size_in_bits = size_in_bits;
}
void print(outputStream* st, int region_index);
};
class FileMapHeader: private CDSFileMapHeaderBase {
@ -325,12 +328,15 @@ public:
static bool is_valid_region(int region) {
return (0 <= region && region < NUM_CDS_REGIONS);
}
void print(outputStream* st);
};
class FileMapInfo : public CHeapObj<mtInternal> {
private:
friend class ManifestStream;
friend class VMStructs;
friend class ArchiveBuilder;
friend class CDSOffsets;
friend class FileMapHeader;
@ -457,9 +463,10 @@ public:
void write_header();
void write_region(int region, char* base, size_t size,
bool read_only, bool allow_exec);
void write_bitmap_region(const CHeapBitMap* ptrmap,
char* write_bitmap_region(const CHeapBitMap* ptrmap,
GrowableArray<ArchiveHeapOopmapInfo>* closed_oopmaps,
GrowableArray<ArchiveHeapOopmapInfo>* open_oopmaps);
GrowableArray<ArchiveHeapOopmapInfo>* open_oopmaps,
size_t &size_in_bytes);
size_t write_archive_heap_regions(GrowableArray<MemRegion> *heap_mem,
GrowableArray<ArchiveHeapOopmapInfo> *oopmaps,
int first_region_id, int max_num_regions);
@ -551,6 +558,10 @@ public:
return header()->space_at(i);
}
void print(outputStream* st) {
header()->print(st);
}
private:
void seek_to_position(size_t pos);
char* skip_first_path_entry(const char* path) NOT_CDS_RETURN_(NULL);
@ -571,7 +582,7 @@ public:
bool read_region(int i, char* base, size_t size);
bool relocate_pointers(intx addr_delta);
static size_t set_oopmaps_offset(GrowableArray<ArchiveHeapOopmapInfo> *oopmaps, size_t curr_size);
static size_t write_oopmaps(GrowableArray<ArchiveHeapOopmapInfo> *oopmaps, size_t curr_offset, uintptr_t* buffer);
static size_t write_oopmaps(GrowableArray<ArchiveHeapOopmapInfo> *oopmaps, size_t curr_offset, char* buffer);
// The starting address of spc, as calculated with CompressedOop::decode_non_null()
address start_address_as_decoded_with_current_oop_encoding_mode(FileMapRegion* spc) {

@ -608,8 +608,8 @@ public:
class StaticArchiveBuilder : public ArchiveBuilder {
public:
StaticArchiveBuilder(DumpRegion* rw_region, DumpRegion* ro_region)
: ArchiveBuilder(rw_region, ro_region) {
StaticArchiveBuilder(DumpRegion* mc_region, DumpRegion* rw_region, DumpRegion* ro_region)
: ArchiveBuilder(mc_region, rw_region, ro_region) {
_alloc_bottom = address(SharedBaseAddress);
_buffer_to_target_delta = 0;
}
@ -724,7 +724,7 @@ void VM_PopulateDumpSharedSpace::doit() {
// that so we don't have to walk the SystemDictionary again.
SystemDictionaryShared::check_excluded_classes();
StaticArchiveBuilder builder(&_rw_region, &_ro_region);
StaticArchiveBuilder builder(&_mc_region, &_rw_region, &_ro_region);
builder.set_current_dump_space(&_mc_region);
builder.gather_klasses_and_symbols();
_global_klass_objects = builder.klasses();
@ -796,7 +796,10 @@ void VM_PopulateDumpSharedSpace::doit() {
mapinfo->set_i2i_entry_code_buffers(MetaspaceShared::i2i_entry_code_buffers(),
MetaspaceShared::i2i_entry_code_buffers_size());
mapinfo->open_for_write();
MetaspaceShared::write_core_archive_regions(mapinfo, _closed_archive_heap_oopmaps, _open_archive_heap_oopmaps);
size_t bitmap_size_in_bytes;
char* bitmap = MetaspaceShared::write_core_archive_regions(mapinfo, _closed_archive_heap_oopmaps,
_open_archive_heap_oopmaps,
bitmap_size_in_bytes);
_total_closed_archive_region_size = mapinfo->write_archive_heap_regions(
_closed_archive_heap_regions,
_closed_archive_heap_oopmaps,
@ -814,6 +817,10 @@ void VM_PopulateDumpSharedSpace::doit() {
print_region_stats(mapinfo);
mapinfo->close();
builder.write_cds_map_to_log(mapinfo, _closed_archive_heap_regions, _open_archive_heap_regions,
bitmap, bitmap_size_in_bytes);
FREE_C_HEAP_ARRAY(char, bitmap);
if (log_is_enabled(Info, cds)) {
builder.print_stats(int(_ro_region.used()), int(_rw_region.used()), int(_mc_region.used()));
}
@ -878,9 +885,10 @@ void VM_PopulateDumpSharedSpace::print_heap_region_stats(GrowableArray<MemRegion
}
}
void MetaspaceShared::write_core_archive_regions(FileMapInfo* mapinfo,
GrowableArray<ArchiveHeapOopmapInfo>* closed_oopmaps,
GrowableArray<ArchiveHeapOopmapInfo>* open_oopmaps) {
char* MetaspaceShared::write_core_archive_regions(FileMapInfo* mapinfo,
GrowableArray<ArchiveHeapOopmapInfo>* closed_oopmaps,
GrowableArray<ArchiveHeapOopmapInfo>* open_oopmaps,
size_t& bitmap_size_in_bytes) {
// Make sure NUM_CDS_REGIONS (exported in cds.h) agrees with
// MetaspaceShared::n_regions (internal to hotspot).
assert(NUM_CDS_REGIONS == MetaspaceShared::n_regions, "sanity");
@ -890,7 +898,9 @@ void MetaspaceShared::write_core_archive_regions(FileMapInfo* mapinfo,
write_region(mapinfo, mc, &_mc_region, /*read_only=*/false,/*allow_exec=*/true);
write_region(mapinfo, rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false);
write_region(mapinfo, ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false);
mapinfo->write_bitmap_region(ArchivePtrMarker::ptrmap(), closed_oopmaps, open_oopmaps);
return mapinfo->write_bitmap_region(ArchivePtrMarker::ptrmap(), closed_oopmaps, open_oopmaps,
bitmap_size_in_bytes);
}
void MetaspaceShared::write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, bool read_only, bool allow_exec) {

@ -262,9 +262,12 @@ class MetaspaceShared : AllStatic {
return is_windows;
}
static void write_core_archive_regions(FileMapInfo* mapinfo,
GrowableArray<ArchiveHeapOopmapInfo>* closed_oopmaps,
GrowableArray<ArchiveHeapOopmapInfo>* open_oopmaps);
// Returns the bitmap region which is allocated from C heap.
// Caller must free it with FREE_C_HEAP_ARRAY()
static char* write_core_archive_regions(FileMapInfo* mapinfo,
GrowableArray<ArchiveHeapOopmapInfo>* closed_oopmaps,
GrowableArray<ArchiveHeapOopmapInfo>* open_oopmaps,
size_t& bitmap_size_in_bytes);
// Can we skip some expensive operations related to modules?
static bool use_optimized_module_handling() { return NOT_CDS(false) CDS_ONLY(_use_optimized_module_handling); }

@ -886,23 +886,22 @@ void os::abort(bool dump_core) {
//---------------------------------------------------------------------------
// Helper functions for fatal error handler
void os::print_hex_dump(outputStream* st, address start, address end, int unitsize) {
void os::print_hex_dump(outputStream* st, address start, address end, int unitsize,
int bytes_per_line, address logical_start) {
assert(unitsize == 1 || unitsize == 2 || unitsize == 4 || unitsize == 8, "just checking");
start = align_down(start, unitsize);
logical_start = align_down(logical_start, unitsize);
bytes_per_line = align_up(bytes_per_line, 8);
int cols = 0;
int cols_per_line = 0;
switch (unitsize) {
case 1: cols_per_line = 16; break;
case 2: cols_per_line = 8; break;
case 4: cols_per_line = 4; break;
case 8: cols_per_line = 2; break;
default: return;
}
int cols_per_line = bytes_per_line / unitsize;
address p = start;
st->print(PTR_FORMAT ": ", p2i(start));
address logical_p = logical_start;
// Print out the addresses as if we were starting from logical_start.
st->print(PTR_FORMAT ": ", p2i(logical_p));
while (p < end) {
if (is_readable_pointer(p)) {
switch (unitsize) {
@ -915,11 +914,12 @@ void os::print_hex_dump(outputStream* st, address start, address end, int unitsi
st->print("%*.*s", 2*unitsize, 2*unitsize, "????????????????");
}
p += unitsize;
logical_p += unitsize;
cols++;
if (cols >= cols_per_line && p < end) {
cols = 0;
st->cr();
st->print(PTR_FORMAT ": ", p2i(p));
st->print(PTR_FORMAT ": ", p2i(logical_p));
} else {
st->print(" ");
}

@ -686,7 +686,11 @@ class os: AllStatic {
// return current frame. pc() and sp() are set to NULL on failure.
static frame current_frame();
static void print_hex_dump(outputStream* st, address start, address end, int unitsize);
static void print_hex_dump(outputStream* st, address start, address end, int unitsize,
int bytes_per_line, address logical_start);
static void print_hex_dump(outputStream* st, address start, address end, int unitsize) {
print_hex_dump(st, start, end, unitsize, /*bytes_per_line=*/16, /*logical_start=*/start);
}
// returns a string to describe the exception/signal;
// returns NULL if exception_code is not an OS exception/signal.