hotspot/src/share/vm/memory/freeList.cpp
changeset 14123 944e56f74fba
parent 13963 e5b53c306fb5
child 15482 470d0b0c09f1
equal deleted inserted replaced
14115:f5e31fb61738 14123:944e56f74fba
    23  */
    23  */
    24 
    24 
    25 #include "precompiled.hpp"
    25 #include "precompiled.hpp"
    26 #include "memory/freeBlockDictionary.hpp"
    26 #include "memory/freeBlockDictionary.hpp"
    27 #include "memory/freeList.hpp"
    27 #include "memory/freeList.hpp"
       
    28 #include "memory/metablock.hpp"
       
    29 #include "memory/metachunk.hpp"
    28 #include "memory/sharedHeap.hpp"
    30 #include "memory/sharedHeap.hpp"
    29 #include "runtime/globals.hpp"
    31 #include "runtime/globals.hpp"
    30 #include "runtime/mutex.hpp"
    32 #include "runtime/mutex.hpp"
    31 #include "runtime/vmThread.hpp"
    33 #include "runtime/vmThread.hpp"
    32 
    34 
    47   , _protecting_lock(NULL)
    49   , _protecting_lock(NULL)
    48 #endif
    50 #endif
    49 {
    51 {
    50   _size         = 0;
    52   _size         = 0;
    51   _count        = 0;
    53   _count        = 0;
    52   _hint         = 0;
       
    53   init_statistics();
       
    54 }
    54 }
    55 
    55 
    56 template <class Chunk>
    56 template <class Chunk>
    57 FreeList<Chunk>::FreeList(Chunk* fc) :
    57 FreeList<Chunk>::FreeList(Chunk* fc) :
    58   _head(fc), _tail(fc)
    58   _head(fc), _tail(fc)
    60   , _protecting_lock(NULL)
    60   , _protecting_lock(NULL)
    61 #endif
    61 #endif
    62 {
    62 {
    63   _size         = fc->size();
    63   _size         = fc->size();
    64   _count        = 1;
    64   _count        = 1;
    65   _hint         = 0;
    65 }
    66   init_statistics();
    66 
    67 #ifndef PRODUCT
    67 template <class Chunk>
    68   _allocation_stats.set_returned_bytes(size() * HeapWordSize);
    68 void FreeList<Chunk>::link_head(Chunk* v) {
    69 #endif
    69   assert_proper_lock_protection();
    70 }
    70   set_head(v);
    71 
    71   // If this method is not used (just set the head instead),
    72 template <class Chunk>
    72   // this check can be avoided.
    73 void FreeList<Chunk>::reset(size_t hint) {
    73   if (v != NULL) {
       
    74     v->link_prev(NULL);
       
    75   }
       
    76 }
       
    77 
       
    78 
       
    79 
       
    80 template <class Chunk>
       
    81 void FreeList<Chunk>::reset() {
       
    82   // Don't set the _size to 0 because this method is
       
    83   // used with a existing list that has a size but which has
       
    84   // been emptied.
       
    85   // Don't clear the _protecting_lock of an existing list.
    74   set_count(0);
    86   set_count(0);
    75   set_head(NULL);
    87   set_head(NULL);
    76   set_tail(NULL);
    88   set_tail(NULL);
    77   set_hint(hint);
    89 }
    78 }
    90 
    79 
    91 template <class Chunk>
    80 template <class Chunk>
    92 void FreeList<Chunk>::initialize() {
    81 void FreeList<Chunk>::init_statistics(bool split_birth) {
    93 #ifdef ASSERT
    82   _allocation_stats.initialize(split_birth);
    94   // Needed early because it might be checked in other initializing code.
    83 }
    95   set_protecting_lock(NULL);
    84 
    96 #endif
    85 template <class Chunk>
    97   reset();
    86 Chunk* FreeList<Chunk>::get_chunk_at_head() {
    98   set_size(0);
    87   assert_proper_lock_protection();
    99 }
    88   assert(head() == NULL || head()->prev() == NULL, "list invariant");
   100 
    89   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
   101 template <class Chunk_t>
    90   Chunk* fc = head();
   102 Chunk_t* FreeList<Chunk_t>::get_chunk_at_head() {
       
   103   assert_proper_lock_protection();
       
   104   assert(head() == NULL || head()->prev() == NULL, "list invariant");
       
   105   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
       
   106   Chunk_t* fc = head();
    91   if (fc != NULL) {
   107   if (fc != NULL) {
    92     Chunk* nextFC = fc->next();
   108     Chunk_t* nextFC = fc->next();
    93     if (nextFC != NULL) {
   109     if (nextFC != NULL) {
    94       // The chunk fc being removed has a "next".  Set the "next" to the
   110       // The chunk fc being removed has a "next".  Set the "next" to the
    95       // "prev" of fc.
   111       // "prev" of fc.
    96       nextFC->link_prev(NULL);
   112       nextFC->link_prev(NULL);
    97     } else { // removed tail of list
   113     } else { // removed tail of list
   195   if (oldHead == NULL) { // only chunk in list
   211   if (oldHead == NULL) { // only chunk in list
   196     assert(tail() == NULL, "inconsistent FreeList");
   212     assert(tail() == NULL, "inconsistent FreeList");
   197     link_tail(chunk);
   213     link_tail(chunk);
   198   }
   214   }
   199   increment_count(); // of # of chunks in list
   215   increment_count(); // of # of chunks in list
   200   DEBUG_ONLY(
       
   201     if (record_return) {
       
   202       increment_returned_bytes_by(size()*HeapWordSize);
       
   203     }
       
   204   )
       
   205   assert(head() == NULL || head()->prev() == NULL, "list invariant");
   216   assert(head() == NULL || head()->prev() == NULL, "list invariant");
   206   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
   217   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
   207   assert(head() == NULL || head()->size() == size(), "wrong item on list");
   218   assert(head() == NULL || head()->size() == size(), "wrong item on list");
   208   assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
   219   assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
   209 }
   220 }
   231     assert(head() == NULL, "inconsistent FreeList");
   242     assert(head() == NULL, "inconsistent FreeList");
   232     link_head(chunk);
   243     link_head(chunk);
   233   }
   244   }
   234   link_tail(chunk);
   245   link_tail(chunk);
   235   increment_count();  // of # of chunks in list
   246   increment_count();  // of # of chunks in list
   236   DEBUG_ONLY(
       
   237     if (record_return) {
       
   238       increment_returned_bytes_by(size()*HeapWordSize);
       
   239     }
       
   240   )
       
   241   assert(head() == NULL || head()->prev() == NULL, "list invariant");
   247   assert(head() == NULL || head()->prev() == NULL, "list invariant");
   242   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
   248   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
   243   assert(head() == NULL || head()->size() == size(), "wrong item on list");
   249   assert(head() == NULL || head()->size() == size(), "wrong item on list");
   244   assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
   250   assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
   245 }
   251 }
   271     fl->set_tail(NULL);
   277     fl->set_tail(NULL);
   272     fl->set_count(0);
   278     fl->set_count(0);
   273   }
   279   }
   274 }
   280 }
   275 
   281 
   276 // verify_chunk_in_free_list() is used to verify that an item is in this free list.
   282 // verify_chunk_in_free_lists() is used to verify that an item is in this free list.
   277 // It is used as a debugging aid.
   283 // It is used as a debugging aid.
   278 template <class Chunk>
   284 template <class Chunk>
   279 bool FreeList<Chunk>::verify_chunk_in_free_list(Chunk* fc) const {
   285 bool FreeList<Chunk>::verify_chunk_in_free_list(Chunk* fc) const {
   280   // This is an internal consistency check, not part of the check that the
   286   // This is an internal consistency check, not part of the check that the
   281   // chunk is in the free lists.
   287   // chunk is in the free lists.
   292   return false;
   298   return false;
   293 }
   299 }
   294 
   300 
   295 #ifndef PRODUCT
   301 #ifndef PRODUCT
   296 template <class Chunk>
   302 template <class Chunk>
   297 void FreeList<Chunk>::verify_stats() const {
       
   298   // The +1 of the LH comparand is to allow some "looseness" in
       
   299   // checking: we usually call this interface when adding a block
       
   300   // and we'll subsequently update the stats; we cannot update the
       
   301   // stats beforehand because in the case of the large-block BT
       
   302   // dictionary for example, this might be the first block and
       
   303   // in that case there would be no place that we could record
       
   304   // the stats (which are kept in the block itself).
       
   305   assert((_allocation_stats.prev_sweep() + _allocation_stats.split_births()
       
   306           + _allocation_stats.coal_births() + 1)   // Total Production Stock + 1
       
   307          >= (_allocation_stats.split_deaths() + _allocation_stats.coal_deaths()
       
   308              + (ssize_t)count()),                // Total Current Stock + depletion
       
   309          err_msg("FreeList " PTR_FORMAT " of size " SIZE_FORMAT
       
   310                  " violates Conservation Principle: "
       
   311                  "prev_sweep(" SIZE_FORMAT ")"
       
   312                  " + split_births(" SIZE_FORMAT ")"
       
   313                  " + coal_births(" SIZE_FORMAT ") + 1 >= "
       
   314                  " split_deaths(" SIZE_FORMAT ")"
       
   315                  " coal_deaths(" SIZE_FORMAT ")"
       
   316                  " + count(" SSIZE_FORMAT ")",
       
   317                  this, _size, _allocation_stats.prev_sweep(), _allocation_stats.split_births(),
       
   318                  _allocation_stats.split_births(), _allocation_stats.split_deaths(),
       
   319                  _allocation_stats.coal_deaths(), count()));
       
   320 }
       
   321 
       
   322 template <class Chunk>
       
   323 void FreeList<Chunk>::assert_proper_lock_protection_work() const {
   303 void FreeList<Chunk>::assert_proper_lock_protection_work() const {
   324   assert(_protecting_lock != NULL, "Don't call this directly");
   304   assert(protecting_lock() != NULL, "Don't call this directly");
   325   assert(ParallelGCThreads > 0, "Don't call this directly");
   305   assert(ParallelGCThreads > 0, "Don't call this directly");
   326   Thread* thr = Thread::current();
   306   Thread* thr = Thread::current();
   327   if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) {
   307   if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) {
   328     // assert that we are holding the freelist lock
   308     // assert that we are holding the freelist lock
   329   } else if (thr->is_GC_task_thread()) {
   309   } else if (thr->is_GC_task_thread()) {
   330     assert(_protecting_lock->owned_by_self(), "FreeList RACE DETECTED");
   310     assert(protecting_lock()->owned_by_self(), "FreeList RACE DETECTED");
   331   } else if (thr->is_Java_thread()) {
   311   } else if (thr->is_Java_thread()) {
   332     assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing");
   312     assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing");
   333   } else {
   313   } else {
   334     ShouldNotReachHere();  // unaccounted thread type?
   314     ShouldNotReachHere();  // unaccounted thread type?
   335   }
   315   }
   348 
   328 
   349 // Print the AllocationStats for the given free list. If the second argument
   329 // Print the AllocationStats for the given free list. If the second argument
   350 // to the call is a non-null string, it is printed in the first column;
   330 // to the call is a non-null string, it is printed in the first column;
   351 // otherwise, if the argument is null (the default), then the size of the
   331 // otherwise, if the argument is null (the default), then the size of the
   352 // (free list) block is printed in the first column.
   332 // (free list) block is printed in the first column.
   353 template <class Chunk>
   333 template <class Chunk_t>
   354 void FreeList<Chunk>::print_on(outputStream* st, const char* c) const {
   334 void FreeList<Chunk_t>::print_on(outputStream* st, const char* c) const {
   355   if (c != NULL) {
   335   if (c != NULL) {
   356     st->print("%16s", c);
   336     st->print("%16s", c);
   357   } else {
   337   } else {
   358     st->print(SIZE_FORMAT_W(16), size());
   338     st->print(SIZE_FORMAT_W(16), size());
   359   }
   339   }
   360   st->print("\t"
   340 }
   361            SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t"
   341 
   362            SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\n",
   342 template class FreeList<Metablock>;
   363            bfr_surp(),             surplus(),             desired(),             prev_sweep(),           before_sweep(),
   343 template class FreeList<Metachunk>;
   364            count(),               coal_births(),          coal_deaths(),          split_births(),         split_deaths());
       
   365 }
       
   366 
       
   367 #ifndef SERIALGC
   344 #ifndef SERIALGC
   368 // Needs to be after the definitions have been seen.
       
   369 template class FreeList<FreeChunk>;
   345 template class FreeList<FreeChunk>;
   370 #endif // SERIALGC
   346 #endif // SERIALGC