8253909: Implement detailed map file for CDS
Reviewed-by: stuefe, ccheung
This commit is contained in:
parent
7733a0e76b
commit
d1e94eebdd
src/hotspot/share
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user