src/hotspot/share/memory/metaspace/spaceManager.cpp
branchstuefe-new-metaspace-branch
changeset 58085 a5f523f2ff91
parent 58063 bdf136b8ae0e
child 58227 0e7d9a23261e
equal deleted inserted replaced
58070:2cecbd566968 58085:a5f523f2ff91
    79   }
    79   }
    80   return byte_size / BytesPerWord;
    80   return byte_size / BytesPerWord;
    81 
    81 
    82 }
    82 }
    83 
    83 
    84 
       
    85 
       
    86 // Given a requested word size, will allocate a chunk large enough to at least fit that
    84 // Given a requested word size, will allocate a chunk large enough to at least fit that
    87 // size, but may be larger according to the rules in the ChunkAllocSequence.
    85 // size, but may be larger according to internal heuristics.
    88 // Updates counters and adds the chunk to the head of the chunk list.
    86 //
    89 Metachunk* SpaceManager::allocate_chunk_to_fit(size_t requested_word_size) {
    87 // On success, it will replace the current chunk with the newly allocated one, which will
       
    88 // become the current chunk. The old current chunk should be retired beforehand.
       
    89 //
       
    90 // May fail if we could not allocate a new chunk. In that case the current chunk remains
       
    91 // unchanged and false is returned.
       
    92 bool SpaceManager::allocate_new_current_chunk(size_t requested_word_size) {
    90 
    93 
    91   assert_lock_strong(lock());
    94   assert_lock_strong(lock());
    92 
    95 
    93   guarantee(requested_word_size < chklvl::MAX_CHUNK_WORD_SIZE,
    96   guarantee(requested_word_size < chklvl::MAX_CHUNK_WORD_SIZE,
    94             "Requested size too large (" SIZE_FORMAT ").", requested_word_size);
    97             "Requested size too large (" SIZE_FORMAT ").", requested_word_size);
    95 
    98 
       
    99   // If we have a current chunk, it should have been retired (almost empty) beforehand.
       
   100   // See: retire_current_chunk().
       
   101   assert(current_chunk() == NULL || current_chunk()->free_below_committed_words() <= 10, "Must retire chunk beforehand");
       
   102 
    96   const chklvl_t min_level = chklvl::level_fitting_word_size(requested_word_size);
   103   const chklvl_t min_level = chklvl::level_fitting_word_size(requested_word_size);
    97   chklvl_t pref_level = _chunk_alloc_sequence->get_next_chunk_level(_chunks.size());
   104   chklvl_t pref_level = _chunk_alloc_sequence->get_next_chunk_level(_chunks.size());
    98 
   105 
    99   if (pref_level > min_level) {
   106   if (pref_level > min_level) {
   100     pref_level = min_level;
   107     pref_level = min_level;
   101   }
   108   }
   102 
   109 
   103   Metachunk* c = _chunk_manager->get_chunk(min_level, pref_level);
   110   Metachunk* c = _chunk_manager->get_chunk(min_level, pref_level);
   104   assert(c != NULL, "Could not get a chunk");
   111   if (c == NULL) {
       
   112     log_debug(metaspace)("SpaceManager %s: failed to allocate new chunk for requested word size " SIZE_FORMAT ".",
       
   113                          _name, requested_word_size);
       
   114     return false;
       
   115   }
       
   116 
   105   assert(c->is_in_use(), "Wrong chunk state.");
   117   assert(c->is_in_use(), "Wrong chunk state.");
   106   assert(c->level() <= min_level && c->level() >= pref_level, "Sanity");
   118   assert(c->level() <= min_level && c->level() >= pref_level, "Sanity");
   107 
   119 
   108   _chunks.add(c);
   120   _chunks.add(c);
   109 
   121 
   142 }
   154 }
   143 
   155 
   144 SpaceManager::~SpaceManager() {
   156 SpaceManager::~SpaceManager() {
   145 
   157 
   146   MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
   158   MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
   147 
       
   148   // Return all chunks to our chunk manager.
       
   149   // Note: this destroys the _chunks list.
       
   150   Metachunk* c = _chunks.first();
   159   Metachunk* c = _chunks.first();
   151   Metachunk* c2 = NULL;
   160   Metachunk* c2 = NULL;
   152   while(c) {
   161   while(c) {
   153     // c may become invalid. Take care while iterating.
   162     // c may become invalid. Take care while iterating.
   154     c2 = c->next();
   163     c2 = c->next();
   162 
   171 
   163   delete _block_freelist;
   172   delete _block_freelist;
   164 
   173 
   165 }
   174 }
   166 
   175 
   167 // The current chunk is unable to service a request. The remainder of the chunk is
   176 // The remaining committed free space in the current chunk is chopped up and stored in the block
   168 // chopped into blocks and fed into the _block_freelists, in the hope of later reuse.
   177 // free list for later use. As a result, the current chunk will remain current but completely
       
   178 // used up. This is a preparation for calling allocate_new_current_chunk().
   169 void SpaceManager::retire_current_chunk() {
   179 void SpaceManager::retire_current_chunk() {
   170   assert_lock_strong(lock());
   180   assert_lock_strong(lock());
   171 
   181 
   172   Metachunk* c = current_chunk();
   182   Metachunk* c = current_chunk();
   173   assert(c != NULL, "Sanity");
   183   assert(c != NULL, "Sanity");
   174 
   184 
   175   log_debug(metaspace)("SpaceManager %s: retiring chunk " METACHUNK_FULL_FORMAT ".",
   185   log_debug(metaspace)("SpaceManager %s: retiring chunk " METACHUNK_FULL_FORMAT ".",
   176                        _name, METACHUNK_FULL_FORMAT_ARGS(c));
   186                        _name, METACHUNK_FULL_FORMAT_ARGS(c));
   177 
   187 
   178   // We can run into very rare situations where we would retire a completely empty chunk.
   188   // Side note:
   179   // This should be exceedingly rare: the chunk was created to fit a prior, smaller, allocation,
   189   // In theory it could happen that we are asked to retire a completely empty chunk. This may be the
   180   // and then the allocation did not go thru since we hit the commit limit, or was immediately
   190   // result of rolled back allocations (see deallocate in place) and a lot of luck.
   181   // immediately deallocated and that hit the fast path (see Metachunk::attempt_roll_back_allocation()).
   191   // But since these cases should be exceedingly rare, we do not handle them special in order to keep
   182   // Then, that allocation was followed by a larger allocation which is too small for the still
   192   // the code simple.
   183   // empty current chunk.
   193 
   184   if (c->used_words() == 0) {
   194   size_t raw_remaining_words = c->free_below_committed_words();
   185     // (A)
   195   size_t net_remaining_words = get_net_allocation_word_size(raw_remaining_words);
   186     log_trace(metaspace)("SpaceManager %s: ... completely empty, return to freelist: chunk" METACHUNK_FORMAT ".",
   196   if (net_remaining_words > 0) {
   187                          _name, METACHUNK_FORMAT_ARGS(c));
   197     bool did_hit_limit = false;
   188 
   198     MetaWord* ptr = c->allocate(net_remaining_words, &did_hit_limit);
   189     // Remove the current chunk from our list and return it to the chunk manager.
   199     assert(ptr != NULL && did_hit_limit == false, "Should have worked");
   190     _chunks.remove(c);
   200     add_allocation_to_block_freelist(ptr, net_remaining_words);
   191     _chunk_manager->return_chunk(c);
   201     _total_used_words_counter->increment_by(net_remaining_words);
   192 
       
   193   } else {
       
   194     // (B)
       
   195     size_t raw_remaining_words = c->free_below_committed_words();
       
   196     size_t net_remaining_words = get_net_allocation_word_size(raw_remaining_words);
       
   197     if (net_remaining_words > 0) {
       
   198       bool did_hit_limit = false;
       
   199       MetaWord* ptr = c->allocate(net_remaining_words, &did_hit_limit);
       
   200       assert(ptr != NULL && did_hit_limit == false, "Should have worked");
       
   201       add_allocation_to_block_freelist(ptr, net_remaining_words);
       
   202       _total_used_words_counter->increment_by(net_remaining_words);
       
   203     }
       
   204   }
   202   }
   205 
   203 
   206   // After this operation: the current chunk should have (almost) no free committed space left.
   204   // After this operation: the current chunk should have (almost) no free committed space left.
   207   // It could also be NULL, if we hit case (A) and returned the only chunk in this space manager.
   205   assert(current_chunk()->free_below_committed_words() <= highest_possible_delta_between_raw_and_net_size,
   208   assert(current_chunk() == NULL ||
       
   209          current_chunk()->free_below_committed_words() <= highest_possible_delta_between_raw_and_net_size,
       
   210          "Chunk retiring did not work (current chunk " METACHUNK_FULL_FORMAT ").",
   206          "Chunk retiring did not work (current chunk " METACHUNK_FULL_FORMAT ").",
   211          METACHUNK_FULL_FORMAT_ARGS(current_chunk()));
   207          METACHUNK_FULL_FORMAT_ARGS(current_chunk()));
   212 
   208 
   213 }
   209 }
   214 
   210 
   232 
   228 
   233   bool did_hit_limit = false;
   229   bool did_hit_limit = false;
   234 
   230 
   235   // Allocate first chunk if needed.
   231   // Allocate first chunk if needed.
   236   if (current_chunk() == NULL) {
   232   if (current_chunk() == NULL) {
   237     Metachunk* c = allocate_chunk_to_fit(raw_word_size);
   233     if (allocate_new_current_chunk(raw_word_size) == false) {
   238     assert(c != NULL && _chunks.size() == 1 && c == current_chunk(), "Should be");
   234       did_hit_limit = true;
       
   235     } else {
       
   236       assert(current_chunk() != NULL && current_chunk()->free_words() >= raw_word_size, "Sanity");
       
   237     }
   239   }
   238   }
   240 
   239 
   241   // 1) Attempt to allocate from the dictionary of deallocated blocks.
   240   // 1) Attempt to allocate from the dictionary of deallocated blocks.
   242 
   241 
   243   // Allocation from the dictionary is expensive in the sense that
   242   // Allocation from the dictionary is expensive in the sense that
   307     retire_current_chunk();
   306     retire_current_chunk();
   308 
   307 
   309     DEBUG_ONLY(InternalStats::inc_num_chunks_retired();)
   308     DEBUG_ONLY(InternalStats::inc_num_chunks_retired();)
   310 
   309 
   311     // Allocate a new chunk.
   310     // Allocate a new chunk.
   312     Metachunk* c = allocate_chunk_to_fit(raw_word_size);
   311     if (allocate_new_current_chunk(raw_word_size) == false) {
   313     assert(c != NULL && _chunks.size() > 0 && c == current_chunk(), "Should be");
   312       did_hit_limit = true;
   314 
   313     } else {
   315     p = current_chunk()->allocate(raw_word_size, &did_hit_limit);
   314       assert(current_chunk() != NULL && current_chunk()->free_words() >= raw_word_size, "Sanity");
   316     log_trace(metaspace)("SpaceManager %s: .. allocated new chunk " CHKLVL_FORMAT " and taken from that.",
   315       p = current_chunk()->allocate(raw_word_size, &did_hit_limit);
   317                          _name, current_chunk()->level());
   316       log_trace(metaspace)("SpaceManager %s: .. allocated new chunk " CHKLVL_FORMAT " and taken from that.",
       
   317                            _name, current_chunk()->level());
       
   318     }
   318 
   319 
   319   }
   320   }
   320 
   321 
   321   assert(p != NULL || (p == NULL && did_hit_limit), "Sanity");
   322   assert(p != NULL || (p == NULL && did_hit_limit), "Sanity");
   322 
   323 
   323   if (p == NULL) {
   324   if (p == NULL) {
   324     DEBUG_ONLY(InternalStats::inc_num_allocs_failed_limit();)
   325     DEBUG_ONLY(InternalStats::inc_num_allocs_failed_limit();)
   325   } else {
   326   } else {
   326     DEBUG_ONLY(InternalStats::inc_num_allocs();)
   327     DEBUG_ONLY(InternalStats::inc_num_allocs();)
       
   328     _total_used_words_counter->increment_by(raw_word_size);
   327   }
   329   }
   328 
   330 
   329   log_trace(metaspace)("SpaceManager %s: returned " PTR_FORMAT ".",
   331   log_trace(metaspace)("SpaceManager %s: returned " PTR_FORMAT ".",
   330                        _name, p2i(p));
   332                        _name, p2i(p));
   331 
       
   332   _total_used_words_counter->increment_by(raw_word_size);
       
   333 
   333 
   334   return p;
   334   return p;
   335 
   335 
   336 }
   336 }
   337 
   337