8014912: Restore PrintSharedSpaces functionality after NPG

Added dumping of object sizes in CDS archive, sorted by MetaspaceObj::Type

Reviewed-by: coleenp, acorn
This commit is contained in:
Ioi Lam 2013-05-28 16:36:19 -07:00
parent f52e6781ee
commit 9dc36eb923
15 changed files with 301 additions and 36 deletions

View file

@ -713,6 +713,23 @@ class SpaceManager : public CHeapObj<mtClass> {
#ifdef ASSERT
void verify_allocated_blocks_words();
#endif
size_t get_raw_word_size(size_t word_size) {
// If only the dictionary is going to be used (i.e., no
// indexed free list), then there is a minimum size requirement.
// MinChunkSize is a placeholder for the real minimum size JJJ
size_t byte_size = word_size * BytesPerWord;
size_t byte_size_with_overhead = byte_size + Metablock::overhead();
size_t raw_bytes_size = MAX2(byte_size_with_overhead,
Metablock::min_block_byte_size());
raw_bytes_size = ARENA_ALIGN(raw_bytes_size);
size_t raw_word_size = raw_bytes_size / BytesPerWord;
assert(raw_word_size * BytesPerWord == raw_bytes_size, "Size problem");
return raw_word_size;
}
};
uint const SpaceManager::_small_chunk_limit = 4;
@ -2320,19 +2337,7 @@ Metachunk* SpaceManager::get_new_chunk(size_t word_size,
MetaWord* SpaceManager::allocate(size_t word_size) {
MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag);
// If only the dictionary is going to be used (i.e., no
// indexed free list), then there is a minimum size requirement.
// MinChunkSize is a placeholder for the real minimum size JJJ
size_t byte_size = word_size * BytesPerWord;
size_t byte_size_with_overhead = byte_size + Metablock::overhead();
size_t raw_bytes_size = MAX2(byte_size_with_overhead,
Metablock::min_block_byte_size());
raw_bytes_size = ARENA_ALIGN(raw_bytes_size);
size_t raw_word_size = raw_bytes_size / BytesPerWord;
assert(raw_word_size * BytesPerWord == raw_bytes_size, "Size problem");
size_t raw_word_size = get_raw_word_size(word_size);
BlockFreelist* fl = block_freelists();
MetaWord* p = NULL;
// Allocation from the dictionary is expensive in the sense that
@ -2896,6 +2901,9 @@ void Metaspace::initialize(Mutex* lock,
if (class_chunk != NULL) {
class_vsm()->add_chunk(class_chunk, true);
}
_alloc_record_head = NULL;
_alloc_record_tail = NULL;
}
size_t Metaspace::align_word_size_up(size_t word_size) {
@ -3000,12 +3008,14 @@ void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) {
}
Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
bool read_only, MetadataType mdtype, TRAPS) {
bool read_only, MetaspaceObj::Type type, TRAPS) {
if (HAS_PENDING_EXCEPTION) {
assert(false, "Should not allocate with exception pending");
return NULL; // caller does a CHECK_NULL too
}
MetadataType mdtype = (type == MetaspaceObj::ClassType) ? ClassType : NonClassType;
// SSS: Should we align the allocations and make sure the sizes are aligned.
MetaWord* result = NULL;
@ -3015,13 +3025,13 @@ Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
// with the SymbolTable_lock. Dumping is single threaded for now. We'll have
// to revisit this for application class data sharing.
if (DumpSharedSpaces) {
if (read_only) {
result = loader_data->ro_metaspace()->allocate(word_size, NonClassType);
} else {
result = loader_data->rw_metaspace()->allocate(word_size, NonClassType);
}
assert(type > MetaspaceObj::UnknownType && type < MetaspaceObj::_number_of_types, "sanity");
Metaspace* space = read_only ? loader_data->ro_metaspace() : loader_data->rw_metaspace();
result = space->allocate(word_size, NonClassType);
if (result == NULL) {
report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite);
} else {
space->record_allocation(result, type, space->vsm()->get_raw_word_size(word_size));
}
return Metablock::initialize(result, word_size);
}
@ -3056,6 +3066,38 @@ Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
return Metablock::initialize(result, word_size);
}
void Metaspace::record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size) {
assert(DumpSharedSpaces, "sanity");
AllocRecord *rec = new AllocRecord((address)ptr, type, (int)word_size * HeapWordSize);
if (_alloc_record_head == NULL) {
_alloc_record_head = _alloc_record_tail = rec;
} else {
_alloc_record_tail->_next = rec;
_alloc_record_tail = rec;
}
}
void Metaspace::iterate(Metaspace::AllocRecordClosure *closure) {
assert(DumpSharedSpaces, "unimplemented for !DumpSharedSpaces");
address last_addr = (address)bottom();
for (AllocRecord *rec = _alloc_record_head; rec; rec = rec->_next) {
address ptr = rec->_ptr;
if (last_addr < ptr) {
closure->doit(last_addr, MetaspaceObj::UnknownType, ptr - last_addr);
}
closure->doit(ptr, rec->_type, rec->_byte_size);
last_addr = ptr + rec->_byte_size;
}
address top = ((address)bottom()) + used_bytes_slow(Metaspace::NonClassType);
if (last_addr < top) {
closure->doit(last_addr, MetaspaceObj::UnknownType, top - last_addr);
}
}
void Metaspace::purge() {
MutexLockerEx cl(SpaceManager::expand_lock(),
Mutex::_no_safepoint_check_flag);