297 // the chunk manager (the freelist if non-humongous, the dictionary if |
297 // the chunk manager (the freelist if non-humongous, the dictionary if |
298 // humongous). |
298 // humongous). |
299 void remove_chunk(Metachunk* chunk); |
299 void remove_chunk(Metachunk* chunk); |
300 |
300 |
301 // Return a single chunk of type index to the ChunkManager. |
301 // Return a single chunk of type index to the ChunkManager. |
302 void return_single_chunk(ChunkIndex index, Metachunk* chunk); |
302 void return_single_chunk(Metachunk* chunk); |
303 |
303 |
304 // Add the simple linked list of chunks to the freelist of chunks |
304 // Add the simple linked list of chunks to the freelist of chunks |
305 // of type index. |
305 // of type index. |
306 void return_chunk_list(ChunkIndex index, Metachunk* chunk); |
306 void return_chunk_list(Metachunk* chunks); |
307 |
307 |
308 // Total of the space in the free chunks list |
308 // Total of the space in the free chunks list |
309 size_t free_chunks_total_words(); |
309 size_t free_chunks_total_words(); |
310 size_t free_chunks_total_bytes(); |
310 size_t free_chunks_total_bytes(); |
311 |
311 |
1279 const Metaspace::MetaspaceType _space_type; |
1279 const Metaspace::MetaspaceType _space_type; |
1280 |
1280 |
1281 // List of chunks in use by this SpaceManager. Allocations |
1281 // List of chunks in use by this SpaceManager. Allocations |
1282 // are done from the current chunk. The list is used for deallocating |
1282 // are done from the current chunk. The list is used for deallocating |
1283 // chunks when the SpaceManager is freed. |
1283 // chunks when the SpaceManager is freed. |
1284 Metachunk* _chunks_in_use[NumberOfInUseLists]; |
1284 Metachunk* _chunk_list; |
1285 Metachunk* _current_chunk; |
1285 Metachunk* _current_chunk; |
1286 |
1286 |
1287 // Maximum number of small chunks to allocate to a SpaceManager |
1287 // Maximum number of small chunks to allocate to a SpaceManager |
1288 static uint const _small_chunk_limit; |
1288 static uint const _small_chunk_limit; |
1289 |
1289 |
1296 // Note: capacity = used + free + waste + overhead. We do not keep running counters for |
1296 // Note: capacity = used + free + waste + overhead. We do not keep running counters for |
1297 // free and waste. Their sum can be deduced from the three other values. |
1297 // free and waste. Their sum can be deduced from the three other values. |
1298 size_t _overhead_words; |
1298 size_t _overhead_words; |
1299 size_t _capacity_words; |
1299 size_t _capacity_words; |
1300 size_t _used_words; |
1300 size_t _used_words; |
|
1301 uintx _num_chunks_by_type[NumberOfInUseLists]; |
1301 |
1302 |
1302 // Free lists of blocks are per SpaceManager since they |
1303 // Free lists of blocks are per SpaceManager since they |
1303 // are assumed to be in chunks in use by the SpaceManager |
1304 // are assumed to be in chunks in use by the SpaceManager |
1304 // and all chunks in use by a SpaceManager are freed when |
1305 // and all chunks in use by a SpaceManager are freed when |
1305 // the class loader using the SpaceManager is collected. |
1306 // the class loader using the SpaceManager is collected. |
1306 BlockFreelist* _block_freelists; |
1307 BlockFreelist* _block_freelists; |
1307 |
1308 |
1308 private: |
1309 private: |
1309 // Accessors |
1310 // Accessors |
1310 Metachunk* chunks_in_use(ChunkIndex index) const { return _chunks_in_use[index]; } |
1311 Metachunk* chunk_list() const { return _chunk_list; } |
1311 void set_chunks_in_use(ChunkIndex index, Metachunk* v) { |
|
1312 _chunks_in_use[index] = v; |
|
1313 } |
|
1314 |
1312 |
1315 BlockFreelist* block_freelists() const { return _block_freelists; } |
1313 BlockFreelist* block_freelists() const { return _block_freelists; } |
1316 |
1314 |
1317 Metaspace::MetadataType mdtype() { return _mdtype; } |
1315 Metaspace::MetadataType mdtype() { return _mdtype; } |
1318 |
1316 |
1335 // Adds to the given statistic object. Expects to be locked with lock(). |
1333 // Adds to the given statistic object. Expects to be locked with lock(). |
1336 void add_to_statistics_locked(SpaceManagerStatistics* out) const; |
1334 void add_to_statistics_locked(SpaceManagerStatistics* out) const; |
1337 |
1335 |
1338 // Verify internal counters against the current state. Expects to be locked with lock(). |
1336 // Verify internal counters against the current state. Expects to be locked with lock(). |
1339 DEBUG_ONLY(void verify_metrics_locked() const;) |
1337 DEBUG_ONLY(void verify_metrics_locked() const;) |
1340 |
|
1341 protected: |
|
1342 void initialize(); |
|
1343 |
1338 |
1344 public: |
1339 public: |
1345 SpaceManager(Metaspace::MetadataType mdtype, |
1340 SpaceManager(Metaspace::MetadataType mdtype, |
1346 Metaspace::MetaspaceType space_type, |
1341 Metaspace::MetaspaceType space_type, |
1347 Mutex* lock); |
1342 Mutex* lock); |
1391 |
1386 |
1392 // Get the initial chunks size for this metaspace type. |
1387 // Get the initial chunks size for this metaspace type. |
1393 size_t get_initial_chunk_size(Metaspace::MetaspaceType type) const; |
1388 size_t get_initial_chunk_size(Metaspace::MetaspaceType type) const; |
1394 |
1389 |
1395 // Todo: remove this once we have counters by chunk type. |
1390 // Todo: remove this once we have counters by chunk type. |
1396 size_t sum_count_in_chunks_in_use(ChunkIndex i); |
1391 uintx num_chunks_by_type(ChunkIndex chunk_type) const { return _num_chunks_by_type[chunk_type]; } |
1397 |
1392 |
1398 Metachunk* get_new_chunk(size_t chunk_word_size); |
1393 Metachunk* get_new_chunk(size_t chunk_word_size); |
1399 |
1394 |
1400 // Block allocation and deallocation. |
1395 // Block allocation and deallocation. |
1401 // Allocates a block from the current chunk |
1396 // Allocates a block from the current chunk |
1617 // will assert that). |
1612 // will assert that). |
1618 do_update_in_use_info_for_chunk(padding_chunk, true); |
1613 do_update_in_use_info_for_chunk(padding_chunk, true); |
1619 |
1614 |
1620 // Return Chunk to freelist. |
1615 // Return Chunk to freelist. |
1621 inc_container_count(); |
1616 inc_container_count(); |
1622 chunk_manager->return_single_chunk(padding_chunk_type, padding_chunk); |
1617 chunk_manager->return_single_chunk(padding_chunk); |
1623 // Please note: at this point, ChunkManager::return_single_chunk() |
1618 // Please note: at this point, ChunkManager::return_single_chunk() |
1624 // may already have merged the padding chunk with neighboring chunks, so |
1619 // may already have merged the padding chunk with neighboring chunks, so |
1625 // it may have vanished at this point. Do not reference the padding |
1620 // it may have vanished at this point. Do not reference the padding |
1626 // chunk beyond this point. |
1621 // chunk beyond this point. |
1627 } |
1622 } |
2120 // size should be a multiple of the smallest chunk size, we |
2115 // size should be a multiple of the smallest chunk size, we |
2121 // should always be able to fill the VirtualSpace completely. |
2116 // should always be able to fill the VirtualSpace completely. |
2122 if (chunk == NULL) { |
2117 if (chunk == NULL) { |
2123 break; |
2118 break; |
2124 } |
2119 } |
2125 chunk_manager->return_single_chunk(index, chunk); |
2120 chunk_manager->return_single_chunk(chunk); |
2126 } |
2121 } |
2127 DEBUG_ONLY(verify_container_count();) |
2122 DEBUG_ONLY(verify_container_count();) |
2128 } |
2123 } |
2129 assert(free_words_in_vs() == 0, "should be empty now"); |
2124 assert(free_words_in_vs() == 0, "should be empty now"); |
2130 } |
2125 } |
3024 } |
3019 } |
3025 |
3020 |
3026 return chunk; |
3021 return chunk; |
3027 } |
3022 } |
3028 |
3023 |
3029 void ChunkManager::return_single_chunk(ChunkIndex index, Metachunk* chunk) { |
3024 void ChunkManager::return_single_chunk(Metachunk* chunk) { |
|
3025 const ChunkIndex index = chunk->get_chunk_type(); |
3030 assert_lock_strong(MetaspaceExpand_lock); |
3026 assert_lock_strong(MetaspaceExpand_lock); |
3031 DEBUG_ONLY(do_verify_chunk(chunk);) |
3027 DEBUG_ONLY(do_verify_chunk(chunk);) |
3032 assert(chunk->get_chunk_type() == index, "Chunk does not match expected index."); |
|
3033 assert(chunk != NULL, "Expected chunk."); |
3028 assert(chunk != NULL, "Expected chunk."); |
3034 assert(chunk->container() != NULL, "Container should have been set."); |
3029 assert(chunk->container() != NULL, "Container should have been set."); |
3035 assert(chunk->is_tagged_free() == false, "Chunk should be in use."); |
3030 assert(chunk->is_tagged_free() == false, "Chunk should be in use."); |
3036 index_bounds_check(index); |
3031 index_bounds_check(index); |
3037 |
3032 |
3075 } |
3070 } |
3076 } |
3071 } |
3077 |
3072 |
3078 } |
3073 } |
3079 |
3074 |
3080 void ChunkManager::return_chunk_list(ChunkIndex index, Metachunk* chunks) { |
3075 void ChunkManager::return_chunk_list(Metachunk* chunks) { |
3081 index_bounds_check(index); |
|
3082 if (chunks == NULL) { |
3076 if (chunks == NULL) { |
3083 return; |
3077 return; |
3084 } |
3078 } |
3085 LogTarget(Trace, gc, metaspace, freelist) log; |
3079 LogTarget(Trace, gc, metaspace, freelist) log; |
3086 if (log.is_enabled()) { // tracing |
3080 if (log.is_enabled()) { // tracing |
3087 log.print("returning list of %s chunks...", chunk_size_name(index)); |
3081 log.print("returning list of chunks..."); |
3088 } |
3082 } |
3089 unsigned num_chunks_returned = 0; |
3083 unsigned num_chunks_returned = 0; |
3090 size_t size_chunks_returned = 0; |
3084 size_t size_chunks_returned = 0; |
3091 Metachunk* cur = chunks; |
3085 Metachunk* cur = chunks; |
3092 while (cur != NULL) { |
3086 while (cur != NULL) { |
3095 Metachunk* next = cur->next(); |
3089 Metachunk* next = cur->next(); |
3096 if (log.is_enabled()) { // tracing |
3090 if (log.is_enabled()) { // tracing |
3097 num_chunks_returned ++; |
3091 num_chunks_returned ++; |
3098 size_chunks_returned += cur->word_size(); |
3092 size_chunks_returned += cur->word_size(); |
3099 } |
3093 } |
3100 return_single_chunk(index, cur); |
3094 return_single_chunk(cur); |
3101 cur = next; |
3095 cur = next; |
3102 } |
3096 } |
3103 if (log.is_enabled()) { // tracing |
3097 if (log.is_enabled()) { // tracing |
3104 log.print("returned %u %s chunks to freelist, total word size " SIZE_FORMAT ".", |
3098 log.print("returned %u chunks to freelist, total word size " SIZE_FORMAT ".", |
3105 num_chunks_returned, chunk_size_name(index), size_chunks_returned); |
3099 num_chunks_returned, size_chunks_returned); |
3106 if (index != HumongousIndex) { |
|
3107 log.print("updated freelist count: " SIZE_FORMAT ".", free_chunks(index)->size()); |
|
3108 } else { |
|
3109 log.print("updated dictionary count " SIZE_FORMAT ".", _humongous_dictionary.total_count()); |
|
3110 } |
|
3111 } |
3100 } |
3112 } |
3101 } |
3113 |
3102 |
3114 void ChunkManager::collect_statistics(ChunkManagerStatistics* out) const { |
3103 void ChunkManager::collect_statistics(ChunkManagerStatistics* out) const { |
3115 MutexLockerEx cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag); |
3104 MutexLockerEx cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag); |
3168 SIZE_FORMAT " adjusted: " SIZE_FORMAT, requested, adjusted); |
3157 SIZE_FORMAT " adjusted: " SIZE_FORMAT, requested, adjusted); |
3169 |
3158 |
3170 return adjusted; |
3159 return adjusted; |
3171 } |
3160 } |
3172 |
3161 |
3173 size_t SpaceManager::sum_count_in_chunks_in_use(ChunkIndex i) { |
|
3174 size_t count = 0; |
|
3175 Metachunk* chunk = chunks_in_use(i); |
|
3176 while (chunk != NULL) { |
|
3177 count++; |
|
3178 chunk = chunk->next(); |
|
3179 } |
|
3180 return count; |
|
3181 } |
|
3182 |
|
3183 void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const { |
3162 void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const { |
3184 |
3163 |
3185 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
3164 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
3186 Metachunk* chunk = chunks_in_use(i); |
3165 st->print("SpaceManager: " UINTX_FORMAT " %s chunks.", |
3187 st->print("SpaceManager: %s " PTR_FORMAT, |
3166 num_chunks_by_type(i), chunk_size_name(i)); |
3188 chunk_size_name(i), p2i(chunk)); |
|
3189 if (chunk != NULL) { |
|
3190 st->print_cr(" free " SIZE_FORMAT, |
|
3191 chunk->free_word_size()); |
|
3192 } else { |
|
3193 st->cr(); |
|
3194 } |
|
3195 } |
3167 } |
3196 |
3168 |
3197 chunk_manager()->locked_print_free_chunks(st); |
3169 chunk_manager()->locked_print_free_chunks(st); |
3198 } |
3170 } |
3199 |
3171 |
3210 // Instead of jumping to SmallChunk after initial chunk exhausted, keeping allocation |
3182 // Instead of jumping to SmallChunk after initial chunk exhausted, keeping allocation |
3211 // from SpecializeChunk up to _anon_or_delegating_metadata_specialize_chunk_limit (4) |
3183 // from SpecializeChunk up to _anon_or_delegating_metadata_specialize_chunk_limit (4) |
3212 // reduces space waste from 60+% to around 30%. |
3184 // reduces space waste from 60+% to around 30%. |
3213 if ((_space_type == Metaspace::AnonymousMetaspaceType || _space_type == Metaspace::ReflectionMetaspaceType) && |
3185 if ((_space_type == Metaspace::AnonymousMetaspaceType || _space_type == Metaspace::ReflectionMetaspaceType) && |
3214 _mdtype == Metaspace::NonClassType && |
3186 _mdtype == Metaspace::NonClassType && |
3215 sum_count_in_chunks_in_use(SpecializedIndex) < _anon_and_delegating_metadata_specialize_chunk_limit && |
3187 num_chunks_by_type(SpecializedIndex) < _anon_and_delegating_metadata_specialize_chunk_limit && |
3216 word_size + Metachunk::overhead() <= SpecializedChunk) { |
3188 word_size + Metachunk::overhead() <= SpecializedChunk) { |
3217 return SpecializedChunk; |
3189 return SpecializedChunk; |
3218 } |
3190 } |
3219 |
3191 |
3220 if (chunks_in_use(MediumIndex) == NULL && |
3192 if (num_chunks_by_type(MediumIndex) == 0 && |
3221 sum_count_in_chunks_in_use(SmallIndex) < _small_chunk_limit) { |
3193 num_chunks_by_type(SmallIndex) < _small_chunk_limit) { |
3222 chunk_word_size = (size_t) small_chunk_size(); |
3194 chunk_word_size = (size_t) small_chunk_size(); |
3223 if (word_size + Metachunk::overhead() > small_chunk_size()) { |
3195 if (word_size + Metachunk::overhead() > small_chunk_size()) { |
3224 chunk_word_size = medium_chunk_size(); |
3196 chunk_word_size = medium_chunk_size(); |
3225 } |
3197 } |
3226 } else { |
3198 } else { |
3322 _space_type(space_type), |
3294 _space_type(space_type), |
3323 _capacity_words(0), |
3295 _capacity_words(0), |
3324 _used_words(0), |
3296 _used_words(0), |
3325 _overhead_words(0), |
3297 _overhead_words(0), |
3326 _block_freelists(NULL), |
3298 _block_freelists(NULL), |
3327 _lock(lock) |
3299 _lock(lock), |
|
3300 _chunk_list(NULL), |
|
3301 _current_chunk(NULL) |
3328 { |
3302 { |
3329 initialize(); |
3303 Metadebug::init_allocation_fail_alot_count(); |
|
3304 memset(_num_chunks_by_type, 0, sizeof(_num_chunks_by_type)); |
|
3305 log_trace(gc, metaspace, freelist)("SpaceManager(): " PTR_FORMAT, p2i(this)); |
3330 } |
3306 } |
3331 |
3307 |
3332 void SpaceManager::account_for_new_chunk(const Metachunk* new_chunk) { |
3308 void SpaceManager::account_for_new_chunk(const Metachunk* new_chunk) { |
3333 |
3309 |
3334 assert_lock_strong(MetaspaceExpand_lock); |
3310 assert_lock_strong(MetaspaceExpand_lock); |
3335 |
3311 |
3336 _capacity_words += new_chunk->word_size(); |
3312 _capacity_words += new_chunk->word_size(); |
3337 _overhead_words += Metachunk::overhead(); |
3313 _overhead_words += Metachunk::overhead(); |
|
3314 DEBUG_ONLY(new_chunk->verify()); |
|
3315 _num_chunks_by_type[new_chunk->get_chunk_type()] ++; |
3338 |
3316 |
3339 // Adjust global counters: |
3317 // Adjust global counters: |
3340 MetaspaceUtils::inc_capacity(mdtype(), new_chunk->word_size()); |
3318 MetaspaceUtils::inc_capacity(mdtype(), new_chunk->word_size()); |
3341 MetaspaceUtils::inc_overhead(mdtype(), Metachunk::overhead()); |
3319 MetaspaceUtils::inc_overhead(mdtype(), Metachunk::overhead()); |
3342 } |
3320 } |
3358 assert_lock_strong(MetaspaceExpand_lock); |
3336 assert_lock_strong(MetaspaceExpand_lock); |
3359 |
3337 |
3360 MetaspaceUtils::dec_capacity(mdtype(), _capacity_words); |
3338 MetaspaceUtils::dec_capacity(mdtype(), _capacity_words); |
3361 MetaspaceUtils::dec_overhead(mdtype(), _overhead_words); |
3339 MetaspaceUtils::dec_overhead(mdtype(), _overhead_words); |
3362 MetaspaceUtils::dec_used(mdtype(), _used_words); |
3340 MetaspaceUtils::dec_used(mdtype(), _used_words); |
3363 } |
|
3364 |
|
3365 void SpaceManager::initialize() { |
|
3366 Metadebug::init_allocation_fail_alot_count(); |
|
3367 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
|
3368 _chunks_in_use[i] = NULL; |
|
3369 } |
|
3370 _current_chunk = NULL; |
|
3371 log_trace(gc, metaspace, freelist)("SpaceManager(): " PTR_FORMAT, p2i(this)); |
|
3372 } |
3341 } |
3373 |
3342 |
3374 SpaceManager::~SpaceManager() { |
3343 SpaceManager::~SpaceManager() { |
3375 |
3344 |
3376 // This call this->_lock which can't be done while holding MetaspaceExpand_lock |
3345 // This call this->_lock which can't be done while holding MetaspaceExpand_lock |
3397 // Add all the chunks in use by this space manager |
3366 // Add all the chunks in use by this space manager |
3398 // to the global list of free chunks. |
3367 // to the global list of free chunks. |
3399 |
3368 |
3400 // Follow each list of chunks-in-use and add them to the |
3369 // Follow each list of chunks-in-use and add them to the |
3401 // free lists. Each list is NULL terminated. |
3370 // free lists. Each list is NULL terminated. |
3402 |
3371 chunk_manager()->return_chunk_list(chunk_list()); |
3403 for (ChunkIndex i = ZeroIndex; i <= HumongousIndex; i = next_chunk_index(i)) { |
3372 #ifdef ASSERT |
3404 Metachunk* chunks = chunks_in_use(i); |
3373 _chunk_list = NULL; |
3405 chunk_manager()->return_chunk_list(i, chunks); |
3374 _current_chunk = NULL; |
3406 set_chunks_in_use(i, NULL); |
3375 #endif |
3407 } |
|
3408 |
3376 |
3409 chunk_manager()->slow_locked_verify(); |
3377 chunk_manager()->slow_locked_verify(); |
3410 |
3378 |
3411 if (_block_freelists != NULL) { |
3379 if (_block_freelists != NULL) { |
3412 delete _block_freelists; |
3380 delete _block_freelists; |
3444 retire_current_chunk(); |
3412 retire_current_chunk(); |
3445 set_current_chunk(new_chunk); |
3413 set_current_chunk(new_chunk); |
3446 } |
3414 } |
3447 |
3415 |
3448 // Add the new chunk at the head of its respective chunk list. |
3416 // Add the new chunk at the head of its respective chunk list. |
3449 new_chunk->set_next(chunks_in_use(index)); |
3417 new_chunk->set_next(_chunk_list); |
3450 set_chunks_in_use(index, new_chunk); |
3418 _chunk_list = new_chunk; |
3451 |
3419 |
3452 // Adjust counters. |
3420 // Adjust counters. |
3453 account_for_new_chunk(new_chunk); |
3421 account_for_new_chunk(new_chunk); |
3454 |
3422 |
3455 assert(new_chunk->is_empty(), "Not ready for reuse"); |
3423 assert(new_chunk->is_empty(), "Not ready for reuse"); |
3538 result = grow_and_allocate(word_size); |
3506 result = grow_and_allocate(word_size); |
3539 } |
3507 } |
3540 |
3508 |
3541 if (result != NULL) { |
3509 if (result != NULL) { |
3542 account_for_allocation(word_size); |
3510 account_for_allocation(word_size); |
3543 assert(result != (MetaWord*) chunks_in_use(MediumIndex), |
|
3544 "Head of the list is being allocated"); |
|
3545 } |
3511 } |
3546 |
3512 |
3547 return result; |
3513 return result; |
3548 } |
3514 } |
3549 |
3515 |
3550 void SpaceManager::verify() { |
3516 void SpaceManager::verify() { |
3551 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
3517 Metachunk* curr = chunk_list(); |
3552 Metachunk* curr = chunks_in_use(i); |
3518 while (curr != NULL) { |
3553 while (curr != NULL) { |
3519 DEBUG_ONLY(do_verify_chunk(curr);) |
3554 DEBUG_ONLY(do_verify_chunk(curr);) |
3520 assert(curr->is_tagged_free() == false, "Chunk should be tagged as in use."); |
3555 assert(curr->is_tagged_free() == false, "Chunk should be tagged as in use."); |
3521 curr = curr->next(); |
3556 curr = curr->next(); |
|
3557 } |
|
3558 } |
3522 } |
3559 } |
3523 } |
3560 |
3524 |
3561 void SpaceManager::verify_chunk_size(Metachunk* chunk) { |
3525 void SpaceManager::verify_chunk_size(Metachunk* chunk) { |
3562 assert(is_humongous(chunk->word_size()) || |
3526 assert(is_humongous(chunk->word_size()) || |
3567 return; |
3531 return; |
3568 } |
3532 } |
3569 |
3533 |
3570 void SpaceManager::add_to_statistics_locked(SpaceManagerStatistics* out) const { |
3534 void SpaceManager::add_to_statistics_locked(SpaceManagerStatistics* out) const { |
3571 assert_lock_strong(lock()); |
3535 assert_lock_strong(lock()); |
3572 for (ChunkIndex i = ZeroIndex; i < NumberOfInUseLists; i = next_chunk_index(i)) { |
3536 Metachunk* chunk = chunk_list(); |
3573 UsedChunksStatistics& chunk_stat = out->chunk_stats(i); |
3537 while (chunk != NULL) { |
3574 Metachunk* chunk = chunks_in_use(i); |
3538 UsedChunksStatistics& chunk_stat = out->chunk_stats(chunk->get_chunk_type()); |
3575 while (chunk != NULL) { |
3539 chunk_stat.add_num(1); |
3576 chunk_stat.add_num(1); |
3540 chunk_stat.add_cap(chunk->word_size()); |
3577 chunk_stat.add_cap(chunk->word_size()); |
3541 chunk_stat.add_overhead(Metachunk::overhead()); |
3578 chunk_stat.add_overhead(Metachunk::overhead()); |
3542 chunk_stat.add_used(chunk->used_word_size() - Metachunk::overhead()); |
3579 chunk_stat.add_used(chunk->used_word_size() - Metachunk::overhead()); |
3543 if (chunk != current_chunk()) { |
3580 if (chunk != current_chunk()) { |
3544 chunk_stat.add_waste(chunk->free_word_size()); |
3581 chunk_stat.add_waste(chunk->free_word_size()); |
3545 } else { |
3582 } else { |
3546 chunk_stat.add_free(chunk->free_word_size()); |
3583 chunk_stat.add_free(chunk->free_word_size()); |
3547 } |
3584 } |
3548 chunk = chunk->next(); |
3585 chunk = chunk->next(); |
|
3586 } |
|
3587 } |
3549 } |
3588 if (block_freelists() != NULL) { |
3550 if (block_freelists() != NULL) { |
3589 out->add_free_blocks_info(block_freelists()->num_blocks(), block_freelists()->total_size()); |
3551 out->add_free_blocks_info(block_freelists()->num_blocks(), block_freelists()->total_size()); |
3590 } |
3552 } |
3591 } |
3553 } |