< prev index next >

src/hotspot/share/memory/metaspace/metaspaceArena.cpp

Print this page

 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  *
 24  */
 25 
 26 #include "precompiled.hpp"
 27 #include "logging/log.hpp"
 28 #include "logging/logStream.hpp"
 29 #include "memory/metaspace/chunkManager.hpp"
 30 #include "memory/metaspace/counters.hpp"
 31 #include "memory/metaspace/freeBlocks.hpp"
 32 #include "memory/metaspace/internalStats.hpp"
 33 #include "memory/metaspace/metachunk.hpp"

 34 #include "memory/metaspace/metaspaceArena.hpp"
 35 #include "memory/metaspace/metaspaceArenaGrowthPolicy.hpp"
 36 #include "memory/metaspace/metaspaceCommon.hpp"
 37 #include "memory/metaspace/metaspaceSettings.hpp"
 38 #include "memory/metaspace/metaspaceStatistics.hpp"
 39 #include "memory/metaspace/virtualSpaceList.hpp"
 40 #include "runtime/atomic.hpp"
 41 #include "runtime/init.hpp"
 42 #include "runtime/mutexLocker.hpp"
 43 #include "services/memoryService.hpp"
 44 #include "utilities/align.hpp"
 45 #include "utilities/debug.hpp"
 46 #include "utilities/globalDefinitions.hpp"
 47 
 48 namespace metaspace {
 49 
 50 #define LOGFMT         "Arena @" PTR_FORMAT " (%s)"
 51 #define LOGFMT_ARGS    p2i(this), this->_name
 52 
 53 // Returns the level of the next chunk to be added, acc to growth policy.

 90   const chunklevel_t max_level = chunklevel::level_fitting_word_size(requested_word_size);
 91   const chunklevel_t preferred_level = MIN2(max_level, next_chunk_level());
 92 
 93   Metachunk* c = _chunk_manager->get_chunk(preferred_level, max_level, requested_word_size);
 94   if (c == NULL) {
 95     return NULL;
 96   }
 97 
 98   assert(c->is_in_use(), "Wrong chunk state.");
 99   assert(c->free_below_committed_words() >= requested_word_size, "Chunk not committed");
100   return c;
101 }
102 
103 void MetaspaceArena::add_allocation_to_fbl(MetaWord* p, size_t word_size) {
104   if (_fbl == NULL) {
105     _fbl = new FreeBlocks(); // Create only on demand
106   }
107   _fbl->add_block(p, word_size);
108 }
109 
110 MetaspaceArena::MetaspaceArena(ChunkManager* chunk_manager, const ArenaGrowthPolicy* growth_policy,
111                                Mutex* lock, SizeAtomicCounter* total_used_words_counter,
112                                const char* name) :
113   _lock(lock),
114   _chunk_manager(chunk_manager),
115   _growth_policy(growth_policy),
116   _chunks(),

117   _fbl(NULL),
118   _total_used_words_counter(total_used_words_counter),
119   _name(name)
120 #ifdef ASSERT
121   , _first_fence(NULL)
122 #endif

