src/hotspot/share/memory/metaspace.cpp
changeset 50066 bd3e4517dfa3
parent 50038 3db7884546a1
child 50119 bf9177eac58d
equal deleted inserted replaced
50065:ae0ebd3cf949 50066:bd3e4517dfa3
   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 }