src/hotspot/share/gc/cms/adaptiveFreeList.cpp
branchaefimov-dns-client-branch
changeset 59099 fcdb8e7ead8f
parent 58984 15e026239a6c
parent 59075 355f4f42dda5
child 59100 b92aac38b046
equal deleted inserted replaced
58984:15e026239a6c 59099:fcdb8e7ead8f
     1 /*
       
     2  * Copyright (c) 2012, 2018, 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 "gc/cms/adaptiveFreeList.hpp"
       
    27 #include "gc/cms/freeChunk.hpp"
       
    28 #include "gc/shared/collectedHeap.hpp"
       
    29 #include "memory/freeList.inline.hpp"
       
    30 #include "runtime/globals.hpp"
       
    31 #include "runtime/mutex.hpp"
       
    32 #include "runtime/orderAccess.hpp"
       
    33 #include "runtime/vmThread.hpp"
       
    34 
       
    35 template <>
       
    36 void AdaptiveFreeList<FreeChunk>::print_on(outputStream* st, const char* c) const {
       
    37   if (c != NULL) {
       
    38     st->print("%16s", c);
       
    39   } else {
       
    40     st->print(SIZE_FORMAT_W(16), size());
       
    41   }
       
    42   st->print("\t"
       
    43            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"
       
    44            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",
       
    45            bfr_surp(),             surplus(),             desired(),             prev_sweep(),           before_sweep(),
       
    46            count(),               coal_births(),          coal_deaths(),          split_births(),         split_deaths());
       
    47 }
       
    48 
       
    49 template <class Chunk>
       
    50 AdaptiveFreeList<Chunk>::AdaptiveFreeList() : FreeList<Chunk>(), _hint(0) {
       
    51   init_statistics();
       
    52 }
       
    53 
       
    54 template <class Chunk>
       
    55 void AdaptiveFreeList<Chunk>::initialize() {
       
    56   FreeList<Chunk>::initialize();
       
    57   set_hint(0);
       
    58   init_statistics(true /* split_birth */);
       
    59 }
       
    60 
       
    61 template <class Chunk>
       
    62 void AdaptiveFreeList<Chunk>::reset(size_t hint) {
       
    63   FreeList<Chunk>::reset();
       
    64   set_hint(hint);
       
    65 }
       
    66 
       
    67 template <class Chunk>
       
    68 void AdaptiveFreeList<Chunk>::init_statistics(bool split_birth) {
       
    69   _allocation_stats.initialize(split_birth);
       
    70 }
       
    71 
       
    72 template <class Chunk>
       
    73 size_t AdaptiveFreeList<Chunk>::get_better_size() {
       
    74 
       
    75   // A candidate chunk has been found.  If it is already under
       
    76   // populated and there is a hinT, REturn the hint().  Else
       
    77   // return the size of this chunk.
       
    78   if (surplus() <= 0) {
       
    79     if (hint() != 0) {
       
    80       return hint();
       
    81     } else {
       
    82       return size();
       
    83     }
       
    84   } else {
       
    85     // This list has a surplus so use it.
       
    86     return size();
       
    87   }
       
    88 }
       
    89 
       
    90 
       
    91 template <class Chunk>
       
    92 void AdaptiveFreeList<Chunk>::return_chunk_at_head(Chunk* chunk) {
       
    93   assert_proper_lock_protection();
       
    94   return_chunk_at_head(chunk, true);
       
    95 }
       
    96 
       
    97 template <class Chunk>
       
    98 void AdaptiveFreeList<Chunk>::return_chunk_at_head(Chunk* chunk, bool record_return) {
       
    99   FreeList<Chunk>::return_chunk_at_head(chunk, record_return);
       
   100 #ifdef ASSERT
       
   101   if (record_return) {
       
   102     increment_returned_bytes_by(size()*HeapWordSize);
       
   103   }
       
   104 #endif
       
   105 }
       
   106 
       
   107 template <class Chunk>
       
   108 void AdaptiveFreeList<Chunk>::return_chunk_at_tail(Chunk* chunk) {
       
   109   AdaptiveFreeList<Chunk>::return_chunk_at_tail(chunk, true);
       
   110 }
       
   111 
       
   112 template <class Chunk>
       
   113 void AdaptiveFreeList<Chunk>::return_chunk_at_tail(Chunk* chunk, bool record_return) {
       
   114   FreeList<Chunk>::return_chunk_at_tail(chunk, record_return);
       
   115 #ifdef ASSERT
       
   116   if (record_return) {
       
   117     increment_returned_bytes_by(size()*HeapWordSize);
       
   118   }
       
   119 #endif
       
   120 }
       
   121 
       
   122 #ifndef PRODUCT
       
   123 template <class Chunk>
       
   124 void AdaptiveFreeList<Chunk>::verify_stats() const {
       
   125   // The +1 of the LH comparand is to allow some "looseness" in
       
   126   // checking: we usually call this interface when adding a block
       
   127   // and we'll subsequently update the stats; we cannot update the
       
   128   // stats beforehand because in the case of the large-block BT
       
   129   // dictionary for example, this might be the first block and
       
   130   // in that case there would be no place that we could record
       
   131   // the stats (which are kept in the block itself).
       
   132   assert((_allocation_stats.prev_sweep() + _allocation_stats.split_births()
       
   133           + _allocation_stats.coal_births() + 1)   // Total Production Stock + 1
       
   134          >= (_allocation_stats.split_deaths() + _allocation_stats.coal_deaths()
       
   135              + (ssize_t)count()),                // Total Current Stock + depletion
       
   136          "FreeList " PTR_FORMAT " of size " SIZE_FORMAT
       
   137          " violates Conservation Principle: "
       
   138          "prev_sweep(" SIZE_FORMAT ")"
       
   139          " + split_births(" SIZE_FORMAT ")"
       
   140          " + coal_births(" SIZE_FORMAT ") + 1 >= "
       
   141          " split_deaths(" SIZE_FORMAT ")"
       
   142          " coal_deaths(" SIZE_FORMAT ")"
       
   143          " + count(" SSIZE_FORMAT ")",
       
   144          p2i(this), size(), _allocation_stats.prev_sweep(), _allocation_stats.split_births(),
       
   145          _allocation_stats.coal_births(), _allocation_stats.split_deaths(),
       
   146          _allocation_stats.coal_deaths(), count());
       
   147 }
       
   148 #endif
       
   149 
       
   150 // Needs to be after the definitions have been seen.
       
   151 template class AdaptiveFreeList<FreeChunk>;