123 {
124   UL(debug, ": born.");
125 
126   // Update statistics
127   InternalStats::inc_num_arena_births();
128 }
129 
130 MetaspaceArena::~MetaspaceArena() {
131 #ifdef ASSERT
132   verify();
133   if (Settings::use_allocation_guard()) {
134     verify_allocation_guards();
135   }
136 #endif
137 
138   MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
139   MemRangeCounter return_counter;
140 
141   Metachunk* c = _chunks.first();
142   Metachunk* c2 = NULL;

207   if (next_chunk_level() > c->level()) {
208     return false;
209   }
210 
211   bool success = _chunk_manager->attempt_enlarge_chunk(c);
212   assert(success == false || c->free_words() >= requested_word_size, "Sanity");
213   return success;
214 }
215 
216 // Allocate memory from Metaspace.
217 // 1) Attempt to allocate from the free block list.
218 // 2) Attempt to allocate from the current chunk.
219 // 3) Attempt to enlarge the current chunk in place if it is too small.
220 // 4) Attempt to get a new chunk and allocate from that chunk.
221 // At any point, if we hit a commit limit, we return NULL.
222 MetaWord* MetaspaceArena::allocate(size_t requested_word_size) {
223   MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
224   UL2(trace, "requested " SIZE_FORMAT " words.", requested_word_size);
225 
226   MetaWord* p = NULL;
227   const size_t raw_word_size = get_raw_word_size_for_requested_word_size(requested_word_size);
228 
229   // Before bothering the arena proper, attempt to re-use a block from the free blocks list
230   if (_fbl != NULL && !_fbl->is_empty()) {
231     p = _fbl->remove_block(raw_word_size);
232     if (p != NULL) {
233       DEBUG_ONLY(InternalStats::inc_num_allocs_from_deallocated_blocks();)
234       UL2(trace, "taken from fbl (now: %d, " SIZE_FORMAT ").",
235           _fbl->count(), _fbl->total_size());
236       // Note: free blocks in freeblock dictionary still count as "used" as far as statistics go;
237       // therefore we have no need to adjust any usage counters (see epilogue of allocate_inner())
238       // and can just return here.
239       return p;
240     }
241   }
242 
243   // Primary allocation
244   p = allocate_inner(requested_word_size);
245 
246 #ifdef ASSERT
247   // Fence allocation

251     if (guard != NULL) {
252       // Ignore allocation errors for the fence to keep coding simple. If this
253       // happens (e.g. because right at this time we hit the Metaspace GC threshold)
254       // we miss adding this one fence. Not a big deal. Note that his would
255       // be pretty rare. Chances are much higher the primary allocation above
256       // would have already failed).
257       Fence* f = new(guard) Fence(_first_fence);
258       _first_fence = f;
259     }
260   }
261 #endif // ASSERT
262 
263   return p;
264 }
265 
266 // Allocate from the arena proper, once dictionary allocations and fencing are sorted out.
267 MetaWord* MetaspaceArena::allocate_inner(size_t requested_word_size) {
268 
269   assert_lock_strong(lock());
270 
271   const size_t raw_word_size = get_raw_word_size_for_requested_word_size(requested_word_size);
272   MetaWord* p = NULL;
273   bool current_chunk_too_small = false;
274   bool commit_failure = false;
275 
276   if (current_chunk() != NULL) {
277 
278     // Attempt to satisfy the allocation from the current chunk.
279 
280     // If the current chunk is too small to hold the requested size, attempt to enlarge it.
281     // If that fails, retire the chunk.
282     if (current_chunk()->free_words() < raw_word_size) {
283       if (!attempt_enlarge_current_chunk(raw_word_size)) {
284         current_chunk_too_small = true;
285       } else {
286         DEBUG_ONLY(InternalStats::inc_num_chunks_enlarged();)
287         UL(debug, "enlarged chunk.");
288       }
289     }
290 
291     // Commit the chunk far enough to hold the requested word size. If that fails, we

351     UL2(trace, "after allocation: %u chunk(s), current:" METACHUNK_FULL_FORMAT,
352         _chunks.count(), METACHUNK_FULL_FORMAT_ARGS(current_chunk()));
353     UL2(trace, "returning " PTR_FORMAT ".", p2i(p));
354   }
355   return p;
356 }
357 
358 // Prematurely returns a metaspace allocation to the _block_freelists
359 // because it is not needed anymore (requires CLD lock to be active).
360 void MetaspaceArena::deallocate_locked(MetaWord* p, size_t word_size) {
361   assert_lock_strong(lock());
362   // At this point a current chunk must exist since we only deallocate if we did allocate before.
363   assert(current_chunk() != NULL, "stray deallocation?");
364   assert(is_valid_area(p, word_size),
365          "Pointer range not part of this Arena and cannot be deallocated: (" PTR_FORMAT ".." PTR_FORMAT ").",
366          p2i(p), p2i(p + word_size));
367 
368   UL2(trace, "deallocating " PTR_FORMAT ", word size: " SIZE_FORMAT ".",
369       p2i(p), word_size);
370 
371   size_t raw_word_size = get_raw_word_size_for_requested_word_size(word_size);
372   add_allocation_to_fbl(p, raw_word_size);
373 
374   DEBUG_ONLY(verify_locked();)
375 }
376 
377 // Prematurely returns a metaspace allocation to the _block_freelists because it is not
378 // needed anymore.
379 void MetaspaceArena::deallocate(MetaWord* p, size_t word_size) {
380   MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
381   deallocate_locked(p, word_size);
382 }
383 
384 // Update statistics. This walks all in-use chunks.
385 void MetaspaceArena::add_to_statistics(ArenaStats* out) const {
386   MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
387 
388   for (const Metachunk* c = _chunks.first(); c != NULL; c = c->next()) {
389     InUseChunkStats& ucs = out->_stats[c->level()];
390     ucs._num++;
391     ucs._word_size += c->word_size();

465     assert(c->is_valid_committed_pointer(p) ==
466            c->is_valid_committed_pointer(p + word_size - 1), "range intersects");
467     found = c->is_valid_committed_pointer(p);
468   }
469   return found;
470 }
471 
472 #endif // ASSERT
473 
474 void MetaspaceArena::print_on(outputStream* st) const {
475   MutexLocker fcl(_lock, Mutex::_no_safepoint_check_flag);
476   print_on_locked(st);
477 }
478 
479 void MetaspaceArena::print_on_locked(outputStream* st) const {
480   assert_lock_strong(_lock);
481   st->print_cr("sm %s: %d chunks, total word size: " SIZE_FORMAT ", committed word size: " SIZE_FORMAT, _name,
482                _chunks.count(), _chunks.calc_word_size(), _chunks.calc_committed_word_size());
483   _chunks.print_on(st);
484   st->cr();
485   st->print_cr("growth-policy " PTR_FORMAT ", lock " PTR_FORMAT ", cm " PTR_FORMAT ", fbl " PTR_FORMAT,
486                 p2i(_growth_policy), p2i(_lock), p2i(_chunk_manager), p2i(_fbl));
487 }
488 
489 } // namespace metaspace
490 

 14  * accompanied this code).
 15  *
 16  * You should have received a copy of the GNU General Public License version
 17  * 2 along with this work; if not, write to the Free Software Foundation,
 18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19  *
 20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21  * or visit www.oracle.com if you need additional information or have any
 22  * questions.
 23  *
 24  */
 25 
 26 #include "precompiled.hpp"
 27 #include "logging/log.hpp"
 28 #include "logging/logStream.hpp"
 29 #include "memory/metaspace/chunkManager.hpp"
 30 #include "memory/metaspace/counters.hpp"
 31 #include "memory/metaspace/freeBlocks.hpp"
 32 #include "memory/metaspace/internalStats.hpp"
 33 #include "memory/metaspace/metachunk.hpp"
 34 #include "memory/metaspace/metaspaceAlignment.hpp"
 35 #include "memory/metaspace/metaspaceArena.hpp"
 36 #include "memory/metaspace/metaspaceArenaGrowthPolicy.hpp"
 37 #include "memory/metaspace/metaspaceCommon.hpp"
 38 #include "memory/metaspace/metaspaceSettings.hpp"
 39 #include "memory/metaspace/metaspaceStatistics.hpp"
 40 #include "memory/metaspace/virtualSpaceList.hpp"
 41 #include "runtime/atomic.hpp"
 42 #include "runtime/init.hpp"
 43 #include "runtime/mutexLocker.hpp"
 44 #include "services/memoryService.hpp"
 45 #include "utilities/align.hpp"
 46 #include "utilities/debug.hpp"
 47 #include "utilities/globalDefinitions.hpp"
 48 
 49 namespace metaspace {
 50 
 51 #define LOGFMT         "Arena @" PTR_FORMAT " (%s)"
 52 #define LOGFMT_ARGS    p2i(this), this->_name
 53 
 54 // Returns the level of the next chunk to be added, acc to growth policy.

 91   const chunklevel_t max_level = chunklevel::level_fitting_word_size(requested_word_size);
 92   const chunklevel_t preferred_level = MIN2(max_level, next_chunk_level());
 93 
 94   Metachunk* c = _chunk_manager->get_chunk(preferred_level, max_level, requested_word_size);
 95   if (c == NULL) {
 96     return NULL;
 97   }
 98 
 99   assert(c->is_in_use(), "Wrong chunk state.");
100   assert(c->free_below_committed_words() >= requested_word_size, "Chunk not committed");
101   return c;
102 }
103 
104 void MetaspaceArena::add_allocation_to_fbl(MetaWord* p, size_t word_size) {
105   if (_fbl == NULL) {
106     _fbl = new FreeBlocks(); // Create only on demand
107   }
108   _fbl->add_block(p, word_size);
109 }
110 
111 MetaspaceArena::MetaspaceArena(ChunkManager* chunk_manager, const ArenaGrowthPolicy* growth_policy, int alignment_words,
112                                Mutex* lock, SizeAtomicCounter* total_used_words_counter,
113                                const char* name) :
114   _lock(lock),
115   _chunk_manager(chunk_manager),
116   _growth_policy(growth_policy),
117   _chunks(),
118   _alignment_words(alignment_words),
119   _fbl(NULL),
120   _total_used_words_counter(total_used_words_counter),
121   _name(name)
122 #ifdef ASSERT
123   , _first_fence(NULL)
124 #endif
125 
126 {
127   UL(debug, ": born.");
128 
129   // Update statistics
130   InternalStats::inc_num_arena_births();
131 }
132 
133 MetaspaceArena::~MetaspaceArena() {
134 #ifdef ASSERT
135   verify();
136   if (Settings::use_allocation_guard()) {
137     verify_allocation_guards();
138   }
139 #endif
140 
141   MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
142   MemRangeCounter return_counter;
143 
144   Metachunk* c = _chunks.first();
145   Metachunk* c2 = NULL;

210   if (next_chunk_level() > c->level()) {
211     return false;
212   }
213 
214   bool success = _chunk_manager->attempt_enlarge_chunk(c);
215   assert(success == false || c->free_words() >= requested_word_size, "Sanity");
216   return success;
217 }
218 
219 // Allocate memory from Metaspace.
220 // 1) Attempt to allocate from the free block list.
221 // 2) Attempt to allocate from the current chunk.
222 // 3) Attempt to enlarge the current chunk in place if it is too small.
223 // 4) Attempt to get a new chunk and allocate from that chunk.
224 // At any point, if we hit a commit limit, we return NULL.
225 MetaWord* MetaspaceArena::allocate(size_t requested_word_size) {
226   MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
227   UL2(trace, "requested " SIZE_FORMAT " words.", requested_word_size);
228 
229   MetaWord* p = NULL;
230   const size_t raw_word_size = get_raw_word_size_for_requested_word_size(requested_word_size, _alignment_words);
231 
232   // Before bothering the arena proper, attempt to re-use a block from the free blocks list
233   if (_fbl != NULL && !_fbl->is_empty()) {
234     p = _fbl->remove_block(raw_word_size);
235     if (p != NULL) {
236       DEBUG_ONLY(InternalStats::inc_num_allocs_from_deallocated_blocks();)
237       UL2(trace, "taken from fbl (now: %d, " SIZE_FORMAT ").",
238           _fbl->count(), _fbl->total_size());
239       // Note: free blocks in freeblock dictionary still count as "used" as far as statistics go;
240       // therefore we have no need to adjust any usage counters (see epilogue of allocate_inner())
241       // and can just return here.
242       return p;
243     }
244   }
245 
246   // Primary allocation
247   p = allocate_inner(requested_word_size);
248 
249 #ifdef ASSERT
250   // Fence allocation

254     if (guard != NULL) {
255       // Ignore allocation errors for the fence to keep coding simple. If this
256       // happens (e.g. because right at this time we hit the Metaspace GC threshold)
257       // we miss adding this one fence. Not a big deal. Note that his would
258       // be pretty rare. Chances are much higher the primary allocation above
259       // would have already failed).
260       Fence* f = new(guard) Fence(_first_fence);
261       _first_fence = f;
262     }
263   }
264 #endif // ASSERT
265 
266   return p;
267 }
268 
269 // Allocate from the arena proper, once dictionary allocations and fencing are sorted out.
270 MetaWord* MetaspaceArena::allocate_inner(size_t requested_word_size) {
271 
272   assert_lock_strong(lock());
273 
274   const size_t raw_word_size = get_raw_word_size_for_requested_word_size(requested_word_size, _alignment_words);
275   MetaWord* p = NULL;
276   bool current_chunk_too_small = false;
277   bool commit_failure = false;
278 
279   if (current_chunk() != NULL) {
280 
281     // Attempt to satisfy the allocation from the current chunk.
282 
283     // If the current chunk is too small to hold the requested size, attempt to enlarge it.
284     // If that fails, retire the chunk.
285     if (current_chunk()->free_words() < raw_word_size) {
286       if (!attempt_enlarge_current_chunk(raw_word_size)) {
287         current_chunk_too_small = true;
288       } else {
289         DEBUG_ONLY(InternalStats::inc_num_chunks_enlarged();)
290         UL(debug, "enlarged chunk.");
291       }
292     }
293 
294     // Commit the chunk far enough to hold the requested word size. If that fails, we

354     UL2(trace, "after allocation: %u chunk(s), current:" METACHUNK_FULL_FORMAT,
355         _chunks.count(), METACHUNK_FULL_FORMAT_ARGS(current_chunk()));
356     UL2(trace, "returning " PTR_FORMAT ".", p2i(p));
357   }
358   return p;
359 }
360 
361 // Prematurely returns a metaspace allocation to the _block_freelists
362 // because it is not needed anymore (requires CLD lock to be active).
363 void MetaspaceArena::deallocate_locked(MetaWord* p, size_t word_size) {
364   assert_lock_strong(lock());
365   // At this point a current chunk must exist since we only deallocate if we did allocate before.
366   assert(current_chunk() != NULL, "stray deallocation?");
367   assert(is_valid_area(p, word_size),
368          "Pointer range not part of this Arena and cannot be deallocated: (" PTR_FORMAT ".." PTR_FORMAT ").",
369          p2i(p), p2i(p + word_size));
370 
371   UL2(trace, "deallocating " PTR_FORMAT ", word size: " SIZE_FORMAT ".",
372       p2i(p), word_size);
373 
374   size_t raw_word_size = get_raw_word_size_for_requested_word_size(word_size, _alignment_words);
375   add_allocation_to_fbl(p, raw_word_size);
376 
377   DEBUG_ONLY(verify_locked();)
378 }
379 
380 // Prematurely returns a metaspace allocation to the _block_freelists because it is not
381 // needed anymore.
382 void MetaspaceArena::deallocate(MetaWord* p, size_t word_size) {
383   MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
384   deallocate_locked(p, word_size);
385 }
386 
387 // Update statistics. This walks all in-use chunks.
388 void MetaspaceArena::add_to_statistics(ArenaStats* out) const {
389   MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
390 
391   for (const Metachunk* c = _chunks.first(); c != NULL; c = c->next()) {
392     InUseChunkStats& ucs = out->_stats[c->level()];
393     ucs._num++;
394     ucs._word_size += c->word_size();

468     assert(c->is_valid_committed_pointer(p) ==
469            c->is_valid_committed_pointer(p + word_size - 1), "range intersects");
470     found = c->is_valid_committed_pointer(p);
471   }
472   return found;
473 }
474 
475 #endif // ASSERT
476 
477 void MetaspaceArena::print_on(outputStream* st) const {
478   MutexLocker fcl(_lock, Mutex::_no_safepoint_check_flag);
479   print_on_locked(st);
480 }
481 
482 void MetaspaceArena::print_on_locked(outputStream* st) const {
483   assert_lock_strong(_lock);
484   st->print_cr("sm %s: %d chunks, total word size: " SIZE_FORMAT ", committed word size: " SIZE_FORMAT, _name,
485                _chunks.count(), _chunks.calc_word_size(), _chunks.calc_committed_word_size());
486   _chunks.print_on(st);
487   st->cr();
488   st->print_cr("growth-policy " PTR_FORMAT ", alignment %d, lock " PTR_FORMAT ", cm " PTR_FORMAT ", fbl " PTR_FORMAT,
489                 p2i(_growth_policy), _alignment_words * BytesPerWord, p2i(_lock), p2i(_chunk_manager), p2i(_fbl));
490 }
491 
492 } // namespace metaspace
493 
< prev index next >