< prev index next >

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

Print this page
rev 60538 : imported patch jep387-core.patch
   1 /*
   2  * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.

   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "memory/allocation.hpp"


  27 #include "memory/metaspace/metachunk.hpp"
  28 #include "memory/metaspace/occupancyMap.hpp"

  29 #include "memory/metaspace/virtualSpaceNode.hpp"


  30 #include "utilities/align.hpp"
  31 #include "utilities/copy.hpp"
  32 #include "utilities/debug.hpp"
  33 
  34 namespace metaspace {
  35 
  36 size_t Metachunk::object_alignment() {
  37   // Must align pointers and sizes to 8,
  38   // so that 64 bit types get correctly aligned.
  39   const size_t alignment = 8;
  40 
  41   // Make sure that the Klass alignment also agree.
  42   STATIC_ASSERT(alignment == (size_t)KlassAlignmentInBytes);
  43 
  44   return alignment;
  45 }
  46 
  47 size_t Metachunk::overhead() {
  48   return align_up(sizeof(Metachunk), object_alignment()) / BytesPerWord;
  49 }
  50 
  51 // Metachunk methods
  52 
  53 Metachunk::Metachunk(ChunkIndex chunktype, bool is_class, size_t word_size,
  54                      VirtualSpaceNode* container)
  55     : Metabase<Metachunk>(word_size),
  56     _container(container),
  57     _top(NULL),
  58     _sentinel(CHUNK_SENTINEL),
  59     _chunk_type(chunktype),
  60     _is_class(is_class),
  61     _origin(origin_normal),
  62     _use_count(0)
  63 {
  64   _top = initial_top();
  65   set_is_tagged_free(false);
  66 #ifdef ASSERT
  67   mangle(uninitMetaWordVal);
  68   verify();
  69 #endif
  70 }

















































  71 
  72 MetaWord* Metachunk::allocate(size_t word_size) {
  73   MetaWord* result = NULL;
  74   // If available, bump the pointer to allocate.
  75   if (free_word_size() >= word_size) {
  76     result = _top;
  77     _top = _top + word_size;

  78   }
  79   return result;








  80 }
  81 
  82 // _bottom points to the start of the chunk including the overhead.
  83 size_t Metachunk::used_word_size() const {
  84   return pointer_delta(_top, bottom(), sizeof(MetaWord));











  85 }
  86 
  87 size_t Metachunk::free_word_size() const {
  88   return pointer_delta(end(), _top, sizeof(MetaWord));











  89 }
  90 
  91 void Metachunk::print_on(outputStream* st) const {
  92   st->print_cr("Metachunk:"
  93                " bottom " PTR_FORMAT " top " PTR_FORMAT
  94                " end " PTR_FORMAT " size " SIZE_FORMAT " (%s)",
  95                p2i(bottom()), p2i(_top), p2i(end()), word_size(),
  96                chunk_size_name(get_chunk_type()));
  97   if (Verbose) {
  98     st->print_cr("    used " SIZE_FORMAT " free " SIZE_FORMAT,
  99                  used_word_size(), free_word_size());








 100   }
 101 }































 102 
 103 #ifdef ASSERT
 104 void Metachunk::mangle(juint word_value) {
 105   // Overwrite the payload of the chunk and not the links that
 106   // maintain list of chunks.
 107   HeapWord* start = (HeapWord*)initial_top();
 108   size_t size = word_size() - overhead();
 109   Copy::fill_to_words(start, size, word_value);
 110 }
 111 
 112 void Metachunk::verify() const {
 113   assert(is_valid_sentinel(), "Chunk " PTR_FORMAT ": sentinel invalid", p2i(this));
 114   const ChunkIndex chunk_type = get_chunk_type();
 115   assert(is_valid_chunktype(chunk_type), "Chunk " PTR_FORMAT ": Invalid chunk type.", p2i(this));
 116   if (chunk_type != HumongousIndex) {
 117     assert(word_size() == get_size_for_nonhumongous_chunktype(chunk_type, is_class()),
 118            "Chunk " PTR_FORMAT ": wordsize " SIZE_FORMAT " does not fit chunk type %s.",
 119            p2i(this), word_size(), chunk_size_name(chunk_type));
 120   }
 121   assert(is_valid_chunkorigin(get_origin()), "Chunk " PTR_FORMAT ": Invalid chunk origin.", p2i(this));
 122   assert(bottom() <= _top && _top <= (MetaWord*)end(),
 123          "Chunk " PTR_FORMAT ": Chunk top out of chunk bounds.", p2i(this));
 124 
 125   // For non-humongous chunks, starting address shall be aligned
 126   // to its chunk size. Humongous chunks start address is
 127   // aligned to specialized chunk size.
 128   const size_t required_alignment =
 129     (chunk_type != HumongousIndex ? word_size() : get_size_for_nonhumongous_chunktype(SpecializedIndex, is_class())) * sizeof(MetaWord);
 130   assert(is_aligned((address)this, required_alignment),
 131          "Chunk " PTR_FORMAT ": (size " SIZE_FORMAT ") not aligned to " SIZE_FORMAT ".",
 132          p2i(this), word_size() * sizeof(MetaWord), required_alignment);
 133 }
 134 
 135 #endif // ASSERT











































































































































 136 
 137 // Helper, returns a descriptive name for the given index.
 138 const char* chunk_size_name(ChunkIndex index) {
 139   switch (index) {
 140     case SpecializedIndex:
 141       return "specialized";
 142     case SmallIndex:
 143       return "small";
 144     case MediumIndex:
 145       return "medium";
 146     case HumongousIndex:
 147       return "humongous";
 148     default:
 149       return "Invalid index";
 150   }
 151 }
 152 
 153 #ifdef ASSERT
 154 void do_verify_chunk(Metachunk* chunk) {
 155   guarantee(chunk != NULL, "Sanity");
 156   // Verify chunk itself; then verify that it is consistent with the
 157   // occupany map of its containing node.
 158   chunk->verify();
 159   VirtualSpaceNode* const vsn = chunk->container();
 160   OccupancyMap* const ocmap = vsn->occupancy_map();
 161   ocmap->verify_for_chunk(chunk);












































































 162 }
 163 #endif
 164 
 165 void do_update_in_use_info_for_chunk(Metachunk* chunk, bool inuse) {
 166   chunk->set_is_tagged_free(!inuse);
 167   OccupancyMap* const ocmap = chunk->container()->occupancy_map();
 168   ocmap->set_region_in_use((MetaWord*)chunk, chunk->word_size(), inuse);























































 169 }
 170 
 171 } // namespace metaspace
 172 
   1 /*
   2  * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
   3  * Copyright (c) 2017, 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/metaspace/chunkLevel.hpp"
  30 #include "memory/metaspace/metachunk.hpp"
  31 #include "memory/metaspace/metaspaceCommon.hpp"
  32 #include "memory/metaspace/settings.hpp"
  33 #include "memory/metaspace/virtualSpaceNode.hpp"
  34 #include "runtime/mutexLocker.hpp"
  35 
  36 #include "utilities/align.hpp"
  37 #include "utilities/copy.hpp"
  38 #include "utilities/debug.hpp"
  39 
  40 namespace metaspace {
  41 
  42 // Return a single char presentation of the state ('f', 'u', 'd')
  43 char Metachunk::get_state_char() const {
  44   switch (_state) {
  45   case state_free:    return 'f';
  46   case state_in_use:  return 'u';
  47   case state_dead:    return 'd';
  48   }
  49   return '?';
  50 }
  51 




















  52 #ifdef ASSERT
  53 void Metachunk::assert_have_expand_lock() {
  54   assert_lock_strong(MetaspaceExpand_lock);

  55 }
  56 #endif
  57 
  58 // Commit uncommitted section of the chunk.
  59 // Fails if we hit a commit limit.
  60 bool Metachunk::commit_up_to(size_t new_committed_words) {
  61 
  62   // Please note:
  63   //
  64   // VirtualSpaceNode::ensure_range_is_committed(), when called over a range containing both committed and uncommitted parts,
  65   // will replace the whole range with a new mapping, thus erasing the existing content in the committed parts. Therefore
  66   // we must make sure never to call VirtualSpaceNode::ensure_range_is_committed() over a range containing live data.
  67   //
  68   // Luckily, this cannot happen by design. We have two cases:
  69   //
  70   // 1) chunks equal or larger than a commit granule.
  71   //    In this case, due to chunk geometry, the chunk should cover whole commit granules (in other words, a chunk equal or larger than
  72   //    a commit granule will never share a granule with a neighbor). That means whatever we commit or uncommit here does not affect
  73   //    neighboring chunks. We only have to take care not to re-commit used parts of ourself. We do this by moving the committed_words
  74   //    limit in multiple of commit granules.
  75   //
  76   // 2) chunks smaller than a commit granule.
  77   //    In this case, a chunk shares a single commit granule with its neighbors. But this never can be a problem:
  78   //    - Either the commit granule is already committed (and maybe the neighbors contain live data). In that case calling
  79   //      ensure_range_is_committed() will do nothing.
  80   //    - Or the commit granule is not committed, but in this case, the neighbors are uncommitted too and cannot contain live data.
  81 
  82 #ifdef ASSERT
  83   if (word_size() >= Settings::commit_granule_words()) {
  84     // case (1)
  85     assert(is_aligned(base(), Settings::commit_granule_bytes()) &&
  86            is_aligned(end(), Settings::commit_granule_bytes()),
  87            "Chunks larger than a commit granule must cover whole granules.");
  88     assert(is_aligned(_committed_words, Settings::commit_granule_words()),
  89            "The commit boundary must be aligned to commit granule size");
  90     assert(_used_words <= _committed_words, "Sanity");
  91   } else {
  92     // case (2)
  93     assert(_committed_words == 0 || _committed_words == word_size(), "Sanity");
  94   }
  95 #endif
  96 
  97   // We should hold the expand lock at this point.
  98   assert_lock_strong(MetaspaceExpand_lock);
  99 
 100   const size_t commit_from = _committed_words;
 101   const size_t commit_to =   MIN2(align_up(new_committed_words, Settings::commit_granule_words()), word_size());
 102 
 103   assert(commit_from >= used_words(), "Sanity");
 104   assert(commit_to <= word_size(), "Sanity");
 105 
 106   if (commit_to > commit_from) {
 107     log_debug(metaspace)("Chunk " METACHUNK_FORMAT ": attempting to move commit line to "
 108                          SIZE_FORMAT " words.", METACHUNK_FORMAT_ARGS(this), commit_to);
 109 
 110     if (!_vsnode->ensure_range_is_committed(base() + commit_from, commit_to - commit_from)) {
 111       DEBUG_ONLY(verify(true);)
 112       return false;
 113     }
 114   }
 115 
 116   // Remember how far we have committed.
 117   _committed_words = commit_to;
 118 
 119   DEBUG_ONLY(verify(true);)
 120 
 121   return true;
 122 
 123 }
 124 
 125 
 126 // Ensure that chunk is committed up to at least new_committed_words words.
 127 // Fails if we hit a commit limit.
 128 bool Metachunk::ensure_committed(size_t new_committed_words) {
 129 
 130   bool rc = true;
 131 
 132   if (new_committed_words > committed_words()) {
 133     MutexLocker cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
 134     rc = commit_up_to(new_committed_words);
 135   }
 136 
 137   return rc;
 138 
 139 }
 140 
 141 bool Metachunk::ensure_committed_locked(size_t new_committed_words) {
 142 
 143   // the .._locked() variant should be called if we own the lock already.
 144   assert_lock_strong(MetaspaceExpand_lock);
 145 
 146   bool rc = true;
 147 
 148   if (new_committed_words > committed_words()) {
 149     rc = commit_up_to(new_committed_words);
 150   }
 151 
 152   return rc;
 153 
 154 }
 155 
 156 // Uncommit chunk area. The area must be a common multiple of the
 157 // commit granule size (in other words, we cannot uncommit chunks smaller than
 158 // a commit granule size).
 159 void Metachunk::uncommit() {
 160   MutexLocker cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag);
 161   uncommit_locked();
 162 }
 163 
 164 void Metachunk::uncommit_locked() {
 165   // Only uncommit chunks which are free, have no used words set (extra precaution) and are equal or larger in size than a single commit granule.
 166   assert_lock_strong(MetaspaceExpand_lock);
 167   assert(_state == state_free && _used_words == 0 && word_size() >= Settings::commit_granule_words(),
 168          "Only free chunks equal or larger than commit granule size can be uncommitted "
 169          "(chunk " METACHUNK_FULL_FORMAT ").", METACHUNK_FULL_FORMAT_ARGS(this));
 170   if (word_size() >= Settings::commit_granule_words()) {
 171     _vsnode->uncommit_range(base(), word_size());
 172     _committed_words = 0;
 173   }
 174 }
 175 void Metachunk::set_committed_words(size_t v) {
 176   // Set committed words. Since we know that we only commit whole commit granules, we can round up v here.
 177   v = MIN2(align_up(v, Settings::commit_granule_words()), word_size());
 178  _committed_words = v;
 179 }
 180 
 181 
 182 // Allocate word_size words from this chunk (word_size must be aligned to
 183 //  allocation_alignment_words).
 184 //
 185 // Caller must make sure the chunk is both large enough and committed far enough
 186 // to hold the allocation. Will always work.
 187 //
 188 MetaWord* Metachunk::allocate(size_t request_word_size) {
 189 
 190   log_trace(metaspace)("Chunk " METACHUNK_FULL_FORMAT ": allocating " SIZE_FORMAT " words.",
 191                        METACHUNK_FULL_FORMAT_ARGS(this), request_word_size);
 192 
 193   // Caller must have made sure this works
 194   assert(free_words() >= request_word_size, "Chunk too small.");
 195   assert(free_below_committed_words() >= request_word_size, "Chunk not committed.");
 196 
 197   MetaWord* const p = top();
 198 
 199   _used_words += request_word_size;
 200 
 201   SOMETIMES(verify(false);)
 202 
 203   return p;
 204 
 205 }
 206 
 207 #ifdef ASSERT
 208 
 209 // Zap this structure.
 210 void Metachunk::zap_header(uint8_t c) {
 211   memset(this, c, sizeof(Metachunk));

























 212 }
 213 
 214 void Metachunk::fill_with_pattern(MetaWord pattern, size_t word_size) {
 215   assert(word_size <= committed_words(), "Sanity");
 216   for (size_t l = 0; l < word_size; l ++) {
 217     _base[l] = pattern;
 218   }
 219 }
 220 
 221 void Metachunk::check_pattern(MetaWord pattern, size_t word_size) {
 222   assert(word_size <= committed_words(), "Sanity");
 223   for (size_t l = 0; l < word_size; l ++) {
 224     assert(_base[l] == pattern,
 225            "chunk " METACHUNK_FULL_FORMAT ": pattern change at " PTR_FORMAT ": expected " UINTX_FORMAT " but got " UINTX_FORMAT ".",
 226            METACHUNK_FULL_FORMAT_ARGS(this), p2i(_base + l), (uintx)pattern, (uintx)_base[l]);
 227 
 228     ////////////////////////////////////////////
 229     // A double-headed list of Metachunks.
 230 
 231     class AbstractMetachunkList {
 232 
 233       Metachunk* _first;
 234       Metachunk* _last;
 235 
 236       // Number of chunks
 237       IntCounter _num;
 238 
 239     protected:
 240 
 241       AbstractMetachunkList() : _first(NULL), _last(NULL), _num() {}
 242 
 243       Metachunk* first() const { return _first; }
 244       int count() const { return _num.get(); }
 245 
 246       // Add chunk to the front of the list.
 247       void add_front(Metachunk* c) {
 248         if (_first == NULL) {
 249           assert(_last == NULL && _num.get() == 0, "Sanity");
 250           _first = _last = c;
 251           c->set_prev(NULL);
 252           c->set_next(NULL);
 253         } else {
 254           assert(_last != NULL && _num.get() > 0, "Sanity");
 255           c->set_next(_first);
 256           c->set_prev(NULL);
 257           _first->set_prev(c);
 258           _first = c;
 259         }
 260         _num.increment();
 261       }
 262 
 263       // Add chunk to the back of the list.
 264       void add_back(Metachunk* c) {
 265         if (_last == NULL) {
 266           assert(_first == NULL && _num.get() == 0, "Sanity");
 267           _last = _first = c;
 268           c->set_prev(NULL);
 269           c->set_next(NULL);
 270         } else {
 271           assert(_first != NULL && _num.get() > 0, "Sanity");
 272           c->set_next(NULL);
 273           c->set_prev(_last);
 274           _last->set_next(c);
 275           _last = c;
 276         }
 277         _num.increment();
 278       }
 279 
 280       // Remove chunk from the front of the list. Returns NULL if list is empty.
 281       Metachunk* remove_front() {
 282         Metachunk* c = NULL;
 283         if (_first == NULL) {
 284           assert(_last == NULL && _num.get() == 0, "Sanity");
 285         } else {
 286           c = _first;
 287           assert(c->prev() == NULL, "Sanity");
 288           if (_first == _last) {
 289             assert(_num.get() == 1, "Sanity");
 290             _first = _last = NULL;
 291           } else {
 292             assert(_num.get() > 1, "Sanity");
 293             _first = _first->next();
 294             _first->set_prev(NULL);
 295           }
 296           _num.decrement();
 297           c->set_next(NULL);
 298         }
 299         return c;
 300       }
 301 
 302       // Remove chunk from the back of the list. Returns NULL if list is empty.
 303       Metachunk* remove_back() {
 304         Metachunk* c = NULL;
 305         if (_last == NULL) {
 306           assert(_first == NULL && _num.get() == 0, "Sanity");
 307         } else {
 308           c = _last;
 309           assert(c->next() == NULL, "Sanity");
 310           if (_first == _last) {
 311             assert(_num.get() == 1, "Sanity");
 312             _first = _last = NULL;
 313           } else {
 314             assert(_num.get() > 1, "Sanity");
 315             _last = _last->prev();
 316             _last->set_next(NULL);
 317           }
 318           _num.decrement();
 319           c->set_prev(NULL);
 320         }
 321         return c;
 322       }
 323 
 324     public:
 325 
 326     #ifdef ASSERT
 327       bool contains(const Metachunk* c) const;
 328       void verify() const;
 329     #endif
 330 
 331       // Returns size, in words, of committed space of all chunks in this list.
 332       // Note: walks list.
 333       size_t committed_word_size() const {
 334         size_t l = 0;
 335         for (const Metachunk* c = _first; c != NULL; c = c->next()) {
 336           l += c->committed_words();
 337         }
 338         return l;
 339       }
 340 
 341       void print_on(outputStream* st) const;
 342 
 343     };
 344 
 345     class UnsortedMetachunkList : public AbstractMetachunkList {
 346     public:
 347 
 348 
 349 
 350 
 351 
 352     };
 353 
 354 













 355   }
 356 }
 357 
 358 
 359 // Verifies linking with neighbors in virtual space.
 360 // Can only be done under expand lock protection.
 361 void Metachunk::verify_neighborhood() const {
 362 
 363   assert_lock_strong(MetaspaceExpand_lock);
 364   assert(!is_dead(), "Do not call on dead chunks.");
 365 
 366   if (is_root_chunk()) {
 367 
 368     // Root chunks are all alone in the world.
 369     assert(next_in_vs() == NULL || prev_in_vs() == NULL, "Root chunks should have no neighbors");
 370 
 371   } else {
 372 
 373     // Non-root chunks have neighbors, at least one, possibly two.
 374 
 375     assert(next_in_vs() != NULL || prev_in_vs() != NULL,
 376            "A non-root chunk should have neighbors (chunk @" PTR_FORMAT
 377            ", base " PTR_FORMAT ", level " CHKLVL_FORMAT ".",
 378            p2i(this), p2i(base()), level());
 379 
 380     if (prev_in_vs() != NULL) {
 381       assert(prev_in_vs()->end() == base(),
 382              "Chunk " METACHUNK_FULL_FORMAT ": should be adjacent to predecessor: " METACHUNK_FULL_FORMAT ".",
 383              METACHUNK_FULL_FORMAT_ARGS(this), METACHUNK_FULL_FORMAT_ARGS(prev_in_vs()));
 384       assert(prev_in_vs()->next_in_vs() == this,
 385              "Chunk " METACHUNK_FULL_FORMAT ": broken link to left neighbor: " METACHUNK_FULL_FORMAT " (" PTR_FORMAT ").",
 386              METACHUNK_FULL_FORMAT_ARGS(this), METACHUNK_FULL_FORMAT_ARGS(prev_in_vs()), p2i(prev_in_vs()->next_in_vs()));
 387     }
 388 
 389     if (next_in_vs() != NULL) {
 390       assert(end() == next_in_vs()->base(),
 391              "Chunk " METACHUNK_FULL_FORMAT ": should be adjacent to successor: " METACHUNK_FULL_FORMAT ".",
 392              METACHUNK_FULL_FORMAT_ARGS(this), METACHUNK_FULL_FORMAT_ARGS(next_in_vs()));
 393       assert(next_in_vs()->prev_in_vs() == this,
 394              "Chunk " METACHUNK_FULL_FORMAT ": broken link to right neighbor: " METACHUNK_FULL_FORMAT " (" PTR_FORMAT ").",
 395              METACHUNK_FULL_FORMAT_ARGS(this), METACHUNK_FULL_FORMAT_ARGS(next_in_vs()), p2i(next_in_vs()->prev_in_vs()));
 396     }
 397 
 398     // One of the neighbors must be the buddy. It can be whole or splintered.
 399 
 400     // The chunk following us or preceeding us may be our buddy or a splintered part of it.
 401     Metachunk* buddy = is_leader() ? next_in_vs() : prev_in_vs();
 402 
 403     assert(buddy != NULL, "Missing neighbor.");
 404     assert(!buddy->is_dead(), "Invalid buddy state.");
 405 
 406     // This neighbor is either or buddy (same level) or a splinter of our buddy - hence
 407     // the level can never be smaller (aka the chunk size cannot be larger).
 408     assert(buddy->level() >= level(), "Wrong level.");
 409 
 410     if (buddy->level() == level()) {
 411 
 412       // If the buddy is of the same size as us, it is unsplintered.
 413       assert(buddy->is_leader() == !is_leader(),
 414              "Only one chunk can be leader in a pair");
 415 
 416       // When direct buddies are neighbors, one or both should be in use, otherwise they should
 417       // have been merged.
 418 
 419       // But since we call this verification function from internal functions where we are about to merge or just did split,
 420       // do not test this. We have RootChunkArea::verify_area_is_ideally_merged() for testing that.
 421 
 422       // assert(buddy->is_in_use() || is_in_use(), "incomplete merging?");
 423 
 424       if (is_leader()) {
 425         assert(buddy->base() == end(), "Sanity");
 426         assert(is_aligned(base(), word_size() * 2 * BytesPerWord), "Sanity");
 427       } else {
 428         assert(buddy->end() == base(), "Sanity");
 429         assert(is_aligned(buddy->base(), word_size() * 2 * BytesPerWord), "Sanity");
 430       }
 431 
 432     } else {
 433 
 434       // Buddy, but splintered, and this is a part of it.
 435       if (is_leader()) {
 436         assert(buddy->base() == end(), "Sanity");
 437       } else {
 438         assert(buddy->end() > (base() - word_size()), "Sanity");
 439       }
 440 
 441     }
 442   }
 443 }

 444 
 445 volatile MetaWord dummy = 0;
 446 
 447 void Metachunk::verify(bool slow) const {
 448 
 449   // Note. This should be called under CLD lock protection.
 450 
 451   // We can verify everything except the _prev_in_vs/_next_in_vs pair.
 452   // This is because neighbor chunks may be added concurrently, so we cannot rely
 453   //  on the content of _next_in_vs/_prev_in_vs unless we have the expand lock.
 454 
 455   assert(!is_dead(), "Do not call on dead chunks.");
 456 
 457   if (is_free()) {
 458     assert(used_words() == 0, "free chunks are not used.");
 459   }
 460 
 461   // Note: only call this on a life Metachunk.
 462   chunklevel::check_valid_level(level());
 463 
 464   assert(base() != NULL, "No base ptr");
 465 
 466   assert(committed_words() >= used_words(),
 467          "mismatch: committed: " SIZE_FORMAT ", used: " SIZE_FORMAT ".",
 468          committed_words(), used_words());
 469 
 470   assert(word_size() >= committed_words(),
 471          "mismatch: word_size: " SIZE_FORMAT ", committed: " SIZE_FORMAT ".",
 472          word_size(), committed_words());
 473 
 474   // Test base pointer
 475   assert(base() != NULL, "Base pointer NULL");
 476   assert(vsnode() != NULL, "No space");
 477   vsnode()->check_pointer(base());
 478 
 479   // Starting address shall be aligned to chunk size.
 480   const size_t required_alignment = word_size() * sizeof(MetaWord);
 481   assert_is_aligned(base(), required_alignment);
 482 
 483   // If slow, test the committed area
 484   if (slow && _committed_words > 0) {
 485     for (const MetaWord* p = _base; p < _base + _committed_words; p += os::vm_page_size()) {
 486       dummy = *p;
 487     }
 488     dummy = *(_base + _committed_words - 1);
 489   }
 490 
 491 }
 492 #endif // ASSERT
 493 
 494 void Metachunk::print_on(outputStream* st) const {
 495 
 496   // Note: must also work with invalid/random data. (e.g. do not call word_size())
 497   st->print("Chunk @" PTR_FORMAT ", state %c, base " PTR_FORMAT ", "
 498             "level " CHKLVL_FORMAT " (" SIZE_FORMAT " words), "
 499             "used " SIZE_FORMAT " words, committed " SIZE_FORMAT " words.",
 500             p2i(this), get_state_char(), p2i(base()), level(),
 501             (chunklevel::is_valid_level(level()) ? chunklevel::word_size_for_level(level()) : (size_t)-1),
 502             used_words(), committed_words());
 503 
 504 }
 505 
 506 } // namespace metaspace
 507 
< prev index next >