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 "memory/allocation.hpp"
  30 #include "memory/metaspace/msChunkHeaderPool.hpp"
  31 #include "memory/metaspace/msChunkManager.hpp"
  32 #include "memory/metaspace/msCommon.hpp"
  33 #include "memory/metaspace/msFreeChunkList.hpp"
  34 #include "memory/metaspace/msMetachunk.hpp"
  35 #include "memory/metaspace/msRootChunkArea.hpp"
  36 #include "runtime/mutexLocker.hpp"
  37 #include "utilities/debug.hpp"
  38 #include "utilities/globalDefinitions.hpp"
  39 
  40 namespace metaspace {
  41 
  42 RootChunkArea::RootChunkArea(const MetaWord* base)
  43   : _base(base), _first_chunk(NULL)
  44 {}
  45 
  46 RootChunkArea::~RootChunkArea() {
  47   // This is called when a VirtualSpaceNode is destructed (purged).
  48   // All chunks should be free of course. In fact, there should only
  49   // be one chunk, since all free chunks should have been merged.
  50   if (_first_chunk != NULL) {
  51     assert(_first_chunk->is_root_chunk() && _first_chunk->is_free(),
  52            "Cannot delete root chunk area if not all chunks are free.");
  53     ChunkHeaderPool::pool()->return_chunk_header(_first_chunk);
  54   }
  55 }
  56 
  57 // Initialize: allocate a root node and a root chunk header; return the
  58 // root chunk header. It will be partly initialized.
  59 // Note: this just allocates a memory-less header; memory itself is allocated inside VirtualSpaceNode.
  60 Metachunk* RootChunkArea::alloc_root_chunk_header(VirtualSpaceNode* node) {
  61 
  62   assert(_first_chunk == 0, "already have a root");
  63 
  64   Metachunk* c = ChunkHeaderPool::pool()->allocate_chunk_header();
  65   c->initialize(node, const_cast<MetaWord*>(_base), chunklevel::ROOT_CHUNK_LEVEL);
  66 
  67   _first_chunk = c;
  68 
  69   return c;
  70 
  71 }
  72 
  73 // Given a chunk c, split it recursively until you get a chunk of the given target_level.
  74 //
  75 // The resulting target chunk resides at the same address as the original chunk.
  76 // The resulting splinters are added to freelists.
  77 //
  78 // Returns pointer to the result chunk; the splitted-off chunks are added as
  79 //  free chunks to the freelists.
  80 void RootChunkArea::split(chunklevel_t target_level, Metachunk* c, FreeChunkListVector* freelists) {
  81 
  82   // Splitting a chunk once works like this:
  83   //
  84   // For a given chunk we want to split:
  85   // - increase the chunk level (which halves its size)
  86   // - (but leave base address as it is since it will be the leader of the newly
  87   //    created chunk pair)
  88   // - then create a new chunk header of the same level, set its memory range
  89   //   to cover the second halfof the old chunk.
  90   // - wire them up (prev_in_vs/next_in_vs)
  91   // - return the follower chunk as "splinter chunk" in the splinters array.
  92 
  93   // Doing this multiple times will create a new free splinter chunk for every
  94   // level we split:
  95   //
  96   // A  <- original chunk
  97   //
  98   // B B  <- split into two halves
  99   //
 100   // C C B  <- first half split again
 101   //
 102   // D D C B  <- first half split again ...
 103   //
 104 
 105   // As an optimization, since we usually do not split once but multiple times,
 106   // to not do each split separately, since we would have to wire up prev_in_vs/next_in_vs
 107   // on every level just to tear it open in the next level when we reintroduce a new
 108   // half chunk splinter.
 109   // Instead, just split split split and delay building up the double linked list of the
 110   // new chunks at the end of all splits.
 111 
 112   DEBUG_ONLY(check_pointer(c->base());)
 113   DEBUG_ONLY(c->verify();)
 114   assert(c->is_free(), "Can only split free chunks.");
 115 
 116   DEBUG_ONLY(chunklevel::check_valid_level(target_level));
 117   assert(target_level > c->level(), "Wrong target level");
 118 
 119   const chunklevel_t starting_level = c->level();
 120 
 121   while (c->level() < target_level) {
 122 
 123     log_trace(metaspace)("Splitting chunk: " METACHUNK_FULL_FORMAT ".", METACHUNK_FULL_FORMAT_ARGS(c));
 124 
 125     c->inc_level();
 126     Metachunk* splinter_chunk = ChunkHeaderPool::pool()->allocate_chunk_header();
 127     splinter_chunk->initialize(c->vsnode(), c->end(), c->level());
 128 
 129     // Fix committed words info: If over the half of the original chunk was
 130     // committed, committed area spills over into the follower chunk.
 131     const size_t old_committed_words = c->committed_words();
 132     if (old_committed_words > c->word_size()) {
 133       c->set_committed_words(c->word_size());
 134       splinter_chunk->set_committed_words(old_committed_words - c->word_size());
 135     } else {
 136       splinter_chunk->set_committed_words(0);
 137     }
 138 
 139     // Insert splinter chunk into vs list
 140     if (c->next_in_vs() != NULL) {
 141       c->next_in_vs()->set_prev_in_vs(splinter_chunk);
 142     }
 143     splinter_chunk->set_next_in_vs(c->next_in_vs());
 144     splinter_chunk->set_prev_in_vs(c);
 145     c->set_next_in_vs(splinter_chunk);
 146 
 147     log_trace(metaspace)(".. Result chunk: " METACHUNK_FULL_FORMAT ".", METACHUNK_FULL_FORMAT_ARGS(c));
 148     log_trace(metaspace)(".. Splinter chunk: " METACHUNK_FULL_FORMAT ".", METACHUNK_FULL_FORMAT_ARGS(splinter_chunk));
 149 
 150     // Add splinter to free lists
 151     freelists->add(splinter_chunk);
 152 
 153   }
 154 
 155   assert(c->level() == target_level, "Sanity");
 156 
 157   DEBUG_ONLY(verify();)
 158   DEBUG_ONLY(c->verify();)
 159 
 160 }
 161 
 162 // Given a chunk, attempt to merge it recursively with its neighboring chunks.
 163 //
 164 // If successful (merged at least once), returns address of
 165 // the merged chunk; NULL otherwise.
 166 //
 167 // The merged chunks are removed from the freelists.
 168 //
 169 // !!! Please note that if this method returns a non-NULL value, the
 170 // original chunk will be invalid and should not be accessed anymore! !!!
 171 Metachunk* RootChunkArea::merge(Metachunk* c, FreeChunkListVector* freelists) {
 172 
 173   // Note rules:
 174   //
 175   // - a chunk always has a buddy, unless it is a root chunk.
 176   // - In that buddy pair, a chunk is either leader or follower.
 177   // - a chunk's base address is always aligned at its size.
 178   // - if chunk is leader, its base address is also aligned to the size of the next
 179   //   lower level, at least. A follower chunk is not.
 180 
 181   // How we merge once:
 182   //
 183   // For a given chunk c, which has to be free and non-root, we do:
 184   // - find out if we are the leader or the follower chunk
 185   // - if we are leader, next_in_vs must be the follower; if we are follower,
 186   //   prev_in_vs must be the leader. Now we have the buddy chunk.
 187   // - However, if the buddy chunk itself is split (of a level higher than us)
 188   //   we cannot merge.
 189   // - we can only merge if the buddy is of the same level as we are and it is
 190   //   free.
 191   // - Then we merge by simply removing the follower chunk from the address range
 192   //   linked list (returning the now useless header to the pool) and decreasing
 193   //   the leader chunk level by one. That makes it double the size.
 194 
 195   // Example:
 196   // (lower case chunks are free, the * indicates the chunk we want to merge):
 197   //
 198   // ........................
 199   // d d*c   b       A           <- we return the second (d*) chunk...
 200   //
 201   // c*  c   b       A           <- we merge it with its predecessor and decrease its level...
 202   //
 203   // b*      b       A           <- we merge it again, since its new neighbor was free too...
 204   //
 205   // a*              A           <- we merge it again, since its new neighbor was free too...
 206   //
 207   // And we are done, since its new neighbor, (A), is not free. We would also be done
 208   // if the new neighbor itself is splintered.
 209 
 210   DEBUG_ONLY(check_pointer(c->base());)
 211   assert(!c->is_root_chunk(), "Cannot be merged further.");
 212   assert(c->is_free(), "Can only merge free chunks.");
 213 
 214   DEBUG_ONLY(c->verify();)
 215 
 216   log_trace(metaspace)("Attempting to merge chunk " METACHUNK_FORMAT ".", METACHUNK_FORMAT_ARGS(c));
 217 
 218   const chunklevel_t starting_level = c->level();
 219 
 220   bool stop = false;
 221   Metachunk* result = NULL;
 222 
 223   do {
 224 
 225     // First find out if this chunk is the leader of its pair
 226     const bool is_leader = c->is_leader();
 227 
 228     // Note: this is either our buddy or a splinter of the buddy.
 229     Metachunk* const buddy = c->is_leader() ? c->next_in_vs() : c->prev_in_vs();
 230     DEBUG_ONLY(buddy->verify();)
 231 
 232     // A buddy chunk must be of the same or higher level (so, same size or smaller)
 233     // never be larger.
 234     assert(buddy->level() >= c->level(), "Sanity");
 235 
 236     // Is this really my buddy (same level) or a splinter of it (higher level)?
 237     // Also, is it free?
 238     if (buddy->level() != c->level() || buddy->is_free() == false) {
 239 
 240       log_trace(metaspace)("cannot merge with chunk " METACHUNK_FORMAT ".", METACHUNK_FORMAT_ARGS(buddy));
 241 
 242       stop = true;
 243 
 244     } else {
 245 
 246       log_trace(metaspace)("will merge with chunk " METACHUNK_FORMAT ".", METACHUNK_FORMAT_ARGS(buddy));
 247 
 248       // We can merge with the buddy.
 249 
 250       // First, remove buddy from the chunk manager.
 251       assert(buddy->is_free(), "Sanity");
 252       freelists->remove(buddy);
 253 
 254       // Determine current leader and follower
 255       Metachunk* leader;
 256       Metachunk* follower;
 257       if (is_leader) {
 258         leader = c; follower = buddy;
 259       } else {
 260         leader = buddy; follower = c;
 261       }
 262 
 263       // Last checkpoint
 264       assert(leader->end() == follower->base() &&
 265              leader->level() == follower->level() &&
 266              leader->is_free() && follower->is_free(), "Sanity");
 267 
 268       // The new merged chunk is as far committed as possible (if leader
 269       // chunk is fully committed, as far as the follower chunk).
 270       size_t merged_committed_words = leader->committed_words();
 271       if (merged_committed_words == leader->word_size()) {
 272         merged_committed_words += follower->committed_words();
 273       }
 274 
 275       // Leader survives, follower chunk is freed. Remove follower from vslist ..
 276       leader->set_next_in_vs(follower->next_in_vs());
 277       if (follower->next_in_vs() != NULL) {
 278         follower->next_in_vs()->set_prev_in_vs(leader);
 279       }
 280 
 281       // .. and return follower chunk header to pool for reuse.
 282       ChunkHeaderPool::pool()->return_chunk_header(follower);
 283 
 284       // Leader level gets decreased (leader chunk doubles in size) but
 285       // base address stays the same.
 286       leader->dec_level();
 287 
 288       // set commit boundary
 289       leader->set_committed_words(merged_committed_words);
 290 
 291       // If the leader is now of root chunk size, stop merging
 292       if (leader->is_root_chunk()) {
 293         stop = true;
 294       }
 295 
 296       result = c = leader;
 297 
 298       DEBUG_ONLY(leader->verify();)
 299 
 300     }
 301 
 302   } while (!stop);
 303 
 304 #ifdef ASSERT
 305   verify();
 306   if (result != NULL) {
 307     result->verify();
 308   }
 309 #endif // ASSERT
 310 
 311   return result;
 312 
 313 }
 314 
 315 // Given a chunk c, which must be "in use" and must not be a root chunk, attempt to
 316 // enlarge it in place by claiming its trailing buddy.
 317 //
 318 // This will only work if c is the leader of the buddy pair and the trailing buddy is free.
 319 //
 320 // If successful, the follower chunk will be removed from the freelists, the leader chunk c will
 321 // double in size (level decreased by one).
 322 //
 323 // On success, true is returned, false otherwise.
 324 bool RootChunkArea::attempt_enlarge_chunk(Metachunk* c, FreeChunkListVector* freelists) {
 325 
 326   DEBUG_ONLY(check_pointer(c->base());)
 327   assert(!c->is_root_chunk(), "Cannot be merged further.");
 328 
 329   // There is no real reason for this limitation other than it is not
 330   // needed on free chunks since they should be merged already:
 331   assert(c->is_in_use(), "Can only enlarge in use chunks.");
 332 
 333   DEBUG_ONLY(c->verify();)
 334 
 335   if (!c->is_leader()) {
 336     return false;
 337   }
 338 
 339   // We are the leader, so the buddy must follow us.
 340   Metachunk* const buddy = c->next_in_vs();
 341   DEBUG_ONLY(buddy->verify();)
 342 
 343   // Of course buddy cannot be larger than us.
 344   assert(buddy->level() >= c->level(), "Sanity");
 345 
 346   // We cannot merge buddy in if it is not free...
 347   if (!buddy->is_free()) {
 348     return false;
 349   }
 350 
 351   // ... nor if it is splintered.
 352   if (buddy->level() != c->level()) {
 353     return false;
 354   }
 355 
 356   // Okay, lets enlarge c.
 357 
 358   log_trace(metaspace)("Enlarging chunk " METACHUNK_FULL_FORMAT " by merging in follower " METACHUNK_FULL_FORMAT ".",
 359                        METACHUNK_FULL_FORMAT_ARGS(c), METACHUNK_FULL_FORMAT_ARGS(buddy));
 360 
 361   // the enlarged c is as far committed as possible:
 362   size_t merged_committed_words = c->committed_words();
 363   if (merged_committed_words == c->word_size()) {
 364     merged_committed_words += buddy->committed_words();
 365   }
 366 
 367   // Remove buddy from vs list...
 368   Metachunk* successor = buddy->next_in_vs();
 369   if (successor != NULL) {
 370     successor->set_prev_in_vs(c);
 371   }
 372   c->set_next_in_vs(successor);
 373 
 374   // .. and from freelist ...
 375   freelists->remove(buddy);
 376 
 377   // .. and return its empty husk to the pool...
 378   ChunkHeaderPool::pool()->return_chunk_header(buddy);
 379 
 380   // Then decrease level of c.
 381   c->dec_level();
 382 
 383   // and correct committed words if needed.
 384   c->set_committed_words(merged_committed_words);
 385 
 386   log_debug(metaspace)("Enlarged chunk " METACHUNK_FULL_FORMAT ".", METACHUNK_FULL_FORMAT_ARGS(c));
 387 //  log_debug(metaspace)("Enlarged chunk " METACHUNK_FORMAT ".", METACHUNK_FORMAT_ARGS(c));
 388 
 389   DEBUG_ONLY(verify());
 390 
 391   return true;
 392 
 393 }
 394 
 395 // Returns true if this root chunk area is completely free:
 396 //  In that case, it should only contain one chunk (maximally merged, so a root chunk)
 397 //  and it should be free.
 398 bool RootChunkArea::is_free() const {
 399   return _first_chunk == NULL ||
 400       (_first_chunk->is_root_chunk() && _first_chunk->is_free());
 401 }
 402 
 403 #ifdef ASSERT
 404 
 405 #define assrt_(cond, ...) \
 406   if (!(cond)) { \
 407     fdStream errst(2); \
 408     this->print_on(&errst); \
 409     vmassert(cond, __VA_ARGS__); \
 410   }
 411 
 412 void RootChunkArea::verify() const {
 413 
 414   assert_lock_strong(MetaspaceExpand_lock);
 415   assert_is_aligned(_base, chunklevel::MAX_CHUNK_BYTE_SIZE);
 416 
 417   // Iterate thru all chunks in this area. They must be ordered correctly,
 418   // being adjacent to each other, and cover the complete area
 419   int num_chunk = 0;
 420 
 421   if (_first_chunk != NULL) {
 422 
 423     assrt_(_first_chunk->prev_in_vs() == NULL, "Sanity");
 424 
 425     const Metachunk* c = _first_chunk;
 426     const MetaWord* expected_next_base = _base;
 427     const MetaWord* const area_end = _base + word_size();
 428 
 429     while (c != NULL) {
 430 
 431       assrt_(c->is_free() || c->is_in_use(),
 432           "Chunk No. %d " METACHUNK_FORMAT " - invalid state.",
 433           num_chunk, METACHUNK_FORMAT_ARGS(c));
 434 
 435       assrt_(c->base() == expected_next_base,
 436              "Chunk No. %d " METACHUNK_FORMAT " - unexpected base.",
 437              num_chunk, METACHUNK_FORMAT_ARGS(c));
 438 
 439       assrt_(c->base() >= base() && c->end() <= end(),
 440              "chunk %d " METACHUNK_FORMAT " oob for this root area [" PTR_FORMAT ".." PTR_FORMAT ").",
 441              num_chunk, METACHUNK_FORMAT_ARGS(c), p2i(base()), p2i(end()));
 442 
 443       assrt_(is_aligned(c->base(), c->word_size()),
 444              "misaligned chunk %d " METACHUNK_FORMAT ".", num_chunk, METACHUNK_FORMAT_ARGS(c));
 445 
 446       c->verify_neighborhood();
 447       c->verify();
 448 
 449       expected_next_base = c->end();
 450       num_chunk++;
 451 
 452       c = c->next_in_vs();
 453 
 454     }
 455     assrt_(expected_next_base == _base + word_size(), "Sanity");
 456   }
 457 
 458 }
 459 
 460 void RootChunkArea::verify_area_is_ideally_merged() const {
 461 
 462   SOMETIMES(assert_lock_strong(MetaspaceExpand_lock);)
 463 
 464   int num_chunk = 0;
 465   for (const Metachunk* c = _first_chunk; c != NULL; c = c->next_in_vs()) {
 466     if (!c->is_root_chunk() && c->is_free()) {
 467       // If a chunk is free, it must not have a buddy which is also free, because
 468       // those chunks should have been merged.
 469       // In other words, a buddy shall be either in-use or splintered
 470       // (which in turn would mean part of it are in use).
 471       Metachunk* const buddy = c->is_leader() ? c->next_in_vs() : c->prev_in_vs();
 472       assrt_(buddy->is_in_use() || buddy->level() > c->level(),
 473              "Chunk No. %d " METACHUNK_FORMAT " : missed merge opportunity with neighbor " METACHUNK_FORMAT ".",
 474              num_chunk, METACHUNK_FORMAT_ARGS(c), METACHUNK_FORMAT_ARGS(buddy));
 475     }
 476     num_chunk++;
 477   }
 478 }
 479 
 480 #endif
 481 
 482 void RootChunkArea::print_on(outputStream* st) const {
 483 
 484   st->print(PTR_FORMAT ": ", p2i(base()));
 485   if (_first_chunk != NULL) {
 486     const Metachunk* c = _first_chunk;
 487     //                                    01234567890123
 488     const char* letters_for_levels_cap = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 489     const char* letters_for_levels =     "abcdefghijklmnopqrstuvwxyz";
 490     while (c != NULL) {
 491       const chunklevel_t l = c->level();
 492       if (l >= 0 && (size_t)l < strlen(letters_for_levels)) {
 493 //        c->print_on(st); st->cr();
 494         st->print("%c", c->is_free() ? letters_for_levels[c->level()] : letters_for_levels_cap[c->level()]);
 495       } else {
 496         // Obviously garbage, but lets not crash.
 497         st->print("?");
 498       }
 499       c = c->next_in_vs();
 500     }
 501   } else {
 502     st->print(" (no chunks)");
 503   }
 504   st->cr();
 505 
 506 }
 507 
 508 // Create an array of ChunkTree objects, all initialized to NULL, covering
 509 // a given memory range. Memory range must be a multiple of root chunk size.
 510 RootChunkAreaLUT::RootChunkAreaLUT(const MetaWord* base, size_t word_size)
 511   : _base(base),
 512     _num((int)(word_size / chunklevel::MAX_CHUNK_WORD_SIZE)),
 513     _arr(NULL)
 514 {
 515   assert_is_aligned(word_size, chunklevel::MAX_CHUNK_WORD_SIZE);
 516   _arr = NEW_C_HEAP_ARRAY(RootChunkArea, _num, mtClass);
 517   const MetaWord* this_base = _base;
 518   for (int i = 0; i < _num; i++) {
 519     RootChunkArea* rca = new(_arr + i) RootChunkArea(this_base);
 520     assert(rca == _arr + i, "Sanity");
 521     this_base += chunklevel::MAX_CHUNK_WORD_SIZE;
 522   }
 523 }
 524 
 525 RootChunkAreaLUT::~RootChunkAreaLUT() {
 526   for (int i = 0; i < _num; i++) {
 527     _arr[i].~RootChunkArea();
 528   }
 529   FREE_C_HEAP_ARRAY(RootChunkArea, _arr);
 530 }
 531 
 532 // Returns true if all areas in this area table are free (only contain free chunks).
 533 bool RootChunkAreaLUT::is_free() const {
 534   for (int i = 0; i < _num; i++) {
 535     if (!_arr[i].is_free()) {
 536       return false;
 537     }
 538   }
 539   return true;
 540 }
 541 
 542 #ifdef ASSERT
 543 
 544 void RootChunkAreaLUT::verify() const {
 545   for (int i = 0; i < _num; i++) {
 546     check_pointer(_arr[i].base());
 547     _arr[i].verify();
 548   }
 549 }
 550 
 551 #endif
 552 
 553 void RootChunkAreaLUT::print_on(outputStream* st) const {
 554   for (int i = 0; i < _num; i++) {
 555     st->print("%2d:", i);
 556     _arr[i].print_on(st);
 557   }
 558 }
 559 
 560 } // end: namespace metaspace