1 /*
   2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2020 SAP SE. All rights reserved.
   4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5  *
   6  * This code is free software; you can redistribute it and/or modify it
   7  * under the terms of the GNU General Public License version 2 only, as
   8  * published by the Free Software Foundation.
   9  *
  10  * This code is distributed in the hope that it will be useful, but WITHOUT
  11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13  * version 2 for more details (a copy is included in the LICENSE file that
  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 
  28 #include "logging/log.hpp"
  29 #include "logging/logStream.hpp"
  30 #include "memory/metaspace/msAllocationGuard.hpp"
  31 #include "memory/metaspace/msArena.hpp"
  32 #include "memory/metaspace/msArenaGrowthPolicy.hpp"
  33 #include "memory/metaspace/msChunkManager.hpp"
  34 #include "memory/metaspace/msCommon.hpp"
  35 #include "memory/metaspace/msFreeBlocks.hpp"
  36 #include "memory/metaspace/msInternalStats.hpp"
  37 #include "memory/metaspace/msMetachunk.hpp"
  38 #include "memory/metaspace/msSettings.hpp"
  39 #include "memory/metaspace/msStatistics.hpp"
  40 #include "memory/metaspace/msVirtualSpaceList.hpp"
  41 #include "runtime/atomic.hpp"
  42 #include "runtime/init.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.
  54 chunklevel_t MetaspaceArena::next_chunk_level() const {
  55   const int growth_step = _chunks.count();
  56   return _growth_policy->get_level_at_step(growth_step);
  57 }
  58 
  59 // Given a chunk, add its remaining free committed space to the free block list.
  60 void MetaspaceArena::salvage_chunk(Metachunk* c) {
  61 
  62   if (Settings::handle_deallocations() == false) {
  63     return;
  64   }
  65 
  66   assert_lock_strong(lock());
  67 
  68   size_t remaining_words = c->free_below_committed_words();
  69 
  70   if (remaining_words > FreeBlocks::MinWordSize) {
  71 
  72     UL2(trace, "salvaging chunk " METACHUNK_FULL_FORMAT ".", METACHUNK_FULL_FORMAT_ARGS(c));
  73 
  74     MetaWord* ptr = c->allocate(remaining_words);
  75     assert(ptr != NULL, "Should have worked");
  76     _total_used_words_counter->increment_by(remaining_words);
  77 
  78     add_allocation_to_fbl(ptr, remaining_words);
  79 
  80     // After this operation: the chunk should have no free committed space left.
  81     assert(c->free_below_committed_words() == 0,
  82            "Salvaging chunk failed (chunk " METACHUNK_FULL_FORMAT ").",
  83            METACHUNK_FULL_FORMAT_ARGS(c));
  84 
  85   }
  86 
  87 }
  88 
  89 // Allocate a new chunk from the underlying chunk manager able to hold at least
  90 // requested word size.
  91 Metachunk* MetaspaceArena::allocate_new_chunk(size_t requested_word_size) {
  92 
  93   assert_lock_strong(lock());
  94 
  95   // Should this ever happen, we need to increase the maximum possible chunk size.
  96   guarantee(requested_word_size <= chunklevel::MAX_CHUNK_WORD_SIZE,
  97             "Requested size too large (" SIZE_FORMAT ") - max allowed size per allocation is " SIZE_FORMAT ".",
  98             requested_word_size, chunklevel::MAX_CHUNK_WORD_SIZE);
  99 
 100   const int growth_step = _chunks.count();
 101   const chunklevel_t max_level = chunklevel::level_fitting_word_size(requested_word_size);
 102   const chunklevel_t preferred_level = MIN2(max_level, next_chunk_level());
 103 
 104   Metachunk* c = _chunk_manager->get_chunk(preferred_level, max_level, requested_word_size);
 105   if (c == NULL) {
 106     return NULL;
 107   }
 108 
 109   assert(c->is_in_use(), "Wrong chunk state.");
 110   assert(c->free_below_committed_words() >= requested_word_size, "Chunk not committed");
 111 
 112   return c;
 113 
 114 }
 115 
 116 void MetaspaceArena::add_allocation_to_fbl(MetaWord* p, size_t word_size) {
 117   assert(Settings::handle_deallocations(), "Sanity");
 118   if (_fbl == NULL) {
 119     _fbl = new FreeBlocks(); // Create only on demand
 120   }
 121   _fbl->add_block(p, word_size);
 122 }
 123 
 124 MetaspaceArena::MetaspaceArena(ChunkManager* chunk_manager,
 125              const ArenaGrowthPolicy* growth_policy,
 126              Mutex* lock,
 127              SizeAtomicCounter* total_used_words_counter,
 128              const char* name)
 129 : _lock(lock),
 130   _chunk_manager(chunk_manager),
 131   _growth_policy(growth_policy),
 132   _chunks(),
 133   _fbl(NULL),
 134   _total_used_words_counter(total_used_words_counter),
 135   _name(name)
 136 {
 137   UL(debug, ": born.");
 138 
 139   // Update statistics
 140   InternalStats::inc_num_arena_births();
 141 }
 142 
 143 MetaspaceArena::~MetaspaceArena() {
 144 
 145   DEBUG_ONLY(verify();)
 146 
 147   MutexLocker fcl(lock(), Mutex::_no_safepoint_check_flag);
 148 
 149   MemRangeCounter return_counter;
 150 
 151   Metachunk* c = _chunks.first();
 152   Metachunk* c2 = NULL;
 153 
 154   while(c) {
 155     c2 = c->next();
 156     return_counter.add(c->used_words());
 157     DEBUG_ONLY(c->set_prev(NULL);)
 158     DEBUG_ONLY(c->set_next(NULL);)
 159     UL2(debug, "return chunk: " METACHUNK_FORMAT ".", METACHUNK_FORMAT_ARGS(c));
 160     _chunk_manager->return_chunk(c);
 161     // c may be invalid after return_chunk(c) was called. Don't access anymore.
 162     c = c2;
 163   }
 164 
 165   UL2(info, "returned %d chunks, total capacity " SIZE_FORMAT " words.",
 166       return_counter.count(), return_counter.total_size());
 167 
 168   _total_used_words_counter->decrement_by(return_counter.total_size());
 169 
 170   DEBUG_ONLY(chunk_manager()->verify();)
 171 
 172   delete _fbl;
 173 
 174   UL(debug, ": dies.");
 175 
 176   // Update statistics
 177   InternalStats::inc_num_arena_deaths();
 178 
 179 }
 180 
 181 // Attempt to enlarge the current chunk to make it large enough to hold at least
 182 //  requested_word_size additional words.
 183 //
 184 // On success, true is returned, false otherwise.
 185 bool MetaspaceArena::attempt_enlarge_current_chunk(size_t requested_word_size) {
 186 
 187   assert_lock_strong(lock());
 188 
 189   Metachunk* c = current_chunk();
 190   assert(c->free_words() < requested_word_size, "Sanity");
 191 
 192   // Not if chunk enlargment is switched off...
 193   if (Settings::enlarge_chunks_in_place() == false) {
 194     return false;
 195   }
 196 
 197   // ... nor if we are already a root chunk ...
 198   if (c->is_root_chunk()) {
 199     return false;
 200   }
 201 
 202   // ... nor if the combined size of chunk content and new content would bring us above the size of a root chunk ...
 203   if ((c->used_words() + requested_word_size) > metaspace::chunklevel::MAX_CHUNK_WORD_SIZE) {
 204     return false;
 205   }
 206 
 207   const chunklevel_t new_level =
 208       chunklevel::level_fitting_word_size(c->used_words() + requested_word_size);
 209   assert(new_level < c->level(), "Sanity");
 210 
 211   // Atm we only enlarge by one level (so, doubling the chunk in size). So, if the requested enlargement
 212   // would require the chunk to more than double in size, we bail. But this covers about 99% of all cases,
 213   // so this is good enough.
 214   if (new_level < c->level() - 1) {
 215     return false;
 216   }
 217 
 218   // This only works if chunk is the leader of its buddy pair (and also if buddy
 219   // is free and unsplit, but that we cannot check outside of metaspace lock).
 220   if (!c->is_leader()) {
 221     return false;
 222   }
 223 
 224   // If the size added to the chunk would be larger than allowed for the next growth step
 225   // dont enlarge.
 226   if (next_chunk_level() > c->level()) {
 227     return false;
 228   }
 229 
 230   bool success = _chunk_manager->attempt_enlarge_chunk(c);
 231 
 232   assert(success == false || c->free_words() >= requested_word_size, "Sanity");
 233 
 234   return success;
 235 
 236 }
 237 
 238 // Allocate memory from Metaspace.
 239 // 1) Attempt to allocate from the free block list.
 240 // 2) Attempt to allocate from the current chunk.
 241 // 3) Attempt to enlarge the current chunk in place if it is too small.
 242 // 4) Attempt to get a new chunk and allocate from that chunk.
 243 // At any point, if we hit a commit limit, we return NULL.
 244 MetaWord* MetaspaceArena::allocate(size_t requested_word_size) {
 245 
 246   MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
 247 
 248   UL2(trace, "requested " SIZE_FORMAT " words.", requested_word_size);
 249 
 250   MetaWord* p = NULL;
 251 
 252   const size_t raw_word_size = get_raw_word_size_for_requested_word_size(requested_word_size);
 253 
 254   // 1) Attempt to allocate from the free blocks list
 255   if (Settings::handle_deallocations() && _fbl != NULL && !_fbl->is_empty()) {
 256     p = _fbl->remove_block(raw_word_size);
 257     if (p != NULL) {
 258       DEBUG_ONLY(InternalStats::inc_num_allocs_from_deallocated_blocks();)
 259       UL2(trace, "taken from fbl (now: %d, " SIZE_FORMAT ").",
 260           _fbl->count(), _fbl->total_size());
 261       // Note: Space in the freeblock dictionary counts as already used (see retire_current_chunk()) -
 262       // that means that we do not modify any counters and therefore can skip the epilog.
 263       return p;
 264     }
 265   }
 266 
 267   bool current_chunk_too_small = false;
 268   bool commit_failure = false;
 269 
 270   if (current_chunk() != NULL) {
 271 
 272     // 2) Attempt to satisfy the allocation from the current chunk.
 273 
 274     // If the current chunk is too small to hold the requested size, attempt to enlarge it.
 275     // If that fails, retire the chunk.
 276     if (current_chunk()->free_words() < raw_word_size) {
 277       if (!attempt_enlarge_current_chunk(raw_word_size)) {
 278         current_chunk_too_small = true;
 279       } else {
 280         DEBUG_ONLY(InternalStats::inc_num_chunks_enlarged();)
 281         UL(debug, "enlarged chunk.");
 282       }
 283     }
 284 
 285     // Commit the chunk far enough to hold the requested word size. If that fails, we
 286     // hit a limit (either GC threshold or MaxMetaspaceSize). In that case retire the
 287     // chunk.
 288     if (!current_chunk_too_small) {
 289       if (!current_chunk()->ensure_committed_additional(raw_word_size)) {
 290         UL2(info, "commit failure (requested size: " SIZE_FORMAT ")", raw_word_size);
 291         commit_failure = true;
 292       }
 293     }
 294 
 295     // Allocate from the current chunk. This should work now.
 296     if (!current_chunk_too_small && !commit_failure) {
 297       p = current_chunk()->allocate(raw_word_size);
 298       assert(p != NULL, "Allocation from chunk failed.");
 299     }
 300 
 301   }
 302 
 303   if (p == NULL) {
 304 
 305     // If we are here, we either had no current chunk to begin with or it was deemed insufficient.
 306     assert(current_chunk() == NULL ||
 307            current_chunk_too_small || commit_failure, "Sanity");
 308 
 309     Metachunk* new_chunk = allocate_new_chunk(raw_word_size);
 310 
 311     if (new_chunk != NULL) {
 312 
 313       UL2(debug, "allocated new chunk " METACHUNK_FORMAT " for requested word size " SIZE_FORMAT ".",
 314           METACHUNK_FORMAT_ARGS(new_chunk), requested_word_size);
 315 
 316       assert(new_chunk->free_below_committed_words() >= raw_word_size, "Sanity");
 317 
 318       // We have a new chunk. Before making it the current chunk, retire the old one.
 319       if (current_chunk() != NULL) {
 320         salvage_chunk(current_chunk());
 321         DEBUG_ONLY(InternalStats::inc_num_chunks_retired();)
 322       }
 323 
 324       _chunks.add(new_chunk);
 325 
 326       // Now, allocate from that chunk. That should work.
 327       p = current_chunk()->allocate(raw_word_size);
 328       assert(p != NULL, "Allocation from chunk failed.");
 329 
 330     } else {
 331       UL2(info, "failed to allocate new chunk for requested word size " SIZE_FORMAT ".", requested_word_size);
 332     }
 333 
 334   }
 335 
 336 #ifdef ASSERT
 337   // When using allocation guards, establish a prefix.
 338   if (p != NULL && Settings::use_allocation_guard()) {
 339     p = establish_prefix(p, raw_word_size);
 340   }
 341 #endif
 342 
 343   if (p == NULL) {
 344     InternalStats::inc_num_allocs_failed_limit();
 345   } else {
 346     DEBUG_ONLY(InternalStats::inc_num_allocs();)
 347     _total_used_words_counter->increment_by(raw_word_size);
 348   }
 349 
 350   SOMETIMES(verify_locked();)
 351 
 352   if (p == NULL) {
 353     UL(info, "allocation failed, returned NULL.");
 354   } else {
 355     UL2(trace, "after allocation: %u chunk(s), current:" METACHUNK_FULL_FORMAT, _chunks.count(), METACHUNK_FULL_FORMAT_ARGS(current_chunk()));
 356     UL2(trace, "returning " PTR_FORMAT ".", p2i(p));
 357   }
 358 
 359   return p;
 360 
 361 }
 362 
 363 // Prematurely returns a metaspace allocation to the _block_freelists
 364 // because it is not needed anymore (requires CLD lock to be active).
 365 void MetaspaceArena::deallocate_locked(MetaWord* p, size_t word_size) {
 366 
 367   if (Settings::handle_deallocations() == false) {
 368     return;
 369   }
 370 
 371   assert_lock_strong(lock());
 372 
 373   // At this point a current chunk must exist since we only deallocate if we did allocate before.
 374   assert(current_chunk() != NULL, "stray deallocation?");
 375 
 376   assert(is_valid_area(p, word_size),
 377          "Pointer range not part of this Arena and cannot be deallocated: (" PTR_FORMAT ".." PTR_FORMAT ").",
 378          p2i(p), p2i(p + word_size));
 379 
 380   UL2(trace, "deallocating " PTR_FORMAT ", word size: " SIZE_FORMAT ".",
 381       p2i(p), word_size);
 382 
 383   size_t raw_word_size = get_raw_word_size_for_requested_word_size(word_size);
 384   add_allocation_to_fbl(p, raw_word_size);
 385 
 386   DEBUG_ONLY(verify_locked();)
 387 
 388 }
 389 
 390 // Prematurely returns a metaspace allocation to the _block_freelists because it is not
 391 // needed anymore.
 392 void MetaspaceArena::deallocate(MetaWord* p, size_t word_size) {
 393   MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
 394   deallocate_locked(p, word_size);
 395 }
 396 
 397 // Update statistics. This walks all in-use chunks.
 398 void MetaspaceArena::add_to_statistics(ArenaStats* out) const {
 399 
 400   MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
 401 
 402   for (const Metachunk* c = _chunks.first(); c != NULL; c = c->next()) {
 403     InUseChunkStats& ucs = out->_stats[c->level()];
 404     ucs._num++;
 405     ucs._word_size += c->word_size();
 406     ucs._committed_words += c->committed_words();
 407     ucs._used_words += c->used_words();
 408     // Note: for free and waste, we only count what's committed.
 409     if (c == current_chunk()) {
 410       ucs._free_words += c->free_below_committed_words();
 411     } else {
 412       ucs._waste_words += c->free_below_committed_words();
 413     }
 414   }
 415 
 416   if (_fbl != NULL) {
 417     out->_free_blocks_num += _fbl->count();
 418     out->_free_blocks_word_size += _fbl->total_size();
 419   }
 420 
 421   SOMETIMES(out->verify();)
 422 
 423 }
 424 
 425 // Convenience method to get the most important usage statistics.
 426 // For deeper analysis use add_to_statistics().
 427 void MetaspaceArena::usage_numbers(size_t* p_used_words, size_t* p_committed_words, size_t* p_capacity_words) const {
 428   MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
 429   size_t used = 0, comm = 0, cap = 0;
 430   for (const Metachunk* c = _chunks.first(); c != NULL; c = c->next()) {
 431     used += c->used_words();
 432     comm += c->committed_words();
 433     cap += c->word_size();
 434   }
 435   if (p_used_words != NULL) {
 436     *p_used_words = used;
 437   }
 438   if (p_committed_words != NULL) {
 439     *p_committed_words = comm;
 440   }
 441   if (p_capacity_words != NULL) {
 442     *p_capacity_words = cap;
 443   }
 444 }
 445 
 446 #ifdef ASSERT
 447 
 448 void MetaspaceArena::verify_locked() const {
 449 
 450   assert_lock_strong(lock());
 451 
 452   assert(_growth_policy != NULL && _chunk_manager != NULL, "Sanity");
 453 
 454   _chunks.verify();
 455 
 456   if (_fbl != NULL) {
 457     _fbl->verify();
 458   }
 459 
 460   // Verify guard zones of all allocations.
 461   SOMETIMES(
 462     if (Settings::use_allocation_guard()) {
 463       for (const Metachunk* c = _chunks.first(); c != NULL; c = c->next()) {
 464         const MetaWord* p = c->base();
 465         while (p < c->top()) {
 466           const Prefix* pp = (const Prefix*)p;
 467           pp->check();
 468           p += pp->_word_size;
 469         }
 470       }
 471     }
 472   )
 473 
 474 }
 475 
 476 void MetaspaceArena::verify() const {
 477 
 478   MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag);
 479   verify_locked();
 480 
 481 }
 482 
 483 // Returns true if the area indicated by pointer and size have actually been allocated
 484 // from this arena.
 485 bool MetaspaceArena::is_valid_area(MetaWord* p, size_t word_size) const {
 486   assert(p != NULL && word_size > 0, "Sanity");
 487   bool found = false;
 488   if (!found) {
 489     for (const Metachunk* c = _chunks.first(); c != NULL && !found; c = c->next()) {
 490       assert(c->is_valid_committed_pointer(p) ==
 491              c->is_valid_committed_pointer(p + word_size - 1), "range intersects");
 492       found = c->is_valid_committed_pointer(p);
 493     }
 494   }
 495   return found;
 496 }
 497 
 498 #endif // ASSERT
 499 
 500 void MetaspaceArena::print_on(outputStream* st) const {
 501   MutexLocker fcl(_lock, Mutex::_no_safepoint_check_flag);
 502   print_on_locked(st);
 503 }
 504 
 505 void MetaspaceArena::print_on_locked(outputStream* st) const {
 506   assert_lock_strong(_lock);
 507   st->print_cr("sm %s: %d chunks, total word size: " SIZE_FORMAT ", committed word size: " SIZE_FORMAT, _name,
 508                _chunks.count(), _chunks.calc_word_size(), _chunks.calc_committed_word_size());
 509   _chunks.print_on(st);
 510   st->cr();
 511   st->print_cr("growth-policy " PTR_FORMAT ", lock " PTR_FORMAT ", cm " PTR_FORMAT ", fbl " PTR_FORMAT,
 512                 p2i(_growth_policy), p2i(_lock), p2i(_chunk_manager), p2i(_fbl));
 513 }
 514 
 515 } // namespace metaspace
 516