1.1 --- a/src/share/vm/memory/metaspace.cpp Tue May 28 11:35:57 2013 -0700 1.2 +++ b/src/share/vm/memory/metaspace.cpp Tue May 28 16:36:19 2013 -0700 1.3 @@ -713,6 +713,23 @@ 1.4 #ifdef ASSERT 1.5 void verify_allocated_blocks_words(); 1.6 #endif 1.7 + 1.8 + size_t get_raw_word_size(size_t word_size) { 1.9 + // If only the dictionary is going to be used (i.e., no 1.10 + // indexed free list), then there is a minimum size requirement. 1.11 + // MinChunkSize is a placeholder for the real minimum size JJJ 1.12 + size_t byte_size = word_size * BytesPerWord; 1.13 + 1.14 + size_t byte_size_with_overhead = byte_size + Metablock::overhead(); 1.15 + 1.16 + size_t raw_bytes_size = MAX2(byte_size_with_overhead, 1.17 + Metablock::min_block_byte_size()); 1.18 + raw_bytes_size = ARENA_ALIGN(raw_bytes_size); 1.19 + size_t raw_word_size = raw_bytes_size / BytesPerWord; 1.20 + assert(raw_word_size * BytesPerWord == raw_bytes_size, "Size problem"); 1.21 + 1.22 + return raw_word_size; 1.23 + } 1.24 }; 1.25 1.26 uint const SpaceManager::_small_chunk_limit = 4; 1.27 @@ -2320,19 +2337,7 @@ 1.28 MetaWord* SpaceManager::allocate(size_t word_size) { 1.29 MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); 1.30 1.31 - // If only the dictionary is going to be used (i.e., no 1.32 - // indexed free list), then there is a minimum size requirement. 1.33 - // MinChunkSize is a placeholder for the real minimum size JJJ 1.34 - size_t byte_size = word_size * BytesPerWord; 1.35 - 1.36 - size_t byte_size_with_overhead = byte_size + Metablock::overhead(); 1.37 - 1.38 - size_t raw_bytes_size = MAX2(byte_size_with_overhead, 1.39 - Metablock::min_block_byte_size()); 1.40 - raw_bytes_size = ARENA_ALIGN(raw_bytes_size); 1.41 - size_t raw_word_size = raw_bytes_size / BytesPerWord; 1.42 - assert(raw_word_size * BytesPerWord == raw_bytes_size, "Size problem"); 1.43 - 1.44 + size_t raw_word_size = get_raw_word_size(word_size); 1.45 BlockFreelist* fl = block_freelists(); 1.46 MetaWord* p = NULL; 1.47 // Allocation from the dictionary is expensive in the sense that 1.48 @@ -2896,6 +2901,9 @@ 1.49 if (class_chunk != NULL) { 1.50 class_vsm()->add_chunk(class_chunk, true); 1.51 } 1.52 + 1.53 + _alloc_record_head = NULL; 1.54 + _alloc_record_tail = NULL; 1.55 } 1.56 1.57 size_t Metaspace::align_word_size_up(size_t word_size) { 1.58 @@ -3000,12 +3008,14 @@ 1.59 } 1.60 1.61 Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, 1.62 - bool read_only, MetadataType mdtype, TRAPS) { 1.63 + bool read_only, MetaspaceObj::Type type, TRAPS) { 1.64 if (HAS_PENDING_EXCEPTION) { 1.65 assert(false, "Should not allocate with exception pending"); 1.66 return NULL; // caller does a CHECK_NULL too 1.67 } 1.68 1.69 + MetadataType mdtype = (type == MetaspaceObj::ClassType) ? ClassType : NonClassType; 1.70 + 1.71 // SSS: Should we align the allocations and make sure the sizes are aligned. 1.72 MetaWord* result = NULL; 1.73 1.74 @@ -3015,13 +3025,13 @@ 1.75 // with the SymbolTable_lock. Dumping is single threaded for now. We'll have 1.76 // to revisit this for application class data sharing. 1.77 if (DumpSharedSpaces) { 1.78 - if (read_only) { 1.79 - result = loader_data->ro_metaspace()->allocate(word_size, NonClassType); 1.80 - } else { 1.81 - result = loader_data->rw_metaspace()->allocate(word_size, NonClassType); 1.82 - } 1.83 + assert(type > MetaspaceObj::UnknownType && type < MetaspaceObj::_number_of_types, "sanity"); 1.84 + Metaspace* space = read_only ? loader_data->ro_metaspace() : loader_data->rw_metaspace(); 1.85 + result = space->allocate(word_size, NonClassType); 1.86 if (result == NULL) { 1.87 report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite); 1.88 + } else { 1.89 + space->record_allocation(result, type, space->vsm()->get_raw_word_size(word_size)); 1.90 } 1.91 return Metablock::initialize(result, word_size); 1.92 } 1.93 @@ -3056,6 +3066,38 @@ 1.94 return Metablock::initialize(result, word_size); 1.95 } 1.96 1.97 +void Metaspace::record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size) { 1.98 + assert(DumpSharedSpaces, "sanity"); 1.99 + 1.100 + AllocRecord *rec = new AllocRecord((address)ptr, type, (int)word_size * HeapWordSize); 1.101 + if (_alloc_record_head == NULL) { 1.102 + _alloc_record_head = _alloc_record_tail = rec; 1.103 + } else { 1.104 + _alloc_record_tail->_next = rec; 1.105 + _alloc_record_tail = rec; 1.106 + } 1.107 +} 1.108 + 1.109 +void Metaspace::iterate(Metaspace::AllocRecordClosure *closure) { 1.110 + assert(DumpSharedSpaces, "unimplemented for !DumpSharedSpaces"); 1.111 + 1.112 + address last_addr = (address)bottom(); 1.113 + 1.114 + for (AllocRecord *rec = _alloc_record_head; rec; rec = rec->_next) { 1.115 + address ptr = rec->_ptr; 1.116 + if (last_addr < ptr) { 1.117 + closure->doit(last_addr, MetaspaceObj::UnknownType, ptr - last_addr); 1.118 + } 1.119 + closure->doit(ptr, rec->_type, rec->_byte_size); 1.120 + last_addr = ptr + rec->_byte_size; 1.121 + } 1.122 + 1.123 + address top = ((address)bottom()) + used_bytes_slow(Metaspace::NonClassType); 1.124 + if (last_addr < top) { 1.125 + closure->doit(last_addr, MetaspaceObj::UnknownType, top - last_addr); 1.126 + } 1.127 +} 1.128 + 1.129 void Metaspace::purge() { 1.130 MutexLockerEx cl(SpaceManager::expand_lock(), 1.131 Mutex::_no_safepoint_check_flag);