hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp
author jmasa
Thu, 07 Jan 2010 08:14:45 -0800
changeset 4577 18d854d28d4e
parent 4574 b2d5b0975515
child 5434 a2e785749780
permissions -rw-r--r--
6912018: CMS: guarantee(head() != 0,"The head of the list cannot be NULL") Summary: Block too small to split was not correctly putback to free lists. Reviewed-by: ysr
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
2105
347008ce7984 6814575: Update copyright year
xdono
parents: 1894
diff changeset
     2
 * Copyright 2001-2009 Sun Microsystems, Inc.  All Rights Reserved.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    19
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    20
 * CA 95054 USA or visit www.sun.com if you need additional information or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    21
 * have any questions.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
489c9b5090e2 Initial load
duke
parents:
diff changeset
    25
# include "incls/_precompiled.incl"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    26
# include "incls/_compactibleFreeListSpace.cpp.incl"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    27
489c9b5090e2 Initial load
duke
parents:
diff changeset
    28
/////////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
    29
//// CompactibleFreeListSpace
489c9b5090e2 Initial load
duke
parents:
diff changeset
    30
/////////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
    31
489c9b5090e2 Initial load
duke
parents:
diff changeset
    32
// highest ranked  free list lock rank
489c9b5090e2 Initial load
duke
parents:
diff changeset
    33
int CompactibleFreeListSpace::_lockRank = Mutex::leaf + 3;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
// Constructor
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
  MemRegion mr, bool use_adaptive_freelists,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
  FreeBlockDictionary::DictionaryChoice dictionaryChoice) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
  _dictionaryChoice(dictionaryChoice),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
  _adaptive_freelists(use_adaptive_freelists),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
  _bt(bs, mr),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
  // free list locks are in the range of values taken by _lockRank
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
  // This range currently is [_leaf+2, _leaf+3]
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
  // Note: this requires that CFLspace c'tors
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
  // are called serially in the order in which the locks are
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
  // are acquired in the program text. This is true today.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
  _freelistLock(_lockRank--, "CompactibleFreeListSpace._lock", true),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
  _parDictionaryAllocLock(Mutex::leaf - 1,  // == rank(ExpandHeap_lock) - 1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
                          "CompactibleFreeListSpace._dict_par_lock", true),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
  _rescan_task_size(CardTableModRefBS::card_size_in_words * BitsPerWord *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
                    CMSRescanMultiple),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
  _marking_task_size(CardTableModRefBS::card_size_in_words * BitsPerWord *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
                    CMSConcMarkMultiple),
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
  _collector(NULL)
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
  _bt.set_space(this);
971
f0b20be4165d 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 613
diff changeset
    57
  initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
  // We have all of "mr", all of which we place in the dictionary
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
  // as one big chunk. We'll need to decide here which of several
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
  // possible alternative dictionary implementations to use. For
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
  // now the choice is easy, since we have only one working
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
  // implementation, namely, the simple binary tree (splaying
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
  // temporarily disabled).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
  switch (dictionaryChoice) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
    case FreeBlockDictionary::dictionarySplayTree:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
    case FreeBlockDictionary::dictionarySkipList:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
    default:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
      warning("dictionaryChoice: selected option not understood; using"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
              " default BinaryTreeDictionary implementation instead.");
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
    70
    case FreeBlockDictionary::dictionaryBinaryTree:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
      _dictionary = new BinaryTreeDictionary(mr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
  assert(_dictionary != NULL, "CMS dictionary initialization");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
  // The indexed free lists are initially all empty and are lazily
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
  // filled in on demand. Initialize the array elements to NULL.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
  initializeIndexedFreeListArray();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
  // Not using adaptive free lists assumes that allocation is first
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
  // from the linAB's.  Also a cms perm gen which can be compacted
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
  // has to have the klass's klassKlass allocated at a lower
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
  // address in the heap than the klass so that the klassKlass is
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
  // moved to its new location before the klass is moved.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
  // Set the _refillSize for the linear allocation blocks
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
  if (!use_adaptive_freelists) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
    FreeChunk* fc = _dictionary->getChunk(mr.word_size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
    // The small linAB initially has all the space and will allocate
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
    // a chunk of any size.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
    HeapWord* addr = (HeapWord*) fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
    _smallLinearAllocBlock.set(addr, fc->size() ,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
      1024*SmallForLinearAlloc, fc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
    // Note that _unallocated_block is not updated here.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
    // Allocations from the linear allocation block should
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
    // update it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
    _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
                               SmallForLinearAlloc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
  // CMSIndexedFreeListReplenish should be at least 1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
  CMSIndexedFreeListReplenish = MAX2((uintx)1, CMSIndexedFreeListReplenish);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
  _promoInfo.setSpace(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
  if (UseCMSBestFit) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
    _fitStrategy = FreeBlockBestFitFirst;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
    _fitStrategy = FreeBlockStrategyNone;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
  checkFreeListConsistency();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
  // Initialize locks for parallel case.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
  if (ParallelGCThreads > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
    for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
      _indexedFreeListParLocks[i] = new Mutex(Mutex::leaf - 1, // == ExpandHeap_lock - 1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
                                              "a freelist par lock",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
                                              true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
      if (_indexedFreeListParLocks[i] == NULL)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
        vm_exit_during_initialization("Could not allocate a par lock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
      DEBUG_ONLY(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
        _indexedFreeList[i].set_protecting_lock(_indexedFreeListParLocks[i]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
      )
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
    _dictionary->set_par_lock(&_parDictionaryAllocLock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
// Like CompactibleSpace forward() but always calls cross_threshold() to
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
// update the block offset table.  Removed initialize_threshold call because
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
// CFLS does not use a block offset array for contiguous spaces.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
HeapWord* CompactibleFreeListSpace::forward(oop q, size_t size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
                                    CompactPoint* cp, HeapWord* compact_top) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
  // q is alive
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
  // First check if we should switch compaction space
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
  assert(this == cp->space, "'this' should be current compaction space.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
  size_t compaction_max_size = pointer_delta(end(), compact_top);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
  assert(adjustObjectSize(size) == cp->space->adjust_object_size_v(size),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
    "virtual adjustObjectSize_v() method is not correct");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
  size_t adjusted_size = adjustObjectSize(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
  assert(compaction_max_size >= MinChunkSize || compaction_max_size == 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
         "no small fragments allowed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
  assert(minimum_free_block_size() == MinChunkSize,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
         "for de-virtualized reference below");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
  // Can't leave a nonzero size, residual fragment smaller than MinChunkSize
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
  if (adjusted_size + MinChunkSize > compaction_max_size &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
      adjusted_size != compaction_max_size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
    do {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
      // switch to next compaction space
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
      cp->space->set_compaction_top(compact_top);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
      cp->space = cp->space->next_compaction_space();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
      if (cp->space == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
        cp->gen = GenCollectedHeap::heap()->prev_gen(cp->gen);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
        assert(cp->gen != NULL, "compaction must succeed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
        cp->space = cp->gen->first_compaction_space();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
        assert(cp->space != NULL, "generation must have a first compaction space");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
      compact_top = cp->space->bottom();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
      cp->space->set_compaction_top(compact_top);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
      // The correct adjusted_size may not be the same as that for this method
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
      // (i.e., cp->space may no longer be "this" so adjust the size again.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
      // Use the virtual method which is not used above to save the virtual
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
      // dispatch.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
      adjusted_size = cp->space->adjust_object_size_v(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
      compaction_max_size = pointer_delta(cp->space->end(), compact_top);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
      assert(cp->space->minimum_free_block_size() == 0, "just checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
    } while (adjusted_size > compaction_max_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
  // store the forwarding pointer into the mark word
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
  if ((HeapWord*)q != compact_top) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
    q->forward_to(oop(compact_top));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
    assert(q->is_gc_marked(), "encoding the pointer should preserve the mark");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
    // if the object isn't moving we can just set the mark to the default
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
    // mark and handle it specially later on.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
    q->init_mark();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
    assert(q->forwardee() == NULL, "should be forwarded to NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
   177
  VALIDATE_MARK_SWEEP_ONLY(MarkSweep::register_live_oop(q, adjusted_size));
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
  compact_top += adjusted_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
  // we need to update the offset table so that the beginnings of objects can be
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
  // found during scavenge.  Note that we are updating the offset table based on
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
  // where the object will be once the compaction phase finishes.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
  // Always call cross_threshold().  A contiguous space can only call it when
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
  // the compaction_top exceeds the current threshold but not for an
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
  // non-contiguous space.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
  cp->threshold =
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
    cp->space->cross_threshold(compact_top - adjusted_size, compact_top);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
  return compact_top;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
// A modified copy of OffsetTableContigSpace::cross_threshold() with _offsets -> _bt
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
// and use of single_block instead of alloc_block.  The name here is not really
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
// appropriate - maybe a more general name could be invented for both the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
// contiguous and noncontiguous spaces.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
HeapWord* CompactibleFreeListSpace::cross_threshold(HeapWord* start, HeapWord* the_end) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
  _bt.single_block(start, the_end);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
  return end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
// Initialize them to NULL.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
void CompactibleFreeListSpace::initializeIndexedFreeListArray() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
  for (size_t i = 0; i < IndexSetSize; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
    // Note that on platforms where objects are double word aligned,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
    // the odd array elements are not used.  It is convenient, however,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
    // to map directly from the object size to the array element.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
    _indexedFreeList[i].reset(IndexSetSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
    _indexedFreeList[i].set_size(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
    assert(_indexedFreeList[i].count() == 0, "reset check failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
    assert(_indexedFreeList[i].head() == NULL, "reset check failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
    assert(_indexedFreeList[i].tail() == NULL, "reset check failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
    assert(_indexedFreeList[i].hint() == IndexSetSize, "reset check failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
void CompactibleFreeListSpace::resetIndexedFreeListArray() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
  for (int i = 1; i < IndexSetSize; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
    assert(_indexedFreeList[i].size() == (size_t) i,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
      "Indexed free list sizes are incorrect");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
    _indexedFreeList[i].reset(IndexSetSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
    assert(_indexedFreeList[i].count() == 0, "reset check failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
    assert(_indexedFreeList[i].head() == NULL, "reset check failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
    assert(_indexedFreeList[i].tail() == NULL, "reset check failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
    assert(_indexedFreeList[i].hint() == IndexSetSize, "reset check failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   228
489c9b5090e2 Initial load
duke
parents:
diff changeset
   229
void CompactibleFreeListSpace::reset(MemRegion mr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   230
  resetIndexedFreeListArray();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   231
  dictionary()->reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   232
  if (BlockOffsetArrayUseUnallocatedBlock) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   233
    assert(end() == mr.end(), "We are compacting to the bottom of CMS gen");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   234
    // Everything's allocated until proven otherwise.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   235
    _bt.set_unallocated_block(end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
  if (!mr.is_empty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
    assert(mr.word_size() >= MinChunkSize, "Chunk size is too small");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
    _bt.single_block(mr.start(), mr.word_size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   240
    FreeChunk* fc = (FreeChunk*) mr.start();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
    fc->setSize(mr.word_size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
    if (mr.word_size() >= IndexSetSize ) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   243
      returnChunkToDictionary(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   244
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   245
      _bt.verify_not_unallocated((HeapWord*)fc, fc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
      _indexedFreeList[mr.word_size()].returnChunkAtHead(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   247
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   248
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   249
  _promoInfo.reset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   250
  _smallLinearAllocBlock._ptr = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   251
  _smallLinearAllocBlock._word_size = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   252
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   253
489c9b5090e2 Initial load
duke
parents:
diff changeset
   254
void CompactibleFreeListSpace::reset_after_compaction() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   255
  // Reset the space to the new reality - one free chunk.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
  MemRegion mr(compaction_top(), end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
  reset(mr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
  // Now refill the linear allocation block(s) if possible.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
  if (_adaptive_freelists) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
    refillLinearAllocBlocksIfNeeded();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   262
    // Place as much of mr in the linAB as we can get,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
    // provided it was big enough to go into the dictionary.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
    FreeChunk* fc = dictionary()->findLargestDict();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
    if (fc != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
      assert(fc->size() == mr.word_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
             "Why was the chunk broken up?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
      removeChunkFromDictionary(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
      HeapWord* addr = (HeapWord*) fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
      _smallLinearAllocBlock.set(addr, fc->size() ,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
        1024*SmallForLinearAlloc, fc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
      // Note that _unallocated_block is not updated here.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
// Walks the entire dictionary, returning a coterminal
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
// chunk, if it exists. Use with caution since it involves
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
// a potentially complete walk of a potentially large tree.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
FreeChunk* CompactibleFreeListSpace::find_chunk_at_end() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
  assert_lock_strong(&_freelistLock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
  return dictionary()->find_chunk_ends_at(end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
void CompactibleFreeListSpace::initializeIndexedFreeListArrayReturnedBytes() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
  for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
    _indexedFreeList[i].allocation_stats()->set_returnedBytes(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
size_t CompactibleFreeListSpace::sumIndexedFreeListArrayReturnedBytes() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
  size_t sum = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
  for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
    sum += _indexedFreeList[i].allocation_stats()->returnedBytes();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
  return sum;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
size_t CompactibleFreeListSpace::totalCountInIndexedFreeLists() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
  size_t count = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
  for (int i = MinChunkSize; i < IndexSetSize; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
    debug_only(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
      ssize_t total_list_count = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
      for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   309
         fc = fc->next()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
        total_list_count++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
      assert(total_list_count ==  _indexedFreeList[i].count(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
        "Count in list is incorrect");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
    )
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
    count += _indexedFreeList[i].count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   316
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   317
  return count;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   318
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   319
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
size_t CompactibleFreeListSpace::totalCount() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   321
  size_t num = totalCountInIndexedFreeLists();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   322
  num +=  dictionary()->totalCount();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   323
  if (_smallLinearAllocBlock._word_size != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
    num++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
  return num;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   328
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   329
489c9b5090e2 Initial load
duke
parents:
diff changeset
   330
bool CompactibleFreeListSpace::is_free_block(const HeapWord* p) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   331
  FreeChunk* fc = (FreeChunk*) p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
  return fc->isFree();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   333
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
size_t CompactibleFreeListSpace::used() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
  return capacity() - free();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
size_t CompactibleFreeListSpace::free() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
  // "MT-safe, but not MT-precise"(TM), if you will: i.e.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
  // if you do this while the structures are in flux you
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
  // may get an approximate answer only; for instance
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
  // because there is concurrent allocation either
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
  // directly by mutators or for promotion during a GC.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
  // It's "MT-safe", however, in the sense that you are guaranteed
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
  // not to crash and burn, for instance, because of walking
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
  // pointers that could disappear as you were walking them.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
  // The approximation is because the various components
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
  // that are read below are not read atomically (and
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
  // further the computation of totalSizeInIndexedFreeLists()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
  // is itself a non-atomic computation. The normal use of
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
  // this is during a resize operation at the end of GC
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
  // and at that time you are guaranteed to get the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
  // correct actual value. However, for instance, this is
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
  // also read completely asynchronously by the "perf-sampler"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
  // that supports jvmstat, and you are apt to see the values
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
  // flicker in such cases.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
  assert(_dictionary != NULL, "No _dictionary?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
  return (_dictionary->totalChunkSize(DEBUG_ONLY(freelistLock())) +
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
          totalSizeInIndexedFreeLists() +
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
          _smallLinearAllocBlock._word_size) * HeapWordSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
size_t CompactibleFreeListSpace::max_alloc_in_words() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
  assert(_dictionary != NULL, "No _dictionary?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
  size_t res = _dictionary->maxChunkSize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
  res = MAX2(res, MIN2(_smallLinearAllocBlock._word_size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
                       (size_t) SmallForLinearAlloc - 1));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
  // XXX the following could potentially be pretty slow;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
  // should one, pesimally for the rare cases when res
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
  // caclulated above is less than IndexSetSize,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
  // just return res calculated above? My reasoning was that
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
  // those cases will be so rare that the extra time spent doesn't
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
  // really matter....
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
  // Note: do not change the loop test i >= res + IndexSetStride
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
  // to i > res below, because i is unsigned and res may be zero.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
  for (size_t i = IndexSetSize - 1; i >= res + IndexSetStride;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
       i -= IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
    if (_indexedFreeList[i].head() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
      assert(_indexedFreeList[i].count() != 0, "Inconsistent FreeList");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
      return i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   386
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   387
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   388
void CompactibleFreeListSpace::print_indexed_free_lists(outputStream* st)
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   389
const {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   390
  reportIndexedFreeListStatistics();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   391
  gclog_or_tty->print_cr("Layout of Indexed Freelists");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   392
  gclog_or_tty->print_cr("---------------------------");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   393
  FreeList::print_labels_on(st, "size");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   394
  for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   395
    _indexedFreeList[i].print_on(gclog_or_tty);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   396
    for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   397
         fc = fc->next()) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   398
      gclog_or_tty->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ")  %s",
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   399
                          fc, (HeapWord*)fc + i,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   400
                          fc->cantCoalesce() ? "\t CC" : "");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   401
    }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   402
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   403
}
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   404
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   405
void CompactibleFreeListSpace::print_promo_info_blocks(outputStream* st)
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   406
const {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   407
  _promoInfo.print_on(st);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   408
}
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   409
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   410
void CompactibleFreeListSpace::print_dictionary_free_lists(outputStream* st)
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   411
const {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   412
  _dictionary->reportStatistics();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   413
  st->print_cr("Layout of Freelists in Tree");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   414
  st->print_cr("---------------------------");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   415
  _dictionary->print_free_lists(st);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   416
}
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   417
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   418
class BlkPrintingClosure: public BlkClosure {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   419
  const CMSCollector*             _collector;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   420
  const CompactibleFreeListSpace* _sp;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   421
  const CMSBitMap*                _live_bit_map;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   422
  const bool                      _post_remark;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   423
  outputStream*                   _st;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   424
public:
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   425
  BlkPrintingClosure(const CMSCollector* collector,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   426
                     const CompactibleFreeListSpace* sp,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   427
                     const CMSBitMap* live_bit_map,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   428
                     outputStream* st):
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   429
    _collector(collector),
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   430
    _sp(sp),
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   431
    _live_bit_map(live_bit_map),
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   432
    _post_remark(collector->abstract_state() > CMSCollector::FinalMarking),
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   433
    _st(st) { }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   434
  size_t do_blk(HeapWord* addr);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   435
};
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   436
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   437
size_t BlkPrintingClosure::do_blk(HeapWord* addr) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   438
  size_t sz = _sp->block_size_no_stall(addr, _collector);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   439
  assert(sz != 0, "Should always be able to compute a size");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   440
  if (_sp->block_is_obj(addr)) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   441
    const bool dead = _post_remark && !_live_bit_map->isMarked(addr);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   442
    _st->print_cr(PTR_FORMAT ": %s object of size " SIZE_FORMAT "%s",
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   443
      addr,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   444
      dead ? "dead" : "live",
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   445
      sz,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   446
      (!dead && CMSPrintObjectsInDump) ? ":" : ".");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   447
    if (CMSPrintObjectsInDump && !dead) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   448
      oop(addr)->print_on(_st);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   449
      _st->print_cr("--------------------------------------");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   450
    }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   451
  } else { // free block
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   452
    _st->print_cr(PTR_FORMAT ": free block of size " SIZE_FORMAT "%s",
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   453
      addr, sz, CMSPrintChunksInDump ? ":" : ".");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   454
    if (CMSPrintChunksInDump) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   455
      ((FreeChunk*)addr)->print_on(_st);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   456
      _st->print_cr("--------------------------------------");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   457
    }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   458
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   459
  return sz;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   460
}
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   461
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   462
void CompactibleFreeListSpace::dump_at_safepoint_with_locks(CMSCollector* c,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   463
  outputStream* st) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   464
  st->print_cr("\n=========================");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   465
  st->print_cr("Block layout in CMS Heap:");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   466
  st->print_cr("=========================");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   467
  BlkPrintingClosure  bpcl(c, this, c->markBitMap(), st);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   468
  blk_iterate(&bpcl);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   469
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   470
  st->print_cr("\n=======================================");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   471
  st->print_cr("Order & Layout of Promotion Info Blocks");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   472
  st->print_cr("=======================================");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   473
  print_promo_info_blocks(st);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   474
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   475
  st->print_cr("\n===========================");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   476
  st->print_cr("Order of Indexed Free Lists");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   477
  st->print_cr("=========================");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   478
  print_indexed_free_lists(st);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   479
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   480
  st->print_cr("\n=================================");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   481
  st->print_cr("Order of Free Lists in Dictionary");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   482
  st->print_cr("=================================");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   483
  print_dictionary_free_lists(st);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   484
}
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   485
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   486
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   487
void CompactibleFreeListSpace::reportFreeListStatistics() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   488
  assert_lock_strong(&_freelistLock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   489
  assert(PrintFLSStatistics != 0, "Reporting error");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   490
  _dictionary->reportStatistics();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   491
  if (PrintFLSStatistics > 1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   492
    reportIndexedFreeListStatistics();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   493
    size_t totalSize = totalSizeInIndexedFreeLists() +
489c9b5090e2 Initial load
duke
parents:
diff changeset
   494
                       _dictionary->totalChunkSize(DEBUG_ONLY(freelistLock()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   495
    gclog_or_tty->print(" free=%ld frag=%1.4f\n", totalSize, flsFrag());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   496
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   497
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   498
489c9b5090e2 Initial load
duke
parents:
diff changeset
   499
void CompactibleFreeListSpace::reportIndexedFreeListStatistics() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   500
  assert_lock_strong(&_freelistLock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   501
  gclog_or_tty->print("Statistics for IndexedFreeLists:\n"
489c9b5090e2 Initial load
duke
parents:
diff changeset
   502
                      "--------------------------------\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   503
  size_t totalSize = totalSizeInIndexedFreeLists();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   504
  size_t   freeBlocks = numFreeBlocksInIndexedFreeLists();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   505
  gclog_or_tty->print("Total Free Space: %d\n", totalSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   506
  gclog_or_tty->print("Max   Chunk Size: %d\n", maxChunkSizeInIndexedFreeLists());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   507
  gclog_or_tty->print("Number of Blocks: %d\n", freeBlocks);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   508
  if (freeBlocks != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   509
    gclog_or_tty->print("Av.  Block  Size: %d\n", totalSize/freeBlocks);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   510
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   511
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   512
489c9b5090e2 Initial load
duke
parents:
diff changeset
   513
size_t CompactibleFreeListSpace::numFreeBlocksInIndexedFreeLists() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   514
  size_t res = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   515
  for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   516
    debug_only(
489c9b5090e2 Initial load
duke
parents:
diff changeset
   517
      ssize_t recount = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   518
      for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   519
         fc = fc->next()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   520
        recount += 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   521
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   522
      assert(recount == _indexedFreeList[i].count(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   523
        "Incorrect count in list");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   524
    )
489c9b5090e2 Initial load
duke
parents:
diff changeset
   525
    res += _indexedFreeList[i].count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   526
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   527
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   528
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   529
489c9b5090e2 Initial load
duke
parents:
diff changeset
   530
size_t CompactibleFreeListSpace::maxChunkSizeInIndexedFreeLists() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   531
  for (size_t i = IndexSetSize - 1; i != 0; i -= IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   532
    if (_indexedFreeList[i].head() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   533
      assert(_indexedFreeList[i].count() != 0, "Inconsistent FreeList");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   534
      return (size_t)i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   535
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   536
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   537
  return 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   538
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   539
489c9b5090e2 Initial load
duke
parents:
diff changeset
   540
void CompactibleFreeListSpace::set_end(HeapWord* value) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   541
  HeapWord* prevEnd = end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   542
  assert(prevEnd != value, "unnecessary set_end call");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   543
  assert(prevEnd == NULL || value >= unallocated_block(), "New end is below unallocated block");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   544
  _end = value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   545
  if (prevEnd != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   546
    // Resize the underlying block offset table.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   547
    _bt.resize(pointer_delta(value, bottom()));
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   548
    if (value <= prevEnd) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   549
      assert(value >= unallocated_block(), "New end is below unallocated block");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   550
    } else {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   551
      // Now, take this new chunk and add it to the free blocks.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   552
      // Note that the BOT has not yet been updated for this block.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   553
      size_t newFcSize = pointer_delta(value, prevEnd);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   554
      // XXX This is REALLY UGLY and should be fixed up. XXX
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   555
      if (!_adaptive_freelists && _smallLinearAllocBlock._ptr == NULL) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   556
        // Mark the boundary of the new block in BOT
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   557
        _bt.mark_block(prevEnd, value);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   558
        // put it all in the linAB
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   559
        if (ParallelGCThreads == 0) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   560
          _smallLinearAllocBlock._ptr = prevEnd;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   561
          _smallLinearAllocBlock._word_size = newFcSize;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   562
          repairLinearAllocBlock(&_smallLinearAllocBlock);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   563
        } else { // ParallelGCThreads > 0
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   564
          MutexLockerEx x(parDictionaryAllocLock(),
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   565
                          Mutex::_no_safepoint_check_flag);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   566
          _smallLinearAllocBlock._ptr = prevEnd;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   567
          _smallLinearAllocBlock._word_size = newFcSize;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   568
          repairLinearAllocBlock(&_smallLinearAllocBlock);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   569
        }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   570
        // Births of chunks put into a LinAB are not recorded.  Births
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   571
        // of chunks as they are allocated out of a LinAB are.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   572
      } else {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   573
        // Add the block to the free lists, if possible coalescing it
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   574
        // with the last free block, and update the BOT and census data.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   575
        addChunkToFreeListsAtEndRecordingStats(prevEnd, newFcSize);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   576
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   577
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   578
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   579
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   580
489c9b5090e2 Initial load
duke
parents:
diff changeset
   581
class FreeListSpace_DCTOC : public Filtering_DCTOC {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   582
  CompactibleFreeListSpace* _cfls;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   583
  CMSCollector* _collector;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   584
protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   585
  // Override.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   586
#define walk_mem_region_with_cl_DECL(ClosureType)                       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   587
  virtual void walk_mem_region_with_cl(MemRegion mr,                    \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   588
                                       HeapWord* bottom, HeapWord* top, \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   589
                                       ClosureType* cl);                \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   590
      void walk_mem_region_with_cl_par(MemRegion mr,                    \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   591
                                       HeapWord* bottom, HeapWord* top, \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   592
                                       ClosureType* cl);                \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   593
    void walk_mem_region_with_cl_nopar(MemRegion mr,                    \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   594
                                       HeapWord* bottom, HeapWord* top, \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   595
                                       ClosureType* cl)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   596
  walk_mem_region_with_cl_DECL(OopClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   597
  walk_mem_region_with_cl_DECL(FilteringClosure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   598
489c9b5090e2 Initial load
duke
parents:
diff changeset
   599
public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   600
  FreeListSpace_DCTOC(CompactibleFreeListSpace* sp,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   601
                      CMSCollector* collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   602
                      OopClosure* cl,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   603
                      CardTableModRefBS::PrecisionStyle precision,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   604
                      HeapWord* boundary) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   605
    Filtering_DCTOC(sp, cl, precision, boundary),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   606
    _cfls(sp), _collector(collector) {}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   607
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   608
489c9b5090e2 Initial load
duke
parents:
diff changeset
   609
// We de-virtualize the block-related calls below, since we know that our
489c9b5090e2 Initial load
duke
parents:
diff changeset
   610
// space is a CompactibleFreeListSpace.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   611
#define FreeListSpace_DCTOC__walk_mem_region_with_cl_DEFN(ClosureType)          \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   612
void FreeListSpace_DCTOC::walk_mem_region_with_cl(MemRegion mr,                 \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   613
                                                 HeapWord* bottom,              \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   614
                                                 HeapWord* top,                 \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   615
                                                 ClosureType* cl) {             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   616
   if (SharedHeap::heap()->n_par_threads() > 0) {                               \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   617
     walk_mem_region_with_cl_par(mr, bottom, top, cl);                          \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   618
   } else {                                                                     \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   619
     walk_mem_region_with_cl_nopar(mr, bottom, top, cl);                        \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   620
   }                                                                            \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   621
}                                                                               \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   622
void FreeListSpace_DCTOC::walk_mem_region_with_cl_par(MemRegion mr,             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   623
                                                      HeapWord* bottom,         \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   624
                                                      HeapWord* top,            \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   625
                                                      ClosureType* cl) {        \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   626
  /* Skip parts that are before "mr", in case "block_start" sent us             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   627
     back too far. */                                                           \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   628
  HeapWord* mr_start = mr.start();                                              \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   629
  size_t bot_size = _cfls->CompactibleFreeListSpace::block_size(bottom);        \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   630
  HeapWord* next = bottom + bot_size;                                           \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   631
  while (next < mr_start) {                                                     \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   632
    bottom = next;                                                              \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   633
    bot_size = _cfls->CompactibleFreeListSpace::block_size(bottom);             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   634
    next = bottom + bot_size;                                                   \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   635
  }                                                                             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   636
                                                                                \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   637
  while (bottom < top) {                                                        \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   638
    if (_cfls->CompactibleFreeListSpace::block_is_obj(bottom) &&                \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   639
        !_cfls->CompactibleFreeListSpace::obj_allocated_since_save_marks(       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   640
                    oop(bottom)) &&                                             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   641
        !_collector->CMSCollector::is_dead_obj(oop(bottom))) {                  \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   642
      size_t word_sz = oop(bottom)->oop_iterate(cl, mr);                        \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   643
      bottom += _cfls->adjustObjectSize(word_sz);                               \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   644
    } else {                                                                    \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   645
      bottom += _cfls->CompactibleFreeListSpace::block_size(bottom);            \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   646
    }                                                                           \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   647
  }                                                                             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   648
}                                                                               \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   649
void FreeListSpace_DCTOC::walk_mem_region_with_cl_nopar(MemRegion mr,           \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   650
                                                        HeapWord* bottom,       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   651
                                                        HeapWord* top,          \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   652
                                                        ClosureType* cl) {      \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   653
  /* Skip parts that are before "mr", in case "block_start" sent us             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   654
     back too far. */                                                           \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   655
  HeapWord* mr_start = mr.start();                                              \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   656
  size_t bot_size = _cfls->CompactibleFreeListSpace::block_size_nopar(bottom);  \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   657
  HeapWord* next = bottom + bot_size;                                           \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   658
  while (next < mr_start) {                                                     \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   659
    bottom = next;                                                              \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   660
    bot_size = _cfls->CompactibleFreeListSpace::block_size_nopar(bottom);       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   661
    next = bottom + bot_size;                                                   \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   662
  }                                                                             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   663
                                                                                \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   664
  while (bottom < top) {                                                        \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   665
    if (_cfls->CompactibleFreeListSpace::block_is_obj_nopar(bottom) &&          \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   666
        !_cfls->CompactibleFreeListSpace::obj_allocated_since_save_marks(       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   667
                    oop(bottom)) &&                                             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   668
        !_collector->CMSCollector::is_dead_obj(oop(bottom))) {                  \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   669
      size_t word_sz = oop(bottom)->oop_iterate(cl, mr);                        \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   670
      bottom += _cfls->adjustObjectSize(word_sz);                               \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   671
    } else {                                                                    \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   672
      bottom += _cfls->CompactibleFreeListSpace::block_size_nopar(bottom);      \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   673
    }                                                                           \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   674
  }                                                                             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
   675
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   676
489c9b5090e2 Initial load
duke
parents:
diff changeset
   677
// (There are only two of these, rather than N, because the split is due
489c9b5090e2 Initial load
duke
parents:
diff changeset
   678
// only to the introduction of the FilteringClosure, a local part of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   679
// impl of this abstraction.)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   680
FreeListSpace_DCTOC__walk_mem_region_with_cl_DEFN(OopClosure)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   681
FreeListSpace_DCTOC__walk_mem_region_with_cl_DEFN(FilteringClosure)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   682
489c9b5090e2 Initial load
duke
parents:
diff changeset
   683
DirtyCardToOopClosure*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   684
CompactibleFreeListSpace::new_dcto_cl(OopClosure* cl,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   685
                                      CardTableModRefBS::PrecisionStyle precision,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   686
                                      HeapWord* boundary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   687
  return new FreeListSpace_DCTOC(this, _collector, cl, precision, boundary);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   688
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   689
489c9b5090e2 Initial load
duke
parents:
diff changeset
   690
489c9b5090e2 Initial load
duke
parents:
diff changeset
   691
// Note on locking for the space iteration functions:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   692
// since the collector's iteration activities are concurrent with
489c9b5090e2 Initial load
duke
parents:
diff changeset
   693
// allocation activities by mutators, absent a suitable mutual exclusion
489c9b5090e2 Initial load
duke
parents:
diff changeset
   694
// mechanism the iterators may go awry. For instace a block being iterated
489c9b5090e2 Initial load
duke
parents:
diff changeset
   695
// may suddenly be allocated or divided up and part of it allocated and
489c9b5090e2 Initial load
duke
parents:
diff changeset
   696
// so on.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   697
489c9b5090e2 Initial load
duke
parents:
diff changeset
   698
// Apply the given closure to each block in the space.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   699
void CompactibleFreeListSpace::blk_iterate_careful(BlkClosureCareful* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   700
  assert_lock_strong(freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   701
  HeapWord *cur, *limit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   702
  for (cur = bottom(), limit = end(); cur < limit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   703
       cur += cl->do_blk_careful(cur));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   704
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   705
489c9b5090e2 Initial load
duke
parents:
diff changeset
   706
// Apply the given closure to each block in the space.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   707
void CompactibleFreeListSpace::blk_iterate(BlkClosure* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   708
  assert_lock_strong(freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   709
  HeapWord *cur, *limit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   710
  for (cur = bottom(), limit = end(); cur < limit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   711
       cur += cl->do_blk(cur));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   712
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   713
489c9b5090e2 Initial load
duke
parents:
diff changeset
   714
// Apply the given closure to each oop in the space.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   715
void CompactibleFreeListSpace::oop_iterate(OopClosure* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   716
  assert_lock_strong(freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   717
  HeapWord *cur, *limit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   718
  size_t curSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   719
  for (cur = bottom(), limit = end(); cur < limit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   720
       cur += curSize) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   721
    curSize = block_size(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   722
    if (block_is_obj(cur)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   723
      oop(cur)->oop_iterate(cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   724
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   725
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   726
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   727
489c9b5090e2 Initial load
duke
parents:
diff changeset
   728
// Apply the given closure to each oop in the space \intersect memory region.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   729
void CompactibleFreeListSpace::oop_iterate(MemRegion mr, OopClosure* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   730
  assert_lock_strong(freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   731
  if (is_empty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   732
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   733
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   734
  MemRegion cur = MemRegion(bottom(), end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   735
  mr = mr.intersection(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   736
  if (mr.is_empty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   737
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   738
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   739
  if (mr.equals(cur)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   740
    oop_iterate(cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   741
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   742
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   743
  assert(mr.end() <= end(), "just took an intersection above");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   744
  HeapWord* obj_addr = block_start(mr.start());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   745
  HeapWord* t = mr.end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   746
489c9b5090e2 Initial load
duke
parents:
diff changeset
   747
  SpaceMemRegionOopsIterClosure smr_blk(cl, mr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   748
  if (block_is_obj(obj_addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   749
    // Handle first object specially.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   750
    oop obj = oop(obj_addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   751
    obj_addr += adjustObjectSize(obj->oop_iterate(&smr_blk));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   752
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   753
    FreeChunk* fc = (FreeChunk*)obj_addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   754
    obj_addr += fc->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   755
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   756
  while (obj_addr < t) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   757
    HeapWord* obj = obj_addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   758
    obj_addr += block_size(obj_addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   759
    // If "obj_addr" is not greater than top, then the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   760
    // entire object "obj" is within the region.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   761
    if (obj_addr <= t) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   762
      if (block_is_obj(obj)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   763
        oop(obj)->oop_iterate(cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   764
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   765
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   766
      // "obj" extends beyond end of region
489c9b5090e2 Initial load
duke
parents:
diff changeset
   767
      if (block_is_obj(obj)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   768
        oop(obj)->oop_iterate(&smr_blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   769
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   770
      break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   771
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   772
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   773
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   774
489c9b5090e2 Initial load
duke
parents:
diff changeset
   775
// NOTE: In the following methods, in order to safely be able to
489c9b5090e2 Initial load
duke
parents:
diff changeset
   776
// apply the closure to an object, we need to be sure that the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   777
// object has been initialized. We are guaranteed that an object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   778
// is initialized if we are holding the Heap_lock with the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   779
// world stopped.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   780
void CompactibleFreeListSpace::verify_objects_initialized() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   781
  if (is_init_completed()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   782
    assert_locked_or_safepoint(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   783
    if (Universe::is_fully_initialized()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   784
      guarantee(SafepointSynchronize::is_at_safepoint(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   785
                "Required for objects to be initialized");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   786
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   787
  } // else make a concession at vm start-up
489c9b5090e2 Initial load
duke
parents:
diff changeset
   788
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   789
489c9b5090e2 Initial load
duke
parents:
diff changeset
   790
// Apply the given closure to each object in the space
489c9b5090e2 Initial load
duke
parents:
diff changeset
   791
void CompactibleFreeListSpace::object_iterate(ObjectClosure* blk) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   792
  assert_lock_strong(freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   793
  NOT_PRODUCT(verify_objects_initialized());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   794
  HeapWord *cur, *limit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   795
  size_t curSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   796
  for (cur = bottom(), limit = end(); cur < limit;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   797
       cur += curSize) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   798
    curSize = block_size(cur);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   799
    if (block_is_obj(cur)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   800
      blk->do_object(oop(cur));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   801
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   802
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   803
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   804
1893
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   805
// Apply the given closure to each live object in the space
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   806
//   The usage of CompactibleFreeListSpace
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   807
// by the ConcurrentMarkSweepGeneration for concurrent GC's allows
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   808
// objects in the space with references to objects that are no longer
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   809
// valid.  For example, an object may reference another object
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   810
// that has already been sweep up (collected).  This method uses
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   811
// obj_is_alive() to determine whether it is safe to apply the closure to
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   812
// an object.  See obj_is_alive() for details on how liveness of an
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   813
// object is decided.
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   814
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   815
void CompactibleFreeListSpace::safe_object_iterate(ObjectClosure* blk) {
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   816
  assert_lock_strong(freelistLock());
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   817
  NOT_PRODUCT(verify_objects_initialized());
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   818
  HeapWord *cur, *limit;
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   819
  size_t curSize;
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   820
  for (cur = bottom(), limit = end(); cur < limit;
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   821
       cur += curSize) {
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   822
    curSize = block_size(cur);
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   823
    if (block_is_obj(cur) && obj_is_alive(cur)) {
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   824
      blk->do_object(oop(cur));
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   825
    }
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   826
  }
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   827
}
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1392
diff changeset
   828
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   829
void CompactibleFreeListSpace::object_iterate_mem(MemRegion mr,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   830
                                                  UpwardsObjectClosure* cl) {
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
   831
  assert_locked(freelistLock());
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   832
  NOT_PRODUCT(verify_objects_initialized());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   833
  Space::object_iterate_mem(mr, cl);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   834
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   835
489c9b5090e2 Initial load
duke
parents:
diff changeset
   836
// Callers of this iterator beware: The closure application should
489c9b5090e2 Initial load
duke
parents:
diff changeset
   837
// be robust in the face of uninitialized objects and should (always)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   838
// return a correct size so that the next addr + size below gives us a
489c9b5090e2 Initial load
duke
parents:
diff changeset
   839
// valid block boundary. [See for instance,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   840
// ScanMarkedObjectsAgainCarefullyClosure::do_object_careful()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   841
// in ConcurrentMarkSweepGeneration.cpp.]
489c9b5090e2 Initial load
duke
parents:
diff changeset
   842
HeapWord*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   843
CompactibleFreeListSpace::object_iterate_careful(ObjectClosureCareful* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   844
  assert_lock_strong(freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   845
  HeapWord *addr, *last;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   846
  size_t size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   847
  for (addr = bottom(), last  = end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   848
       addr < last; addr += size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   849
    FreeChunk* fc = (FreeChunk*)addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   850
    if (fc->isFree()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   851
      // Since we hold the free list lock, which protects direct
489c9b5090e2 Initial load
duke
parents:
diff changeset
   852
      // allocation in this generation by mutators, a free object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   853
      // will remain free throughout this iteration code.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   854
      size = fc->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   855
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   856
      // Note that the object need not necessarily be initialized,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   857
      // because (for instance) the free list lock does NOT protect
489c9b5090e2 Initial load
duke
parents:
diff changeset
   858
      // object initialization. The closure application below must
489c9b5090e2 Initial load
duke
parents:
diff changeset
   859
      // therefore be correct in the face of uninitialized objects.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   860
      size = cl->do_object_careful(oop(addr));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   861
      if (size == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   862
        // An unparsable object found. Signal early termination.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   863
        return addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   864
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   865
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   866
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   867
  return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   868
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   869
489c9b5090e2 Initial load
duke
parents:
diff changeset
   870
// Callers of this iterator beware: The closure application should
489c9b5090e2 Initial load
duke
parents:
diff changeset
   871
// be robust in the face of uninitialized objects and should (always)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   872
// return a correct size so that the next addr + size below gives us a
489c9b5090e2 Initial load
duke
parents:
diff changeset
   873
// valid block boundary. [See for instance,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   874
// ScanMarkedObjectsAgainCarefullyClosure::do_object_careful()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   875
// in ConcurrentMarkSweepGeneration.cpp.]
489c9b5090e2 Initial load
duke
parents:
diff changeset
   876
HeapWord*
489c9b5090e2 Initial load
duke
parents:
diff changeset
   877
CompactibleFreeListSpace::object_iterate_careful_m(MemRegion mr,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   878
  ObjectClosureCareful* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   879
  assert_lock_strong(freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   880
  // Can't use used_region() below because it may not necessarily
489c9b5090e2 Initial load
duke
parents:
diff changeset
   881
  // be the same as [bottom(),end()); although we could
489c9b5090e2 Initial load
duke
parents:
diff changeset
   882
  // use [used_region().start(),round_to(used_region().end(),CardSize)),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   883
  // that appears too cumbersome, so we just do the simpler check
489c9b5090e2 Initial load
duke
parents:
diff changeset
   884
  // in the assertion below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   885
  assert(!mr.is_empty() && MemRegion(bottom(),end()).contains(mr),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   886
         "mr should be non-empty and within used space");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   887
  HeapWord *addr, *end;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   888
  size_t size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   889
  for (addr = block_start_careful(mr.start()), end  = mr.end();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   890
       addr < end; addr += size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   891
    FreeChunk* fc = (FreeChunk*)addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   892
    if (fc->isFree()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   893
      // Since we hold the free list lock, which protects direct
489c9b5090e2 Initial load
duke
parents:
diff changeset
   894
      // allocation in this generation by mutators, a free object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   895
      // will remain free throughout this iteration code.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   896
      size = fc->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   897
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   898
      // Note that the object need not necessarily be initialized,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   899
      // because (for instance) the free list lock does NOT protect
489c9b5090e2 Initial load
duke
parents:
diff changeset
   900
      // object initialization. The closure application below must
489c9b5090e2 Initial load
duke
parents:
diff changeset
   901
      // therefore be correct in the face of uninitialized objects.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   902
      size = cl->do_object_careful_m(oop(addr), mr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   903
      if (size == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   904
        // An unparsable object found. Signal early termination.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   905
        return addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   906
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   907
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   908
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   909
  return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   910
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   911
489c9b5090e2 Initial load
duke
parents:
diff changeset
   912
1374
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   913
HeapWord* CompactibleFreeListSpace::block_start_const(const void* p) const {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   914
  NOT_PRODUCT(verify_objects_initialized());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   915
  return _bt.block_start(p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   916
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   917
489c9b5090e2 Initial load
duke
parents:
diff changeset
   918
HeapWord* CompactibleFreeListSpace::block_start_careful(const void* p) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   919
  return _bt.block_start_careful(p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   920
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   921
489c9b5090e2 Initial load
duke
parents:
diff changeset
   922
size_t CompactibleFreeListSpace::block_size(const HeapWord* p) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   923
  NOT_PRODUCT(verify_objects_initialized());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   924
  assert(MemRegion(bottom(), end()).contains(p), "p not in space");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   925
  // This must be volatile, or else there is a danger that the compiler
489c9b5090e2 Initial load
duke
parents:
diff changeset
   926
  // will compile the code below into a sometimes-infinite loop, by keeping
489c9b5090e2 Initial load
duke
parents:
diff changeset
   927
  // the value read the first time in a register.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   928
  while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   929
    // We must do this until we get a consistent view of the object.
613
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   930
    if (FreeChunk::indicatesFreeChunk(p)) {
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   931
      volatile FreeChunk* fc = (volatile FreeChunk*)p;
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   932
      size_t res = fc->size();
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   933
      // If the object is still a free chunk, return the size, else it
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   934
      // has been allocated so try again.
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   935
      if (FreeChunk::indicatesFreeChunk(p)) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   936
        assert(res != 0, "Block size should not be 0");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   937
        return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   938
      }
613
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   939
    } else {
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   940
      // must read from what 'p' points to in each loop.
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   941
      klassOop k = ((volatile oopDesc*)p)->klass_or_null();
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   942
      if (k != NULL) {
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   943
        assert(k->is_oop(true /* ignore mark word */), "Should really be klass oop.");
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   944
        oop o = (oop)p;
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   945
        assert(o->is_parsable(), "Should be parsable");
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   946
        assert(o->is_oop(true /* ignore mark word */), "Should be an oop.");
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   947
        size_t res = o->size_given_klass(k->klass_part());
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   948
        res = adjustObjectSize(res);
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   949
        assert(res != 0, "Block size should not be 0");
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   950
        return res;
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   951
      }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   952
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   953
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   954
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   955
489c9b5090e2 Initial load
duke
parents:
diff changeset
   956
// A variant of the above that uses the Printezis bits for
489c9b5090e2 Initial load
duke
parents:
diff changeset
   957
// unparsable but allocated objects. This avoids any possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
   958
// stalls waiting for mutators to initialize objects, and is
489c9b5090e2 Initial load
duke
parents:
diff changeset
   959
// thus potentially faster than the variant above. However,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   960
// this variant may return a zero size for a block that is
489c9b5090e2 Initial load
duke
parents:
diff changeset
   961
// under mutation and for which a consistent size cannot be
489c9b5090e2 Initial load
duke
parents:
diff changeset
   962
// inferred without stalling; see CMSCollector::block_size_if_printezis_bits().
489c9b5090e2 Initial load
duke
parents:
diff changeset
   963
size_t CompactibleFreeListSpace::block_size_no_stall(HeapWord* p,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   964
                                                     const CMSCollector* c)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   965
const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   966
  assert(MemRegion(bottom(), end()).contains(p), "p not in space");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   967
  // This must be volatile, or else there is a danger that the compiler
489c9b5090e2 Initial load
duke
parents:
diff changeset
   968
  // will compile the code below into a sometimes-infinite loop, by keeping
489c9b5090e2 Initial load
duke
parents:
diff changeset
   969
  // the value read the first time in a register.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   970
  DEBUG_ONLY(uint loops = 0;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   971
  while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   972
    // We must do this until we get a consistent view of the object.
613
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   973
    if (FreeChunk::indicatesFreeChunk(p)) {
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   974
      volatile FreeChunk* fc = (volatile FreeChunk*)p;
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   975
      size_t res = fc->size();
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   976
      if (FreeChunk::indicatesFreeChunk(p)) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   977
        assert(res != 0, "Block size should not be 0");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   978
        assert(loops == 0, "Should be 0");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   979
        return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   980
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   981
    } else {
613
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   982
      // must read from what 'p' points to in each loop.
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   983
      klassOop k = ((volatile oopDesc*)p)->klass_or_null();
1894
5c343868d071 6692899: CMS: many vm.parallel_class_loading tests fail with assert "missing Printezis mark"
jmasa
parents: 1893
diff changeset
   984
      if (k != NULL &&
5c343868d071 6692899: CMS: many vm.parallel_class_loading tests fail with assert "missing Printezis mark"
jmasa
parents: 1893
diff changeset
   985
          ((oopDesc*)p)->is_parsable() &&
5c343868d071 6692899: CMS: many vm.parallel_class_loading tests fail with assert "missing Printezis mark"
jmasa
parents: 1893
diff changeset
   986
          ((oopDesc*)p)->is_conc_safe()) {
613
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   987
        assert(k->is_oop(), "Should really be klass oop.");
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   988
        oop o = (oop)p;
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   989
        assert(o->is_oop(), "Should be an oop");
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   990
        size_t res = o->size_given_klass(k->klass_part());
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   991
        res = adjustObjectSize(res);
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   992
        assert(res != 0, "Block size should not be 0");
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   993
        return res;
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   994
      } else {
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   995
        return c->block_size_if_printezis_bits(p);
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
   996
      }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   997
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   998
    assert(loops == 0, "Can loop at most once");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   999
    DEBUG_ONLY(loops++;)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1000
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1001
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1002
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1003
size_t CompactibleFreeListSpace::block_size_nopar(const HeapWord* p) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1004
  NOT_PRODUCT(verify_objects_initialized());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1005
  assert(MemRegion(bottom(), end()).contains(p), "p not in space");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1006
  FreeChunk* fc = (FreeChunk*)p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1007
  if (fc->isFree()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1008
    return fc->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1009
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1010
    // Ignore mark word because this may be a recently promoted
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1011
    // object whose mark word is used to chain together grey
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1012
    // objects (the last one would have a null value).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1013
    assert(oop(p)->is_oop(true), "Should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1014
    return adjustObjectSize(oop(p)->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1015
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1016
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1017
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1018
// This implementation assumes that the property of "being an object" is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1019
// stable.  But being a free chunk may not be (because of parallel
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1020
// promotion.)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1021
bool CompactibleFreeListSpace::block_is_obj(const HeapWord* p) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1022
  FreeChunk* fc = (FreeChunk*)p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1023
  assert(is_in_reserved(p), "Should be in space");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1024
  // When doing a mark-sweep-compact of the CMS generation, this
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1025
  // assertion may fail because prepare_for_compaction() uses
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1026
  // space that is garbage to maintain information on ranges of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1027
  // live objects so that these live ranges can be moved as a whole.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1028
  // Comment out this assertion until that problem can be solved
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1029
  // (i.e., that the block start calculation may look at objects
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1030
  // at address below "p" in finding the object that contains "p"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1031
  // and those objects (if garbage) may have been modified to hold
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1032
  // live range information.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1033
  // assert(ParallelGCThreads > 0 || _bt.block_start(p) == p, "Should be a block boundary");
613
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
  1034
  if (FreeChunk::indicatesFreeChunk(p)) return false;
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
  1035
  klassOop k = oop(p)->klass_or_null();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1036
  if (k != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1037
    // Ignore mark word because it may have been used to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1038
    // chain together promoted objects (the last one
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1039
    // would have a null value).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1040
    assert(oop(p)->is_oop(true), "Should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1041
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1042
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1043
    return false;  // Was not an object at the start of collection.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1044
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1045
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1046
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1047
// Check if the object is alive. This fact is checked either by consulting
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1048
// the main marking bitmap in the sweeping phase or, if it's a permanent
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1049
// generation and we're not in the sweeping phase, by checking the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1050
// perm_gen_verify_bit_map where we store the "deadness" information if
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1051
// we did not sweep the perm gen in the most recent previous GC cycle.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1052
bool CompactibleFreeListSpace::obj_is_alive(const HeapWord* p) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1053
  assert (block_is_obj(p), "The address should point to an object");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1054
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1055
  // If we're sweeping, we use object liveness information from the main bit map
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1056
  // for both perm gen and old gen.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1057
  // We don't need to lock the bitmap (live_map or dead_map below), because
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1058
  // EITHER we are in the middle of the sweeping phase, and the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1059
  // main marking bit map (live_map below) is locked,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1060
  // OR we're in other phases and perm_gen_verify_bit_map (dead_map below)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1061
  // is stable, because it's mutated only in the sweeping phase.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1062
  if (_collector->abstract_state() == CMSCollector::Sweeping) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1063
    CMSBitMap* live_map = _collector->markBitMap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1064
    return live_map->isMarked((HeapWord*) p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1065
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1066
    // If we're not currently sweeping and we haven't swept the perm gen in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1067
    // the previous concurrent cycle then we may have dead but unswept objects
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1068
    // in the perm gen. In this case, we use the "deadness" information
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1069
    // that we had saved in perm_gen_verify_bit_map at the last sweep.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1070
    if (!CMSClassUnloadingEnabled && _collector->_permGen->reserved().contains(p)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1071
      if (_collector->verifying()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1072
        CMSBitMap* dead_map = _collector->perm_gen_verify_bit_map();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1073
        // Object is marked in the dead_map bitmap at the previous sweep
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1074
        // when we know that it's dead; if the bitmap is not allocated then
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1075
        // the object is alive.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1076
        return (dead_map->sizeInBits() == 0) // bit_map has been allocated
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1077
               || !dead_map->par_isMarked((HeapWord*) p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1078
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1079
        return false; // We can't say for sure if it's live, so we say that it's dead.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1080
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1081
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1082
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1083
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1084
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1085
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1086
bool CompactibleFreeListSpace::block_is_obj_nopar(const HeapWord* p) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1087
  FreeChunk* fc = (FreeChunk*)p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1088
  assert(is_in_reserved(p), "Should be in space");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1089
  assert(_bt.block_start(p) == p, "Should be a block boundary");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1090
  if (!fc->isFree()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1091
    // Ignore mark word because it may have been used to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1092
    // chain together promoted objects (the last one
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1093
    // would have a null value).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1094
    assert(oop(p)->is_oop(true), "Should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1095
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1096
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1097
  return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1098
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1099
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1100
// "MT-safe but not guaranteed MT-precise" (TM); you may get an
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1101
// approximate answer if you don't hold the freelistlock when you call this.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1102
size_t CompactibleFreeListSpace::totalSizeInIndexedFreeLists() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1103
  size_t size = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1104
  for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1105
    debug_only(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1106
      // We may be calling here without the lock in which case we
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1107
      // won't do this modest sanity check.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1108
      if (freelistLock()->owned_by_self()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1109
        size_t total_list_size = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1110
        for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1111
          fc = fc->next()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1112
          total_list_size += i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1113
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1114
        assert(total_list_size == i * _indexedFreeList[i].count(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1115
               "Count in list is incorrect");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1116
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1117
    )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1118
    size += i * _indexedFreeList[i].count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1119
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1120
  return size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1121
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1122
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1123
HeapWord* CompactibleFreeListSpace::par_allocate(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1124
  MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1125
  return allocate(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1126
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1127
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1128
HeapWord*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1129
CompactibleFreeListSpace::getChunkFromSmallLinearAllocBlockRemainder(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1130
  return getChunkFromLinearAllocBlockRemainder(&_smallLinearAllocBlock, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1131
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1132
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1133
HeapWord* CompactibleFreeListSpace::allocate(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1134
  assert_lock_strong(freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1135
  HeapWord* res = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1136
  assert(size == adjustObjectSize(size),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1137
         "use adjustObjectSize() before calling into allocate()");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1138
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1139
  if (_adaptive_freelists) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1140
    res = allocate_adaptive_freelists(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1141
  } else {  // non-adaptive free lists
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1142
    res = allocate_non_adaptive_freelists(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1143
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1144
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1145
  if (res != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1146
    // check that res does lie in this space!
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1147
    assert(is_in_reserved(res), "Not in this space!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1148
    assert(is_aligned((void*)res), "alignment check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1149
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1150
    FreeChunk* fc = (FreeChunk*)res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1151
    fc->markNotFree();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1152
    assert(!fc->isFree(), "shouldn't be marked free");
613
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
  1153
    assert(oop(fc)->klass_or_null() == NULL, "should look uninitialized");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1154
    // Verify that the block offset table shows this to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1155
    // be a single block, but not one which is unallocated.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1156
    _bt.verify_single_block(res, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1157
    _bt.verify_not_unallocated(res, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1158
    // mangle a just allocated object with a distinct pattern.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1159
    debug_only(fc->mangleAllocated(size));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1160
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1161
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1162
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1163
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1164
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1165
HeapWord* CompactibleFreeListSpace::allocate_non_adaptive_freelists(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1166
  HeapWord* res = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1167
  // try and use linear allocation for smaller blocks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1168
  if (size < _smallLinearAllocBlock._allocation_size_limit) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1169
    // if successful, the following also adjusts block offset table
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1170
    res = getChunkFromSmallLinearAllocBlock(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1171
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1172
  // Else triage to indexed lists for smaller sizes
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1173
  if (res == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1174
    if (size < SmallForDictionary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1175
      res = (HeapWord*) getChunkFromIndexedFreeList(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1176
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1177
      // else get it from the big dictionary; if even this doesn't
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1178
      // work we are out of luck.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1179
      res = (HeapWord*)getChunkFromDictionaryExact(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1180
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1181
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1182
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1183
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1184
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1185
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1186
HeapWord* CompactibleFreeListSpace::allocate_adaptive_freelists(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1187
  assert_lock_strong(freelistLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1188
  HeapWord* res = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1189
  assert(size == adjustObjectSize(size),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1190
         "use adjustObjectSize() before calling into allocate()");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1191
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1192
  // Strategy
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1193
  //   if small
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1194
  //     exact size from small object indexed list if small
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1195
  //     small or large linear allocation block (linAB) as appropriate
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1196
  //     take from lists of greater sized chunks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1197
  //   else
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1198
  //     dictionary
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1199
  //     small or large linear allocation block if it has the space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1200
  // Try allocating exact size from indexTable first
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1201
  if (size < IndexSetSize) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1202
    res = (HeapWord*) getChunkFromIndexedFreeList(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1203
    if(res != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1204
      assert(res != (HeapWord*)_indexedFreeList[size].head(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1205
        "Not removed from free list");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1206
      // no block offset table adjustment is necessary on blocks in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1207
      // the indexed lists.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1208
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1209
    // Try allocating from the small LinAB
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1210
    } else if (size < _smallLinearAllocBlock._allocation_size_limit &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1211
        (res = getChunkFromSmallLinearAllocBlock(size)) != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1212
        // if successful, the above also adjusts block offset table
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1213
        // Note that this call will refill the LinAB to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1214
        // satisfy the request.  This is different that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1215
        // evm.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1216
        // Don't record chunk off a LinAB?  smallSplitBirth(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1217
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1218
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1219
      // Raid the exact free lists larger than size, even if they are not
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1220
      // overpopulated.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1221
      res = (HeapWord*) getChunkFromGreater(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1222
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1223
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1224
    // Big objects get allocated directly from the dictionary.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1225
    res = (HeapWord*) getChunkFromDictionaryExact(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1226
    if (res == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1227
      // Try hard not to fail since an allocation failure will likely
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1228
      // trigger a synchronous GC.  Try to get the space from the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1229
      // allocation blocks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1230
      res = getChunkFromSmallLinearAllocBlockRemainder(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1231
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1232
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1233
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1234
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1235
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1236
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1237
// A worst-case estimate of the space required (in HeapWords) to expand the heap
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1238
// when promoting obj.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1239
size_t CompactibleFreeListSpace::expansionSpaceRequired(size_t obj_size) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1240
  // Depending on the object size, expansion may require refilling either a
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1241
  // bigLAB or a smallLAB plus refilling a PromotionInfo object.  MinChunkSize
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1242
  // is added because the dictionary may over-allocate to avoid fragmentation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1243
  size_t space = obj_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1244
  if (!_adaptive_freelists) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1245
    space = MAX2(space, _smallLinearAllocBlock._refillSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1246
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1247
  space += _promoInfo.refillSize() + 2 * MinChunkSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1248
  return space;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1249
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1250
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1251
FreeChunk* CompactibleFreeListSpace::getChunkFromGreater(size_t numWords) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1252
  FreeChunk* ret;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1253
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1254
  assert(numWords >= MinChunkSize, "Size is less than minimum");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1255
  assert(linearAllocationWouldFail() || bestFitFirst(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1256
    "Should not be here");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1257
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1258
  size_t i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1259
  size_t currSize = numWords + MinChunkSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1260
  assert(currSize % MinObjAlignment == 0, "currSize should be aligned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1261
  for (i = currSize; i < IndexSetSize; i += IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1262
    FreeList* fl = &_indexedFreeList[i];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1263
    if (fl->head()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1264
      ret = getFromListGreater(fl, numWords);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1265
      assert(ret == NULL || ret->isFree(), "Should be returning a free chunk");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1266
      return ret;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1267
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1268
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1269
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1270
  currSize = MAX2((size_t)SmallForDictionary,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1271
                  (size_t)(numWords + MinChunkSize));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1272
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1273
  /* Try to get a chunk that satisfies request, while avoiding
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1274
     fragmentation that can't be handled. */
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1275
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1276
    ret =  dictionary()->getChunk(currSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1277
    if (ret != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1278
      assert(ret->size() - numWords >= MinChunkSize,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1279
             "Chunk is too small");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1280
      _bt.allocated((HeapWord*)ret, ret->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1281
      /* Carve returned chunk. */
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1282
      (void) splitChunkAndReturnRemainder(ret, numWords);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1283
      /* Label this as no longer a free chunk. */
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1284
      assert(ret->isFree(), "This chunk should be free");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1285
      ret->linkPrev(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1286
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1287
    assert(ret == NULL || ret->isFree(), "Should be returning a free chunk");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1288
    return ret;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1289
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1290
  ShouldNotReachHere();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1291
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1292
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1293
bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1294
  const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1295
  assert(fc->size() < IndexSetSize, "Size of chunk is too large");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1296
  return _indexedFreeList[fc->size()].verifyChunkInFreeLists(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1297
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1298
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1299
bool CompactibleFreeListSpace::verifyChunkInFreeLists(FreeChunk* fc) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1300
  if (fc->size() >= IndexSetSize) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1301
    return dictionary()->verifyChunkInFreeLists(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1302
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1303
    return verifyChunkInIndexedFreeLists(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1304
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1305
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1306
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1307
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1308
void CompactibleFreeListSpace::assert_locked() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1309
  CMSLockVerifier::assert_locked(freelistLock(), parDictionaryAllocLock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1310
}
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1311
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1312
void CompactibleFreeListSpace::assert_locked(const Mutex* lock) const {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1313
  CMSLockVerifier::assert_locked(lock);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1314
}
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1315
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1316
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1317
FreeChunk* CompactibleFreeListSpace::allocateScratch(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1318
  // In the parallel case, the main thread holds the free list lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1319
  // on behalf the parallel threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1320
  FreeChunk* fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1321
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1322
    // If GC is parallel, this might be called by several threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1323
    // This should be rare enough that the locking overhead won't affect
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1324
    // the sequential code.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1325
    MutexLockerEx x(parDictionaryAllocLock(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1326
                    Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1327
    fc = getChunkFromDictionary(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1328
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1329
  if (fc != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1330
    fc->dontCoalesce();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1331
    assert(fc->isFree(), "Should be free, but not coalescable");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1332
    // Verify that the block offset table shows this to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1333
    // be a single block, but not one which is unallocated.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1334
    _bt.verify_single_block((HeapWord*)fc, fc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1335
    _bt.verify_not_unallocated((HeapWord*)fc, fc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1336
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1337
  return fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1338
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1339
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  1340
oop CompactibleFreeListSpace::promote(oop obj, size_t obj_size) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1341
  assert(obj_size == (size_t)obj->size(), "bad obj_size passed in");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1342
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1343
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1344
  // if we are tracking promotions, then first ensure space for
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1345
  // promotion (including spooling space for saving header if necessary).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1346
  // then allocate and copy, then track promoted info if needed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1347
  // When tracking (see PromotionInfo::track()), the mark word may
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1348
  // be displaced and in this case restoration of the mark word
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1349
  // occurs in the (oop_since_save_marks_)iterate phase.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1350
  if (_promoInfo.tracking() && !_promoInfo.ensure_spooling_space()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1351
    return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1352
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1353
  // Call the allocate(size_t, bool) form directly to avoid the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1354
  // additional call through the allocate(size_t) form.  Having
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1355
  // the compile inline the call is problematic because allocate(size_t)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1356
  // is a virtual method.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1357
  HeapWord* res = allocate(adjustObjectSize(obj_size));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1358
  if (res != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1359
    Copy::aligned_disjoint_words((HeapWord*)obj, res, obj_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1360
    // if we should be tracking promotions, do so.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1361
    if (_promoInfo.tracking()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1362
        _promoInfo.track((PromotedObject*)res);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1363
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1364
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1365
  return oop(res);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1366
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1367
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1368
HeapWord*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1369
CompactibleFreeListSpace::getChunkFromSmallLinearAllocBlock(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1370
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1371
  assert(size >= MinChunkSize, "minimum chunk size");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1372
  assert(size <  _smallLinearAllocBlock._allocation_size_limit,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1373
    "maximum from smallLinearAllocBlock");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1374
  return getChunkFromLinearAllocBlock(&_smallLinearAllocBlock, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1375
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1376
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1377
HeapWord*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1378
CompactibleFreeListSpace::getChunkFromLinearAllocBlock(LinearAllocBlock *blk,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1379
                                                       size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1380
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1381
  assert(size >= MinChunkSize, "too small");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1382
  HeapWord* res = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1383
  // Try to do linear allocation from blk, making sure that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1384
  if (blk->_word_size == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1385
    // We have probably been unable to fill this either in the prologue or
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1386
    // when it was exhausted at the last linear allocation. Bail out until
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1387
    // next time.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1388
    assert(blk->_ptr == NULL, "consistency check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1389
    return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1390
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1391
  assert(blk->_word_size != 0 && blk->_ptr != NULL, "consistency check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1392
  res = getChunkFromLinearAllocBlockRemainder(blk, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1393
  if (res != NULL) return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1394
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1395
  // about to exhaust this linear allocation block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1396
  if (blk->_word_size == size) { // exactly satisfied
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1397
    res = blk->_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1398
    _bt.allocated(res, blk->_word_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1399
  } else if (size + MinChunkSize <= blk->_refillSize) {
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1400
    size_t sz = blk->_word_size;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1401
    // Update _unallocated_block if the size is such that chunk would be
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1402
    // returned to the indexed free list.  All other chunks in the indexed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1403
    // free lists are allocated from the dictionary so that _unallocated_block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1404
    // has already been adjusted for them.  Do it here so that the cost
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1405
    // for all chunks added back to the indexed free lists.
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1406
    if (sz < SmallForDictionary) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1407
      _bt.allocated(blk->_ptr, sz);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1408
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1409
    // Return the chunk that isn't big enough, and then refill below.
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1410
    addChunkToFreeLists(blk->_ptr, sz);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1411
    splitBirth(sz);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1412
    // Don't keep statistics on adding back chunk from a LinAB.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1413
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1414
    // A refilled block would not satisfy the request.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1415
    return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1416
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1417
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1418
  blk->_ptr = NULL; blk->_word_size = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1419
  refillLinearAllocBlock(blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1420
  assert(blk->_ptr == NULL || blk->_word_size >= size + MinChunkSize,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1421
         "block was replenished");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1422
  if (res != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1423
    splitBirth(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1424
    repairLinearAllocBlock(blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1425
  } else if (blk->_ptr != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1426
    res = blk->_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1427
    size_t blk_size = blk->_word_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1428
    blk->_word_size -= size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1429
    blk->_ptr  += size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1430
    splitBirth(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1431
    repairLinearAllocBlock(blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1432
    // Update BOT last so that other (parallel) GC threads see a consistent
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1433
    // view of the BOT and free blocks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1434
    // Above must occur before BOT is updated below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1435
    _bt.split_block(res, blk_size, size);  // adjust block offset table
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1436
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1437
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1438
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1439
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1440
HeapWord*  CompactibleFreeListSpace::getChunkFromLinearAllocBlockRemainder(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1441
                                        LinearAllocBlock* blk,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1442
                                        size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1443
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1444
  assert(size >= MinChunkSize, "too small");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1445
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1446
  HeapWord* res = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1447
  // This is the common case.  Keep it simple.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1448
  if (blk->_word_size >= size + MinChunkSize) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1449
    assert(blk->_ptr != NULL, "consistency check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1450
    res = blk->_ptr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1451
    // Note that the BOT is up-to-date for the linAB before allocation.  It
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1452
    // indicates the start of the linAB.  The split_block() updates the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1453
    // BOT for the linAB after the allocation (indicates the start of the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1454
    // next chunk to be allocated).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1455
    size_t blk_size = blk->_word_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1456
    blk->_word_size -= size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1457
    blk->_ptr  += size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1458
    splitBirth(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1459
    repairLinearAllocBlock(blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1460
    // Update BOT last so that other (parallel) GC threads see a consistent
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1461
    // view of the BOT and free blocks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1462
    // Above must occur before BOT is updated below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1463
    _bt.split_block(res, blk_size, size);  // adjust block offset table
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1464
    _bt.allocated(res, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1465
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1466
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1467
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1468
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1469
FreeChunk*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1470
CompactibleFreeListSpace::getChunkFromIndexedFreeList(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1471
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1472
  assert(size < SmallForDictionary, "just checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1473
  FreeChunk* res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1474
  res = _indexedFreeList[size].getChunkAtHead();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1475
  if (res == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1476
    res = getChunkFromIndexedFreeListHelper(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1477
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1478
  _bt.verify_not_unallocated((HeapWord*) res, size);
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1479
  assert(res == NULL || res->size() == size, "Incorrect block size");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1480
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1481
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1482
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1483
FreeChunk*
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1484
CompactibleFreeListSpace::getChunkFromIndexedFreeListHelper(size_t size,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1485
  bool replenish) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1486
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1487
  FreeChunk* fc = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1488
  if (size < SmallForDictionary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1489
    assert(_indexedFreeList[size].head() == NULL ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1490
      _indexedFreeList[size].surplus() <= 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1491
      "List for this size should be empty or under populated");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1492
    // Try best fit in exact lists before replenishing the list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1493
    if (!bestFitFirst() || (fc = bestFitSmall(size)) == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1494
      // Replenish list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1495
      //
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1496
      // Things tried that failed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1497
      //   Tried allocating out of the two LinAB's first before
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1498
      // replenishing lists.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1499
      //   Tried small linAB of size 256 (size in indexed list)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1500
      // and replenishing indexed lists from the small linAB.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1501
      //
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1502
      FreeChunk* newFc = NULL;
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1503
      const size_t replenish_size = CMSIndexedFreeListReplenish * size;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1504
      if (replenish_size < SmallForDictionary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1505
        // Do not replenish from an underpopulated size.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1506
        if (_indexedFreeList[replenish_size].surplus() > 0 &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1507
            _indexedFreeList[replenish_size].head() != NULL) {
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1508
          newFc = _indexedFreeList[replenish_size].getChunkAtHead();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1509
        } else if (bestFitFirst()) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1510
          newFc = bestFitSmall(replenish_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1511
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1512
      }
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1513
      if (newFc == NULL && replenish_size > size) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1514
        assert(CMSIndexedFreeListReplenish > 1, "ctl pt invariant");
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1515
        newFc = getChunkFromIndexedFreeListHelper(replenish_size, false);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1516
      }
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1517
      // Note: The stats update re split-death of block obtained above
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1518
      // will be recorded below precisely when we know we are going to
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1519
      // be actually splitting it into more than one pieces below.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1520
      if (newFc != NULL) {
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1521
        if  (replenish || CMSReplenishIntermediate) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1522
          // Replenish this list and return one block to caller.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1523
          size_t i;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1524
          FreeChunk *curFc, *nextFc;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1525
          size_t num_blk = newFc->size() / size;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1526
          assert(num_blk >= 1, "Smaller than requested?");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1527
          assert(newFc->size() % size == 0, "Should be integral multiple of request");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1528
          if (num_blk > 1) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1529
            // we are sure we will be splitting the block just obtained
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1530
            // into multiple pieces; record the split-death of the original
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1531
            splitDeath(replenish_size);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1532
          }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1533
          // carve up and link blocks 0, ..., num_blk - 2
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1534
          // The last chunk is not added to the lists but is returned as the
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1535
          // free chunk.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1536
          for (curFc = newFc, nextFc = (FreeChunk*)((HeapWord*)curFc + size),
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1537
               i = 0;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1538
               i < (num_blk - 1);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1539
               curFc = nextFc, nextFc = (FreeChunk*)((HeapWord*)nextFc + size),
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1540
               i++) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1541
            curFc->setSize(size);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1542
            // Don't record this as a return in order to try and
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1543
            // determine the "returns" from a GC.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1544
            _bt.verify_not_unallocated((HeapWord*) fc, size);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1545
            _indexedFreeList[size].returnChunkAtTail(curFc, false);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1546
            _bt.mark_block((HeapWord*)curFc, size);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1547
            splitBirth(size);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1548
            // Don't record the initial population of the indexed list
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1549
            // as a split birth.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1550
          }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1551
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1552
          // check that the arithmetic was OK above
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1553
          assert((HeapWord*)nextFc == (HeapWord*)newFc + num_blk*size,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1554
            "inconsistency in carving newFc");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1555
          curFc->setSize(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1556
          _bt.mark_block((HeapWord*)curFc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1557
          splitBirth(size);
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1558
          fc = curFc;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1559
        } else {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1560
          // Return entire block to caller
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1561
          fc = newFc;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1562
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1563
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1564
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1565
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1566
    // Get a free chunk from the free chunk dictionary to be returned to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1567
    // replenish the indexed free list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1568
    fc = getChunkFromDictionaryExact(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1569
  }
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1570
  // assert(fc == NULL || fc->isFree(), "Should be returning a free chunk");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1571
  return fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1572
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1573
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1574
FreeChunk*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1575
CompactibleFreeListSpace::getChunkFromDictionary(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1576
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1577
  FreeChunk* fc = _dictionary->getChunk(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1578
  if (fc == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1579
    return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1580
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1581
  _bt.allocated((HeapWord*)fc, fc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1582
  if (fc->size() >= size + MinChunkSize) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1583
    fc = splitChunkAndReturnRemainder(fc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1584
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1585
  assert(fc->size() >= size, "chunk too small");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1586
  assert(fc->size() < size + MinChunkSize, "chunk too big");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1587
  _bt.verify_single_block((HeapWord*)fc, fc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1588
  return fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1589
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1590
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1591
FreeChunk*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1592
CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1593
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1594
  FreeChunk* fc = _dictionary->getChunk(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1595
  if (fc == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1596
    return fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1597
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1598
  _bt.allocated((HeapWord*)fc, fc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1599
  if (fc->size() == size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1600
    _bt.verify_single_block((HeapWord*)fc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1601
    return fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1602
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1603
  assert(fc->size() > size, "getChunk() guarantee");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1604
  if (fc->size() < size + MinChunkSize) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1605
    // Return the chunk to the dictionary and go get a bigger one.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1606
    returnChunkToDictionary(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1607
    fc = _dictionary->getChunk(size + MinChunkSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1608
    if (fc == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1609
      return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1610
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1611
    _bt.allocated((HeapWord*)fc, fc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1612
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1613
  assert(fc->size() >= size + MinChunkSize, "tautology");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1614
  fc = splitChunkAndReturnRemainder(fc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1615
  assert(fc->size() == size, "chunk is wrong size");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1616
  _bt.verify_single_block((HeapWord*)fc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1617
  return fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1618
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1619
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1620
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1621
CompactibleFreeListSpace::returnChunkToDictionary(FreeChunk* chunk) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1622
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1623
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1624
  size_t size = chunk->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1625
  _bt.verify_single_block((HeapWord*)chunk, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1626
  // adjust _unallocated_block downward, as necessary
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1627
  _bt.freed((HeapWord*)chunk, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1628
  _dictionary->returnChunk(chunk);
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1629
#ifndef PRODUCT
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1630
  if (CMSCollector::abstract_state() != CMSCollector::Sweeping) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1631
    TreeChunk::as_TreeChunk(chunk)->list()->verify_stats();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1632
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1633
#endif // PRODUCT
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1634
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1635
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1636
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1637
CompactibleFreeListSpace::returnChunkToFreeList(FreeChunk* fc) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1638
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1639
  size_t size = fc->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1640
  _bt.verify_single_block((HeapWord*) fc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1641
  _bt.verify_not_unallocated((HeapWord*) fc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1642
  if (_adaptive_freelists) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1643
    _indexedFreeList[size].returnChunkAtTail(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1644
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1645
    _indexedFreeList[size].returnChunkAtHead(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1646
  }
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1647
#ifndef PRODUCT
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1648
  if (CMSCollector::abstract_state() != CMSCollector::Sweeping) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1649
     _indexedFreeList[size].verify_stats();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1650
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  1651
#endif // PRODUCT
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1652
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1653
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1654
// Add chunk to end of last block -- if it's the largest
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1655
// block -- and update BOT and census data. We would
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1656
// of course have preferred to coalesce it with the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1657
// last block, but it's currently less expensive to find the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1658
// largest block than it is to find the last.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1659
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1660
CompactibleFreeListSpace::addChunkToFreeListsAtEndRecordingStats(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1661
  HeapWord* chunk, size_t     size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1662
  // check that the chunk does lie in this space!
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1663
  assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1664
  // One of the parallel gc task threads may be here
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1665
  // whilst others are allocating.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1666
  Mutex* lock = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1667
  if (ParallelGCThreads != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1668
    lock = &_parDictionaryAllocLock;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1669
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1670
  FreeChunk* ec;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1671
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1672
    MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1673
    ec = dictionary()->findLargestDict();  // get largest block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1674
    if (ec != NULL && ec->end() == chunk) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1675
      // It's a coterminal block - we can coalesce.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1676
      size_t old_size = ec->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1677
      coalDeath(old_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1678
      removeChunkFromDictionary(ec);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1679
      size += old_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1680
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1681
      ec = (FreeChunk*)chunk;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1682
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1683
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1684
  ec->setSize(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1685
  debug_only(ec->mangleFreed(size));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1686
  if (size < SmallForDictionary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1687
    lock = _indexedFreeListParLocks[size];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1688
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1689
  MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1690
  addChunkAndRepairOffsetTable((HeapWord*)ec, size, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1691
  // record the birth under the lock since the recording involves
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1692
  // manipulation of the list on which the chunk lives and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1693
  // if the chunk is allocated and is the last on the list,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1694
  // the list can go away.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1695
  coalBirth(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1696
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1697
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1698
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1699
CompactibleFreeListSpace::addChunkToFreeLists(HeapWord* chunk,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1700
                                              size_t     size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1701
  // check that the chunk does lie in this space!
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1702
  assert(chunk != NULL && is_in_reserved(chunk), "Not in this space!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1703
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1704
  _bt.verify_single_block(chunk, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1705
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1706
  FreeChunk* fc = (FreeChunk*) chunk;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1707
  fc->setSize(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1708
  debug_only(fc->mangleFreed(size));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1709
  if (size < SmallForDictionary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1710
    returnChunkToFreeList(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1711
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1712
    returnChunkToDictionary(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1713
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1714
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1715
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1716
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1717
CompactibleFreeListSpace::addChunkAndRepairOffsetTable(HeapWord* chunk,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1718
  size_t size, bool coalesced) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1719
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1720
  assert(chunk != NULL, "null chunk");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1721
  if (coalesced) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1722
    // repair BOT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1723
    _bt.single_block(chunk, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1724
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1725
  addChunkToFreeLists(chunk, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1726
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1727
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1728
// We _must_ find the purported chunk on our free lists;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1729
// we assert if we don't.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1730
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1731
CompactibleFreeListSpace::removeFreeChunkFromFreeLists(FreeChunk* fc) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1732
  size_t size = fc->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1733
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1734
  debug_only(verifyFreeLists());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1735
  if (size < SmallForDictionary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1736
    removeChunkFromIndexedFreeList(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1737
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1738
    removeChunkFromDictionary(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1739
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1740
  _bt.verify_single_block((HeapWord*)fc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1741
  debug_only(verifyFreeLists());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1742
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1743
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1744
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1745
CompactibleFreeListSpace::removeChunkFromDictionary(FreeChunk* fc) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1746
  size_t size = fc->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1747
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1748
  assert(fc != NULL, "null chunk");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1749
  _bt.verify_single_block((HeapWord*)fc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1750
  _dictionary->removeChunk(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1751
  // adjust _unallocated_block upward, as necessary
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1752
  _bt.allocated((HeapWord*)fc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1753
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1754
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1755
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1756
CompactibleFreeListSpace::removeChunkFromIndexedFreeList(FreeChunk* fc) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1757
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1758
  size_t size = fc->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1759
  _bt.verify_single_block((HeapWord*)fc, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1760
  NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1761
    if (FLSVerifyIndexTable) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1762
      verifyIndexedFreeList(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1763
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1764
  )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1765
  _indexedFreeList[size].removeChunk(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1766
  debug_only(fc->clearNext());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1767
  debug_only(fc->clearPrev());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1768
  NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1769
    if (FLSVerifyIndexTable) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1770
      verifyIndexedFreeList(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1771
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1772
  )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1773
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1774
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1775
FreeChunk* CompactibleFreeListSpace::bestFitSmall(size_t numWords) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1776
  /* A hint is the next larger size that has a surplus.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1777
     Start search at a size large enough to guarantee that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1778
     the excess is >= MIN_CHUNK. */
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1779
  size_t start = align_object_size(numWords + MinChunkSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1780
  if (start < IndexSetSize) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1781
    FreeList* it   = _indexedFreeList;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1782
    size_t    hint = _indexedFreeList[start].hint();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1783
    while (hint < IndexSetSize) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1784
      assert(hint % MinObjAlignment == 0, "hint should be aligned");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1785
      FreeList *fl = &_indexedFreeList[hint];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1786
      if (fl->surplus() > 0 && fl->head() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1787
        // Found a list with surplus, reset original hint
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1788
        // and split out a free chunk which is returned.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1789
        _indexedFreeList[start].set_hint(hint);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1790
        FreeChunk* res = getFromListGreater(fl, numWords);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1791
        assert(res == NULL || res->isFree(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1792
          "Should be returning a free chunk");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1793
        return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1794
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1795
      hint = fl->hint(); /* keep looking */
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1796
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1797
    /* None found. */
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1798
    it[start].set_hint(IndexSetSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1799
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1800
  return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1801
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1802
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1803
/* Requires fl->size >= numWords + MinChunkSize */
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1804
FreeChunk* CompactibleFreeListSpace::getFromListGreater(FreeList* fl,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1805
  size_t numWords) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1806
  FreeChunk *curr = fl->head();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1807
  size_t oldNumWords = curr->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1808
  assert(numWords >= MinChunkSize, "Word size is too small");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1809
  assert(curr != NULL, "List is empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1810
  assert(oldNumWords >= numWords + MinChunkSize,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1811
        "Size of chunks in the list is too small");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1812
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1813
  fl->removeChunk(curr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1814
  // recorded indirectly by splitChunkAndReturnRemainder -
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1815
  // smallSplit(oldNumWords, numWords);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1816
  FreeChunk* new_chunk = splitChunkAndReturnRemainder(curr, numWords);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1817
  // Does anything have to be done for the remainder in terms of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1818
  // fixing the card table?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1819
  assert(new_chunk == NULL || new_chunk->isFree(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1820
    "Should be returning a free chunk");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1821
  return new_chunk;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1822
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1823
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1824
FreeChunk*
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1825
CompactibleFreeListSpace::splitChunkAndReturnRemainder(FreeChunk* chunk,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1826
  size_t new_size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1827
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1828
  size_t size = chunk->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1829
  assert(size > new_size, "Split from a smaller block?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1830
  assert(is_aligned(chunk), "alignment problem");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1831
  assert(size == adjustObjectSize(size), "alignment problem");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1832
  size_t rem_size = size - new_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1833
  assert(rem_size == adjustObjectSize(rem_size), "alignment problem");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1834
  assert(rem_size >= MinChunkSize, "Free chunk smaller than minimum");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1835
  FreeChunk* ffc = (FreeChunk*)((HeapWord*)chunk + new_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1836
  assert(is_aligned(ffc), "alignment problem");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1837
  ffc->setSize(rem_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1838
  ffc->linkNext(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1839
  ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1840
  // Above must occur before BOT is updated below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1841
  // adjust block offset table
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1842
  _bt.split_block((HeapWord*)chunk, chunk->size(), new_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1843
  if (rem_size < SmallForDictionary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1844
    bool is_par = (SharedHeap::heap()->n_par_threads() > 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1845
    if (is_par) _indexedFreeListParLocks[rem_size]->lock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1846
    returnChunkToFreeList(ffc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1847
    split(size, rem_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1848
    if (is_par) _indexedFreeListParLocks[rem_size]->unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1849
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1850
    returnChunkToDictionary(ffc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1851
    split(size ,rem_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1852
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1853
  chunk->setSize(new_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1854
  return chunk;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1855
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1856
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1857
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1858
CompactibleFreeListSpace::sweep_completed() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1859
  // Now that space is probably plentiful, refill linear
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1860
  // allocation blocks as needed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1861
  refillLinearAllocBlocksIfNeeded();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1862
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1863
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1864
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1865
CompactibleFreeListSpace::gc_prologue() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1866
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1867
  if (PrintFLSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1868
    gclog_or_tty->print("Before GC:\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1869
    reportFreeListStatistics();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1870
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1871
  refillLinearAllocBlocksIfNeeded();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1872
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1873
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1874
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1875
CompactibleFreeListSpace::gc_epilogue() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1876
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1877
  if (PrintGCDetails && Verbose && !_adaptive_freelists) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1878
    if (_smallLinearAllocBlock._word_size == 0)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1879
      warning("CompactibleFreeListSpace(epilogue):: Linear allocation failure");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1880
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1881
  assert(_promoInfo.noPromotions(), "_promoInfo inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1882
  _promoInfo.stopTrackingPromotions();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1883
  repairLinearAllocationBlocks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1884
  // Print Space's stats
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1885
  if (PrintFLSStatistics != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1886
    gclog_or_tty->print("After GC:\n");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1887
    reportFreeListStatistics();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1888
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1889
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1890
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1891
// Iteration support, mostly delegated from a CMS generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1892
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1893
void CompactibleFreeListSpace::save_marks() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1894
  // mark the "end" of the used space at the time of this call;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1895
  // note, however, that promoted objects from this point
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1896
  // on are tracked in the _promoInfo below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1897
  set_saved_mark_word(BlockOffsetArrayUseUnallocatedBlock ?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1898
                      unallocated_block() : end());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1899
  // inform allocator that promotions should be tracked.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1900
  assert(_promoInfo.noPromotions(), "_promoInfo inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1901
  _promoInfo.startTrackingPromotions();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1902
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1903
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1904
bool CompactibleFreeListSpace::no_allocs_since_save_marks() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1905
  assert(_promoInfo.tracking(), "No preceding save_marks?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1906
  guarantee(SharedHeap::heap()->n_par_threads() == 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1907
            "Shouldn't be called (yet) during parallel part of gc.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1908
  return _promoInfo.noPromotions();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1909
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1910
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1911
#define CFLS_OOP_SINCE_SAVE_MARKS_DEFN(OopClosureType, nv_suffix)           \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1912
                                                                            \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1913
void CompactibleFreeListSpace::                                             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1914
oop_since_save_marks_iterate##nv_suffix(OopClosureType* blk) {              \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1915
  assert(SharedHeap::heap()->n_par_threads() == 0,                          \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1916
         "Shouldn't be called (yet) during parallel part of gc.");          \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1917
  _promoInfo.promoted_oops_iterate##nv_suffix(blk);                         \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1918
  /*                                                                        \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1919
   * This also restores any displaced headers and removes the elements from \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1920
   * the iteration set as they are processed, so that we have a clean slate \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1921
   * at the end of the iteration. Note, thus, that if new objects are       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1922
   * promoted as a result of the iteration they are iterated over as well.  \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1923
   */                                                                       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1924
  assert(_promoInfo.noPromotions(), "_promoInfo inconsistency");            \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1925
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1926
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1927
ALL_SINCE_SAVE_MARKS_CLOSURES(CFLS_OOP_SINCE_SAVE_MARKS_DEFN)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1928
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1929
//////////////////////////////////////////////////////////////////////////////
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1930
// We go over the list of promoted objects, removing each from the list,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1931
// and applying the closure (this may, in turn, add more elements to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1932
// the tail of the promoted list, and these newly added objects will
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1933
// also be processed) until the list is empty.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1934
// To aid verification and debugging, in the non-product builds
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1935
// we actually forward _promoHead each time we process a promoted oop.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1936
// Note that this is not necessary in general (i.e. when we don't need to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1937
// call PromotionInfo::verify()) because oop_iterate can only add to the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1938
// end of _promoTail, and never needs to look at _promoHead.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1939
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1940
#define PROMOTED_OOPS_ITERATE_DEFN(OopClosureType, nv_suffix)               \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1941
                                                                            \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1942
void PromotionInfo::promoted_oops_iterate##nv_suffix(OopClosureType* cl) {  \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1943
  NOT_PRODUCT(verify());                                                    \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1944
  PromotedObject *curObj, *nextObj;                                         \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1945
  for (curObj = _promoHead; curObj != NULL; curObj = nextObj) {             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1946
    if ((nextObj = curObj->next()) == NULL) {                               \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1947
      /* protect ourselves against additions due to closure application     \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1948
         below by resetting the list.  */                                   \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1949
      assert(_promoTail == curObj, "Should have been the tail");            \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1950
      _promoHead = _promoTail = NULL;                                       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1951
    }                                                                       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1952
    if (curObj->hasDisplacedMark()) {                                       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1953
      /* restore displaced header */                                        \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1954
      oop(curObj)->set_mark(nextDisplacedHeader());                         \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1955
    } else {                                                                \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1956
      /* restore prototypical header */                                     \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1957
      oop(curObj)->init_mark();                                             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1958
    }                                                                       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1959
    /* The "promoted_mark" should now not be set */                         \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1960
    assert(!curObj->hasPromotedMark(),                                      \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1961
           "Should have been cleared by restoring displaced mark-word");    \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1962
    NOT_PRODUCT(_promoHead = nextObj);                                      \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1963
    if (cl != NULL) oop(curObj)->oop_iterate(cl);                           \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1964
    if (nextObj == NULL) { /* start at head of list reset above */          \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1965
      nextObj = _promoHead;                                                 \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1966
    }                                                                       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1967
  }                                                                         \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1968
  assert(noPromotions(), "post-condition violation");                       \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1969
  assert(_promoHead == NULL && _promoTail == NULL, "emptied promoted list");\
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1970
  assert(_spoolHead == _spoolTail, "emptied spooling buffers");             \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1971
  assert(_firstIndex == _nextIndex, "empty buffer");                        \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1972
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1973
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1974
// This should have been ALL_SINCE_...() just like the others,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1975
// but, because the body of the method above is somehwat longer,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1976
// the MSVC compiler cannot cope; as a workaround, we split the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1977
// macro into its 3 constituent parts below (see original macro
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1978
// definition in specializedOopClosures.hpp).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1979
SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(PROMOTED_OOPS_ITERATE_DEFN)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1980
PROMOTED_OOPS_ITERATE_DEFN(OopsInGenClosure,_v)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1981
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1982
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1983
void CompactibleFreeListSpace::object_iterate_since_last_GC(ObjectClosure* cl) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1984
  // ugghh... how would one do this efficiently for a non-contiguous space?
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1985
  guarantee(false, "NYI");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1986
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1987
185
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  1988
bool CompactibleFreeListSpace::linearAllocationWouldFail() const {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1989
  return _smallLinearAllocBlock._word_size == 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1990
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1991
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1992
void CompactibleFreeListSpace::repairLinearAllocationBlocks() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1993
  // Fix up linear allocation blocks to look like free blocks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1994
  repairLinearAllocBlock(&_smallLinearAllocBlock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1995
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1996
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1997
void CompactibleFreeListSpace::repairLinearAllocBlock(LinearAllocBlock* blk) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1998
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1999
  if (blk->_ptr != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2000
    assert(blk->_word_size != 0 && blk->_word_size >= MinChunkSize,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2001
           "Minimum block size requirement");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2002
    FreeChunk* fc = (FreeChunk*)(blk->_ptr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2003
    fc->setSize(blk->_word_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2004
    fc->linkPrev(NULL);   // mark as free
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2005
    fc->dontCoalesce();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2006
    assert(fc->isFree(), "just marked it free");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2007
    assert(fc->cantCoalesce(), "just marked it uncoalescable");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2008
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2009
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2010
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2011
void CompactibleFreeListSpace::refillLinearAllocBlocksIfNeeded() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2012
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2013
  if (_smallLinearAllocBlock._ptr == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2014
    assert(_smallLinearAllocBlock._word_size == 0,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2015
      "Size of linAB should be zero if the ptr is NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2016
    // Reset the linAB refill and allocation size limit.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2017
    _smallLinearAllocBlock.set(0, 0, 1024*SmallForLinearAlloc, SmallForLinearAlloc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2018
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2019
  refillLinearAllocBlockIfNeeded(&_smallLinearAllocBlock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2020
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2021
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2022
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2023
CompactibleFreeListSpace::refillLinearAllocBlockIfNeeded(LinearAllocBlock* blk) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2024
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2025
  assert((blk->_ptr == NULL && blk->_word_size == 0) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2026
         (blk->_ptr != NULL && blk->_word_size >= MinChunkSize),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2027
         "blk invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2028
  if (blk->_ptr == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2029
    refillLinearAllocBlock(blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2030
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2031
  if (PrintMiscellaneous && Verbose) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2032
    if (blk->_word_size == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2033
      warning("CompactibleFreeListSpace(prologue):: Linear allocation failure");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2034
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2035
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2036
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2037
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2038
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2039
CompactibleFreeListSpace::refillLinearAllocBlock(LinearAllocBlock* blk) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2040
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2041
  assert(blk->_word_size == 0 && blk->_ptr == NULL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2042
         "linear allocation block should be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2043
  FreeChunk* fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2044
  if (blk->_refillSize < SmallForDictionary &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2045
      (fc = getChunkFromIndexedFreeList(blk->_refillSize)) != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2046
    // A linAB's strategy might be to use small sizes to reduce
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2047
    // fragmentation but still get the benefits of allocation from a
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2048
    // linAB.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2049
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2050
    fc = getChunkFromDictionary(blk->_refillSize);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2051
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2052
  if (fc != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2053
    blk->_ptr  = (HeapWord*)fc;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2054
    blk->_word_size = fc->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2055
    fc->dontCoalesce();   // to prevent sweeper from sweeping us up
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2056
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2057
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2058
185
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2059
// Support for concurrent collection policy decisions.
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2060
bool CompactibleFreeListSpace::should_concurrent_collect() const {
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2061
  // In the future we might want to add in frgamentation stats --
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2062
  // including erosion of the "mountain" into this decision as well.
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2063
  return !adaptive_freelists() && linearAllocationWouldFail();
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2064
}
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2065
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2066
// Support for compaction
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2067
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2068
void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2069
  SCAN_AND_FORWARD(cp,end,block_is_obj,block_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2070
  // prepare_for_compaction() uses the space between live objects
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2071
  // so that later phase can skip dead space quickly.  So verification
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2072
  // of the free lists doesn't work after.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2073
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2074
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2075
#define obj_size(q) adjustObjectSize(oop(q)->size())
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2076
#define adjust_obj_size(s) adjustObjectSize(s)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2077
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2078
void CompactibleFreeListSpace::adjust_pointers() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2079
  // In other versions of adjust_pointers(), a bail out
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2080
  // based on the amount of live data in the generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2081
  // (i.e., if 0, bail out) may be used.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2082
  // Cannot test used() == 0 here because the free lists have already
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2083
  // been mangled by the compaction.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2084
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2085
  SCAN_AND_ADJUST_POINTERS(adjust_obj_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2086
  // See note about verification in prepare_for_compaction().
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2087
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2088
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2089
void CompactibleFreeListSpace::compact() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2090
  SCAN_AND_COMPACT(obj_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2091
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2092
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2093
// fragmentation_metric = 1 - [sum of (fbs**2) / (sum of fbs)**2]
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2094
// where fbs is free block sizes
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2095
double CompactibleFreeListSpace::flsFrag() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2096
  size_t itabFree = totalSizeInIndexedFreeLists();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2097
  double frag = 0.0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2098
  size_t i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2099
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2100
  for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2101
    double sz  = i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2102
    frag      += _indexedFreeList[i].count() * (sz * sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2103
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2104
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2105
  double totFree = itabFree +
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2106
                   _dictionary->totalChunkSize(DEBUG_ONLY(freelistLock()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2107
  if (totFree > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2108
    frag = ((frag + _dictionary->sum_of_squared_block_sizes()) /
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2109
            (totFree * totFree));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2110
    frag = (double)1.0  - frag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2111
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2112
    assert(frag == 0.0, "Follows from totFree == 0");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2113
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2114
  return frag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2115
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2116
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2117
void CompactibleFreeListSpace::beginSweepFLCensus(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2118
  float inter_sweep_current,
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2119
  float inter_sweep_estimate,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2120
  float intra_sweep_estimate) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2121
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2122
  size_t i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2123
  for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2124
    FreeList* fl    = &_indexedFreeList[i];
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2125
    if (PrintFLSStatistics > 1) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2126
      gclog_or_tty->print("size[%d] : ", i);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2127
    }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2128
    fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2129
    fl->set_coalDesired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent));
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2130
    fl->set_beforeSweep(fl->count());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2131
    fl->set_bfrSurp(fl->surplus());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2132
  }
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2133
  _dictionary->beginSweepDictCensus(CMSLargeCoalSurplusPercent,
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2134
                                    inter_sweep_current,
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2135
                                    inter_sweep_estimate,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2136
                                    intra_sweep_estimate);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2137
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2138
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2139
void CompactibleFreeListSpace::setFLSurplus() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2140
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2141
  size_t i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2142
  for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2143
    FreeList *fl = &_indexedFreeList[i];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2144
    fl->set_surplus(fl->count() -
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2145
                    (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent));
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2146
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2147
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2148
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2149
void CompactibleFreeListSpace::setFLHints() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2150
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2151
  size_t i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2152
  size_t h = IndexSetSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2153
  for (i = IndexSetSize - 1; i != 0; i -= IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2154
    FreeList *fl = &_indexedFreeList[i];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2155
    fl->set_hint(h);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2156
    if (fl->surplus() > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2157
      h = i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2158
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2159
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2160
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2161
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2162
void CompactibleFreeListSpace::clearFLCensus() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2163
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2164
  int i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2165
  for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2166
    FreeList *fl = &_indexedFreeList[i];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2167
    fl->set_prevSweep(fl->count());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2168
    fl->set_coalBirths(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2169
    fl->set_coalDeaths(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2170
    fl->set_splitBirths(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2171
    fl->set_splitDeaths(0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2172
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2173
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2174
185
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2175
void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) {
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2176
  if (PrintFLSStatistics > 0) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2177
    HeapWord* largestAddr = (HeapWord*) dictionary()->findLargestDict();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2178
    gclog_or_tty->print_cr("CMS: Large block " PTR_FORMAT,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2179
                           largestAddr);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2180
  }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2181
  setFLSurplus();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2182
  setFLHints();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2183
  if (PrintGC && PrintFLSCensus > 0) {
185
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2184
    printFLCensus(sweep_count);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2185
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2186
  clearFLCensus();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2187
  assert_locked();
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2188
  _dictionary->endSweepDictCensus(CMSLargeSplitSurplusPercent);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2189
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2190
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2191
bool CompactibleFreeListSpace::coalOverPopulated(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2192
  if (size < SmallForDictionary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2193
    FreeList *fl = &_indexedFreeList[size];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2194
    return (fl->coalDesired() < 0) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2195
           ((int)fl->count() > fl->coalDesired());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2196
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2197
    return dictionary()->coalDictOverPopulated(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2198
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2199
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2200
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2201
void CompactibleFreeListSpace::smallCoalBirth(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2202
  assert(size < SmallForDictionary, "Size too large for indexed list");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2203
  FreeList *fl = &_indexedFreeList[size];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2204
  fl->increment_coalBirths();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2205
  fl->increment_surplus();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2206
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2207
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2208
void CompactibleFreeListSpace::smallCoalDeath(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2209
  assert(size < SmallForDictionary, "Size too large for indexed list");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2210
  FreeList *fl = &_indexedFreeList[size];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2211
  fl->increment_coalDeaths();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2212
  fl->decrement_surplus();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2213
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2214
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2215
void CompactibleFreeListSpace::coalBirth(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2216
  if (size  < SmallForDictionary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2217
    smallCoalBirth(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2218
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2219
    dictionary()->dictCensusUpdate(size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2220
                                   false /* split */,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2221
                                   true /* birth */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2222
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2223
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2224
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2225
void CompactibleFreeListSpace::coalDeath(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2226
  if(size  < SmallForDictionary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2227
    smallCoalDeath(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2228
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2229
    dictionary()->dictCensusUpdate(size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2230
                                   false /* split */,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2231
                                   false /* birth */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2232
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2233
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2234
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2235
void CompactibleFreeListSpace::smallSplitBirth(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2236
  assert(size < SmallForDictionary, "Size too large for indexed list");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2237
  FreeList *fl = &_indexedFreeList[size];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2238
  fl->increment_splitBirths();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2239
  fl->increment_surplus();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2240
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2241
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2242
void CompactibleFreeListSpace::smallSplitDeath(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2243
  assert(size < SmallForDictionary, "Size too large for indexed list");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2244
  FreeList *fl = &_indexedFreeList[size];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2245
  fl->increment_splitDeaths();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2246
  fl->decrement_surplus();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2247
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2248
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2249
void CompactibleFreeListSpace::splitBirth(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2250
  if (size  < SmallForDictionary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2251
    smallSplitBirth(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2252
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2253
    dictionary()->dictCensusUpdate(size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2254
                                   true /* split */,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2255
                                   true /* birth */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2256
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2257
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2258
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2259
void CompactibleFreeListSpace::splitDeath(size_t size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2260
  if (size  < SmallForDictionary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2261
    smallSplitDeath(size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2262
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2263
    dictionary()->dictCensusUpdate(size,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2264
                                   true /* split */,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2265
                                   false /* birth */);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2266
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2267
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2268
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2269
void CompactibleFreeListSpace::split(size_t from, size_t to1) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2270
  size_t to2 = from - to1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2271
  splitDeath(from);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2272
  splitBirth(to1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2273
  splitBirth(to2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2274
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2275
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2276
void CompactibleFreeListSpace::print() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2277
  tty->print(" CompactibleFreeListSpace");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2278
  Space::print();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2279
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2280
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2281
void CompactibleFreeListSpace::prepare_for_verify() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2282
  assert_locked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2283
  repairLinearAllocationBlocks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2284
  // Verify that the SpoolBlocks look like free blocks of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2285
  // appropriate sizes... To be done ...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2286
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2287
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2288
class VerifyAllBlksClosure: public BlkClosure {
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2289
 private:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2290
  const CompactibleFreeListSpace* _sp;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2291
  const MemRegion                 _span;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2292
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2293
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2294
  VerifyAllBlksClosure(const CompactibleFreeListSpace* sp,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2295
    MemRegion span) :  _sp(sp), _span(span) { }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2296
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2297
  virtual size_t do_blk(HeapWord* addr) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2298
    size_t res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2299
    if (_sp->block_is_obj(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2300
      oop p = oop(addr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2301
      guarantee(p->is_oop(), "Should be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2302
      res = _sp->adjustObjectSize(p->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2303
      if (_sp->obj_is_alive(addr)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2304
        p->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2305
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2306
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2307
      FreeChunk* fc = (FreeChunk*)addr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2308
      res = fc->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2309
      if (FLSVerifyLists && !fc->cantCoalesce()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2310
        guarantee(_sp->verifyChunkInFreeLists(fc),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2311
                  "Chunk should be on a free list");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2312
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2313
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2314
    guarantee(res != 0, "Livelock: no rank reduction!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2315
    return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2316
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2317
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2318
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2319
class VerifyAllOopsClosure: public OopClosure {
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2320
 private:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2321
  const CMSCollector*             _collector;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2322
  const CompactibleFreeListSpace* _sp;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2323
  const MemRegion                 _span;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2324
  const bool                      _past_remark;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2325
  const CMSBitMap*                _bit_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2326
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2327
 protected:
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2328
  void do_oop(void* p, oop obj) {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2329
    if (_span.contains(obj)) { // the interior oop points into CMS heap
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2330
      if (!_span.contains(p)) { // reference from outside CMS heap
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2331
        // Should be a valid object; the first disjunct below allows
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2332
        // us to sidestep an assertion in block_is_obj() that insists
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2333
        // that p be in _sp. Note that several generations (and spaces)
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2334
        // are spanned by _span (CMS heap) above.
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2335
        guarantee(!_sp->is_in_reserved(obj) ||
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2336
                  _sp->block_is_obj((HeapWord*)obj),
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2337
                  "Should be an object");
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2338
        guarantee(obj->is_oop(), "Should be an oop");
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2339
        obj->verify();
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2340
        if (_past_remark) {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2341
          // Remark has been completed, the object should be marked
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2342
          _bit_map->isMarked((HeapWord*)obj);
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2343
        }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2344
      } else { // reference within CMS heap
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2345
        if (_past_remark) {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2346
          // Remark has been completed -- so the referent should have
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2347
          // been marked, if referring object is.
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2348
          if (_bit_map->isMarked(_collector->block_start(p))) {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2349
            guarantee(_bit_map->isMarked((HeapWord*)obj), "Marking error?");
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2350
          }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2351
        }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2352
      }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2353
    } else if (_sp->is_in_reserved(p)) {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2354
      // the reference is from FLS, and points out of FLS
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2355
      guarantee(obj->is_oop(), "Should be an oop");
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2356
      obj->verify();
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2357
    }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2358
  }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2359
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2360
  template <class T> void do_oop_work(T* p) {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2361
    T heap_oop = oopDesc::load_heap_oop(p);
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2362
    if (!oopDesc::is_null(heap_oop)) {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2363
      oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2364
      do_oop(p, obj);
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2365
    }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2366
  }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2367
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2368
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2369
  VerifyAllOopsClosure(const CMSCollector* collector,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2370
    const CompactibleFreeListSpace* sp, MemRegion span,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2371
    bool past_remark, CMSBitMap* bit_map) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2372
    OopClosure(), _collector(collector), _sp(sp), _span(span),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2373
    _past_remark(past_remark), _bit_map(bit_map) { }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2374
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2375
  virtual void do_oop(oop* p)       { VerifyAllOopsClosure::do_oop_work(p); }
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 185
diff changeset
  2376
  virtual void do_oop(narrowOop* p) { VerifyAllOopsClosure::do_oop_work(p); }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2377
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2378
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2379
void CompactibleFreeListSpace::verify(bool ignored) const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2380
  assert_lock_strong(&_freelistLock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2381
  verify_objects_initialized();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2382
  MemRegion span = _collector->_span;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2383
  bool past_remark = (_collector->abstract_state() ==
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2384
                      CMSCollector::Sweeping);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2385
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2386
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2387
  HandleMark  hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2388
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2389
  // Check integrity of CFL data structures
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2390
  _promoInfo.verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2391
  _dictionary->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2392
  if (FLSVerifyIndexTable) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2393
    verifyIndexedFreeLists();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2394
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2395
  // Check integrity of all objects and free blocks in space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2396
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2397
    VerifyAllBlksClosure cl(this, span);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2398
    ((CompactibleFreeListSpace*)this)->blk_iterate(&cl);  // cast off const
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2399
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2400
  // Check that all references in the heap to FLS
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2401
  // are to valid objects in FLS or that references in
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2402
  // FLS are to valid objects elsewhere in the heap
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2403
  if (FLSVerifyAllHeapReferences)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2404
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2405
    VerifyAllOopsClosure cl(_collector, this, span, past_remark,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2406
      _collector->markBitMap());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2407
    CollectedHeap* ch = Universe::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2408
    ch->oop_iterate(&cl);              // all oops in generations
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2409
    ch->permanent_oop_iterate(&cl);    // all oops in perm gen
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2410
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2411
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2412
  if (VerifyObjectStartArray) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2413
    // Verify the block offset table
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2414
    _bt.verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2415
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2416
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2417
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2418
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2419
void CompactibleFreeListSpace::verifyFreeLists() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2420
  if (FLSVerifyLists) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2421
    _dictionary->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2422
    verifyIndexedFreeLists();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2423
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2424
    if (FLSVerifyDictionary) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2425
      _dictionary->verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2426
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2427
    if (FLSVerifyIndexTable) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2428
      verifyIndexedFreeLists();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2429
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2430
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2431
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2432
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2433
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2434
void CompactibleFreeListSpace::verifyIndexedFreeLists() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2435
  size_t i = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2436
  for (; i < MinChunkSize; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2437
    guarantee(_indexedFreeList[i].head() == NULL, "should be NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2438
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2439
  for (; i < IndexSetSize; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2440
    verifyIndexedFreeList(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2441
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2442
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2443
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2444
void CompactibleFreeListSpace::verifyIndexedFreeList(size_t size) const {
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2445
  FreeChunk* fc   =  _indexedFreeList[size].head();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2446
  FreeChunk* tail =  _indexedFreeList[size].tail();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2447
  size_t    num = _indexedFreeList[size].count();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2448
  size_t      n = 0;
1374
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
  2449
  guarantee((size % 2 == 0) || fc == NULL, "Odd slots should be empty");
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2450
  for (; fc != NULL; fc = fc->next(), n++) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2451
    guarantee(fc->size() == size, "Size inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2452
    guarantee(fc->isFree(), "!free?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2453
    guarantee(fc->next() == NULL || fc->next()->prev() == fc, "Broken list");
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2454
    guarantee((fc->next() == NULL) == (fc == tail), "Incorrect tail");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2455
  }
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2456
  guarantee(n == num, "Incorrect count");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2457
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2458
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2459
#ifndef PRODUCT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2460
void CompactibleFreeListSpace::checkFreeListConsistency() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2461
  assert(_dictionary->minSize() <= IndexSetSize,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2462
    "Some sizes can't be allocated without recourse to"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2463
    " linear allocation buffers");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2464
  assert(MIN_TREE_CHUNK_SIZE*HeapWordSize == sizeof(TreeChunk),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2465
    "else MIN_TREE_CHUNK_SIZE is wrong");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2466
  assert((IndexSetStride == 2 && IndexSetStart == 2) ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2467
         (IndexSetStride == 1 && IndexSetStart == 1), "just checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2468
  assert((IndexSetStride != 2) || (MinChunkSize % 2 == 0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2469
      "Some for-loops may be incorrectly initialized");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2470
  assert((IndexSetStride != 2) || (IndexSetSize % 2 == 1),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2471
      "For-loops that iterate over IndexSet with stride 2 may be wrong");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2472
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2473
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2474
185
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2475
void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2476
  assert_lock_strong(&_freelistLock);
185
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2477
  FreeList total;
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2478
  gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count);
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2479
  FreeList::print_labels_on(gclog_or_tty, "size");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2480
  size_t totalFree = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2481
  for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2482
    const FreeList *fl = &_indexedFreeList[i];
185
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2483
    totalFree += fl->count() * fl->size();
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2484
    if (i % (40*IndexSetStride) == 0) {
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2485
      FreeList::print_labels_on(gclog_or_tty, "size");
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2486
    }
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2487
    fl->print_on(gclog_or_tty);
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2488
    total.set_bfrSurp(    total.bfrSurp()     + fl->bfrSurp()    );
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2489
    total.set_surplus(    total.surplus()     + fl->surplus()    );
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2490
    total.set_desired(    total.desired()     + fl->desired()    );
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2491
    total.set_prevSweep(  total.prevSweep()   + fl->prevSweep()  );
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2492
    total.set_beforeSweep(total.beforeSweep() + fl->beforeSweep());
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2493
    total.set_count(      total.count()       + fl->count()      );
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2494
    total.set_coalBirths( total.coalBirths()  + fl->coalBirths() );
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2495
    total.set_coalDeaths( total.coalDeaths()  + fl->coalDeaths() );
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2496
    total.set_splitBirths(total.splitBirths() + fl->splitBirths());
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2497
    total.set_splitDeaths(total.splitDeaths() + fl->splitDeaths());
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2498
  }
185
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2499
  total.print_on(gclog_or_tty, "TOTAL");
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2500
  gclog_or_tty->print_cr("Total free in indexed lists "
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2501
                         SIZE_FORMAT " words", totalFree);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2502
  gclog_or_tty->print("growth: %8.5f  deficit: %8.5f\n",
185
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2503
    (double)(total.splitBirths()+total.coalBirths()-total.splitDeaths()-total.coalDeaths())/
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2504
            (total.prevSweep() != 0 ? (double)total.prevSweep() : 1.0),
cda2a1eb4be5 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 1
diff changeset
  2505
    (double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0));
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2506
  _dictionary->printDictCensus();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2507
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2508
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2509
// Return the next displaced header, incrementing the pointer and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2510
// recycling spool area as necessary.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2511
markOop PromotionInfo::nextDisplacedHeader() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2512
  assert(_spoolHead != NULL, "promotionInfo inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2513
  assert(_spoolHead != _spoolTail || _firstIndex < _nextIndex,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2514
         "Empty spool space: no displaced header can be fetched");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2515
  assert(_spoolHead->bufferSize > _firstIndex, "Off by one error at head?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2516
  markOop hdr = _spoolHead->displacedHdr[_firstIndex];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2517
  // Spool forward
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2518
  if (++_firstIndex == _spoolHead->bufferSize) { // last location in this block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2519
    // forward to next block, recycling this block into spare spool buffer
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2520
    SpoolBlock* tmp = _spoolHead->nextSpoolBlock;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2521
    assert(_spoolHead != _spoolTail, "Spooling storage mix-up");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2522
    _spoolHead->nextSpoolBlock = _spareSpool;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2523
    _spareSpool = _spoolHead;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2524
    _spoolHead = tmp;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2525
    _firstIndex = 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2526
    NOT_PRODUCT(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2527
      if (_spoolHead == NULL) {  // all buffers fully consumed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2528
        assert(_spoolTail == NULL && _nextIndex == 1,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2529
               "spool buffers processing inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2530
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2531
    )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2532
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2533
  return hdr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2534
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2535
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2536
void PromotionInfo::track(PromotedObject* trackOop) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2537
  track(trackOop, oop(trackOop)->klass());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2538
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2539
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2540
void PromotionInfo::track(PromotedObject* trackOop, klassOop klassOfOop) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2541
  // make a copy of header as it may need to be spooled
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2542
  markOop mark = oop(trackOop)->mark();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2543
  trackOop->clearNext();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2544
  if (mark->must_be_preserved_for_cms_scavenge(klassOfOop)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2545
    // save non-prototypical header, and mark oop
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2546
    saveDisplacedHeader(mark);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2547
    trackOop->setDisplacedMark();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2548
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2549
    // we'd like to assert something like the following:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2550
    // assert(mark == markOopDesc::prototype(), "consistency check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2551
    // ... but the above won't work because the age bits have not (yet) been
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2552
    // cleared. The remainder of the check would be identical to the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2553
    // condition checked in must_be_preserved() above, so we don't really
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2554
    // have anything useful to check here!
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2555
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2556
  if (_promoTail != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2557
    assert(_promoHead != NULL, "List consistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2558
    _promoTail->setNext(trackOop);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2559
    _promoTail = trackOop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2560
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2561
    assert(_promoHead == NULL, "List consistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2562
    _promoHead = _promoTail = trackOop;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2563
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2564
  // Mask as newly promoted, so we can skip over such objects
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2565
  // when scanning dirty cards
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2566
  assert(!trackOop->hasPromotedMark(), "Should not have been marked");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2567
  trackOop->setPromotedMark();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2568
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2569
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2570
// Save the given displaced header, incrementing the pointer and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2571
// obtaining more spool area as necessary.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2572
void PromotionInfo::saveDisplacedHeader(markOop hdr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2573
  assert(_spoolHead != NULL && _spoolTail != NULL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2574
         "promotionInfo inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2575
  assert(_spoolTail->bufferSize > _nextIndex, "Off by one error at tail?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2576
  _spoolTail->displacedHdr[_nextIndex] = hdr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2577
  // Spool forward
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2578
  if (++_nextIndex == _spoolTail->bufferSize) { // last location in this block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2579
    // get a new spooling block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2580
    assert(_spoolTail->nextSpoolBlock == NULL, "tail should terminate spool list");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2581
    _splice_point = _spoolTail;                   // save for splicing
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2582
    _spoolTail->nextSpoolBlock = getSpoolBlock(); // might fail
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2583
    _spoolTail = _spoolTail->nextSpoolBlock;      // might become NULL ...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2584
    // ... but will attempt filling before next promotion attempt
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2585
    _nextIndex = 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2586
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2587
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2588
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2589
// Ensure that spooling space exists. Return false if spooling space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2590
// could not be obtained.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2591
bool PromotionInfo::ensure_spooling_space_work() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2592
  assert(!has_spooling_space(), "Only call when there is no spooling space");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2593
  // Try and obtain more spooling space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2594
  SpoolBlock* newSpool = getSpoolBlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2595
  assert(newSpool == NULL ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2596
         (newSpool->bufferSize != 0 && newSpool->nextSpoolBlock == NULL),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2597
        "getSpoolBlock() sanity check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2598
  if (newSpool == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2599
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2600
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2601
  _nextIndex = 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2602
  if (_spoolTail == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2603
    _spoolTail = newSpool;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2604
    if (_spoolHead == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2605
      _spoolHead = newSpool;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2606
      _firstIndex = 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2607
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2608
      assert(_splice_point != NULL && _splice_point->nextSpoolBlock == NULL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2609
             "Splice point invariant");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2610
      // Extra check that _splice_point is connected to list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2611
      #ifdef ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2612
      {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2613
        SpoolBlock* blk = _spoolHead;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2614
        for (; blk->nextSpoolBlock != NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2615
             blk = blk->nextSpoolBlock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2616
        assert(blk != NULL && blk == _splice_point,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2617
               "Splice point incorrect");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2618
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2619
      #endif // ASSERT
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2620
      _splice_point->nextSpoolBlock = newSpool;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2621
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2622
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2623
    assert(_spoolHead != NULL, "spool list consistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2624
    _spoolTail->nextSpoolBlock = newSpool;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2625
    _spoolTail = newSpool;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2626
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2627
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2628
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2629
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2630
// Get a free spool buffer from the free pool, getting a new block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2631
// from the heap if necessary.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2632
SpoolBlock* PromotionInfo::getSpoolBlock() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2633
  SpoolBlock* res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2634
  if ((res = _spareSpool) != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2635
    _spareSpool = _spareSpool->nextSpoolBlock;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2636
    res->nextSpoolBlock = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2637
  } else {  // spare spool exhausted, get some from heap
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2638
    res = (SpoolBlock*)(space()->allocateScratch(refillSize()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2639
    if (res != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2640
      res->init();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2641
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2642
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2643
  assert(res == NULL || res->nextSpoolBlock == NULL, "postcondition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2644
  return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2645
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2646
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2647
void PromotionInfo::startTrackingPromotions() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2648
  assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2649
         "spooling inconsistency?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2650
  _firstIndex = _nextIndex = 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2651
  _tracking = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2652
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2653
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2654
#define CMSPrintPromoBlockInfo 1
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2655
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2656
void PromotionInfo::stopTrackingPromotions(uint worker_id) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2657
  assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2658
         "spooling inconsistency?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2659
  _firstIndex = _nextIndex = 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2660
  _tracking = false;
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2661
  if (CMSPrintPromoBlockInfo > 1) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2662
    print_statistics(worker_id);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2663
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2664
}
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2665
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2666
void PromotionInfo::print_statistics(uint worker_id) const {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2667
  assert(_spoolHead == _spoolTail && _firstIndex == _nextIndex,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2668
         "Else will undercount");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2669
  assert(CMSPrintPromoBlockInfo > 0, "Else unnecessary call");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2670
  // Count the number of blocks and slots in the free pool
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2671
  size_t slots  = 0;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2672
  size_t blocks = 0;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2673
  for (SpoolBlock* cur_spool = _spareSpool;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2674
       cur_spool != NULL;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2675
       cur_spool = cur_spool->nextSpoolBlock) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2676
    // the first entry is just a self-pointer; indices 1 through
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2677
    // bufferSize - 1 are occupied (thus, bufferSize - 1 slots).
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2678
    guarantee((void*)cur_spool->displacedHdr == (void*)&cur_spool->displacedHdr,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2679
              "first entry of displacedHdr should be self-referential");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2680
    slots += cur_spool->bufferSize - 1;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2681
    blocks++;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2682
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2683
  if (_spoolHead != NULL) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2684
    slots += _spoolHead->bufferSize - 1;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2685
    blocks++;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2686
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2687
  gclog_or_tty->print_cr(" [worker %d] promo_blocks = %d, promo_slots = %d ",
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2688
                         worker_id, blocks, slots);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2689
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2690
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2691
// When _spoolTail is not NULL, then the slot <_spoolTail, _nextIndex>
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2692
// points to the next slot available for filling.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2693
// The set of slots holding displaced headers are then all those in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2694
// right-open interval denoted by:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2695
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2696
//    [ <_spoolHead, _firstIndex>, <_spoolTail, _nextIndex> )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2697
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2698
// When _spoolTail is NULL, then the set of slots with displaced headers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2699
// is all those starting at the slot <_spoolHead, _firstIndex> and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2700
// going up to the last slot of last block in the linked list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2701
// In this lartter case, _splice_point points to the tail block of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2702
// this linked list of blocks holding displaced headers.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2703
void PromotionInfo::verify() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2704
  // Verify the following:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2705
  // 1. the number of displaced headers matches the number of promoted
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2706
  //    objects that have displaced headers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2707
  // 2. each promoted object lies in this space
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2708
  debug_only(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2709
    PromotedObject* junk = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2710
    assert(junk->next_addr() == (void*)(oop(junk)->mark_addr()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2711
           "Offset of PromotedObject::_next is expected to align with "
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2712
           "  the OopDesc::_mark within OopDesc");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2713
  )
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2714
  // FIXME: guarantee????
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2715
  guarantee(_spoolHead == NULL || _spoolTail != NULL ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2716
            _splice_point != NULL, "list consistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2717
  guarantee(_promoHead == NULL || _promoTail != NULL, "list consistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2718
  // count the number of objects with displaced headers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2719
  size_t numObjsWithDisplacedHdrs = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2720
  for (PromotedObject* curObj = _promoHead; curObj != NULL; curObj = curObj->next()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2721
    guarantee(space()->is_in_reserved((HeapWord*)curObj), "Containment");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2722
    // the last promoted object may fail the mark() != NULL test of is_oop().
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2723
    guarantee(curObj->next() == NULL || oop(curObj)->is_oop(), "must be an oop");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2724
    if (curObj->hasDisplacedMark()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2725
      numObjsWithDisplacedHdrs++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2726
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2727
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2728
  // Count the number of displaced headers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2729
  size_t numDisplacedHdrs = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2730
  for (SpoolBlock* curSpool = _spoolHead;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2731
       curSpool != _spoolTail && curSpool != NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2732
       curSpool = curSpool->nextSpoolBlock) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2733
    // the first entry is just a self-pointer; indices 1 through
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2734
    // bufferSize - 1 are occupied (thus, bufferSize - 1 slots).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2735
    guarantee((void*)curSpool->displacedHdr == (void*)&curSpool->displacedHdr,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2736
              "first entry of displacedHdr should be self-referential");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2737
    numDisplacedHdrs += curSpool->bufferSize - 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2738
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2739
  guarantee((_spoolHead == _spoolTail) == (numDisplacedHdrs == 0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2740
            "internal consistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2741
  guarantee(_spoolTail != NULL || _nextIndex == 1,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2742
            "Inconsistency between _spoolTail and _nextIndex");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2743
  // We overcounted (_firstIndex-1) worth of slots in block
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2744
  // _spoolHead and we undercounted (_nextIndex-1) worth of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2745
  // slots in block _spoolTail. We make an appropriate
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2746
  // adjustment by subtracting the first and adding the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2747
  // second:  - (_firstIndex - 1) + (_nextIndex - 1)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2748
  numDisplacedHdrs += (_nextIndex - _firstIndex);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2749
  guarantee(numDisplacedHdrs == numObjsWithDisplacedHdrs, "Displaced hdr count");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2750
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2751
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2752
void PromotionInfo::print_on(outputStream* st) const {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2753
  SpoolBlock* curSpool = NULL;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2754
  size_t i = 0;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2755
  st->print_cr("start & end indices: [" SIZE_FORMAT ", " SIZE_FORMAT ")",
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2756
               _firstIndex, _nextIndex);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2757
  for (curSpool = _spoolHead; curSpool != _spoolTail && curSpool != NULL;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2758
       curSpool = curSpool->nextSpoolBlock) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2759
    curSpool->print_on(st);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2760
    st->print_cr(" active ");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2761
    i++;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2762
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2763
  for (curSpool = _spoolTail; curSpool != NULL;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2764
       curSpool = curSpool->nextSpoolBlock) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2765
    curSpool->print_on(st);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2766
    st->print_cr(" inactive ");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2767
    i++;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2768
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2769
  for (curSpool = _spareSpool; curSpool != NULL;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2770
       curSpool = curSpool->nextSpoolBlock) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2771
    curSpool->print_on(st);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2772
    st->print_cr(" free ");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2773
    i++;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2774
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2775
  st->print_cr(SIZE_FORMAT " header spooling blocks", i);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2776
}
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2777
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2778
void SpoolBlock::print_on(outputStream* st) const {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2779
  st->print("[" PTR_FORMAT "," PTR_FORMAT "), " SIZE_FORMAT " HeapWords -> " PTR_FORMAT,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2780
            this, (HeapWord*)displacedHdr + bufferSize,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2781
            bufferSize, nextSpoolBlock);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2782
}
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2783
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2784
///////////////////////////////////////////////////////////////////////////
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2785
// CFLS_LAB
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2786
///////////////////////////////////////////////////////////////////////////
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2787
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2788
#define VECTOR_257(x)                                                                                  \
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2789
  /* 1  2  3  4  5  6  7  8  9 1x 11 12 13 14 15 16 17 18 19 2x 21 22 23 24 25 26 27 28 29 3x 31 32 */ \
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2790
  {  x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2791
     x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2792
     x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2793
     x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2794
     x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2795
     x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2796
     x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2797
     x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x,   \
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2798
     x }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2799
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2800
// Initialize with default setting of CMSParPromoteBlocksToClaim, _not_
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2801
// OldPLABSize, whose static default is different; if overridden at the
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2802
// command-line, this will get reinitialized via a call to
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2803
// modify_initialization() below.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2804
AdaptiveWeightedAverage CFLS_LAB::_blocks_to_claim[]    =
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2805
  VECTOR_257(AdaptiveWeightedAverage(OldPLABWeight, (float)CMSParPromoteBlocksToClaim));
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2806
size_t CFLS_LAB::_global_num_blocks[]  = VECTOR_257(0);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2807
int    CFLS_LAB::_global_num_workers[] = VECTOR_257(0);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2808
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2809
CFLS_LAB::CFLS_LAB(CompactibleFreeListSpace* cfls) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2810
  _cfls(cfls)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2811
{
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2812
  assert(CompactibleFreeListSpace::IndexSetSize == 257, "Modify VECTOR_257() macro above");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2813
  for (size_t i = CompactibleFreeListSpace::IndexSetStart;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2814
       i < CompactibleFreeListSpace::IndexSetSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2815
       i += CompactibleFreeListSpace::IndexSetStride) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2816
    _indexedFreeList[i].set_size(i);
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2817
    _num_blocks[i] = 0;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2818
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2819
}
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2820
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2821
static bool _CFLS_LAB_modified = false;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2822
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2823
void CFLS_LAB::modify_initialization(size_t n, unsigned wt) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2824
  assert(!_CFLS_LAB_modified, "Call only once");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2825
  _CFLS_LAB_modified = true;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2826
  for (size_t i = CompactibleFreeListSpace::IndexSetStart;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2827
       i < CompactibleFreeListSpace::IndexSetSize;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2828
       i += CompactibleFreeListSpace::IndexSetStride) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2829
    _blocks_to_claim[i].modify(n, wt, true /* force */);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2830
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2831
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2832
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2833
HeapWord* CFLS_LAB::alloc(size_t word_sz) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2834
  FreeChunk* res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2835
  word_sz = _cfls->adjustObjectSize(word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2836
  if (word_sz >=  CompactibleFreeListSpace::IndexSetSize) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2837
    // This locking manages sync with other large object allocations.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2838
    MutexLockerEx x(_cfls->parDictionaryAllocLock(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2839
                    Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2840
    res = _cfls->getChunkFromDictionaryExact(word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2841
    if (res == NULL) return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2842
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2843
    FreeList* fl = &_indexedFreeList[word_sz];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2844
    if (fl->count() == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2845
      // Attempt to refill this local free list.
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2846
      get_from_global_pool(word_sz, fl);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2847
      // If it didn't work, give up.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2848
      if (fl->count() == 0) return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2849
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2850
    res = fl->getChunkAtHead();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2851
    assert(res != NULL, "Why was count non-zero?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2852
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2853
  res->markNotFree();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2854
  assert(!res->isFree(), "shouldn't be marked free");
613
2aa2b913106c 6687581: Make CMS work with compressed oops
coleenp
parents: 360
diff changeset
  2855
  assert(oop(res)->klass_or_null() == NULL, "should look uninitialized");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2856
  // mangle a just allocated object with a distinct pattern.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2857
  debug_only(res->mangleAllocated(word_sz));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2858
  return (HeapWord*)res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2859
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2860
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2861
// Get a chunk of blocks of the right size and update related
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2862
// book-keeping stats
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2863
void CFLS_LAB::get_from_global_pool(size_t word_sz, FreeList* fl) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2864
  // Get the #blocks we want to claim
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2865
  size_t n_blks = (size_t)_blocks_to_claim[word_sz].average();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2866
  assert(n_blks > 0, "Error");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2867
  assert(ResizePLAB || n_blks == OldPLABSize, "Error");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2868
  // In some cases, when the application has a phase change,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2869
  // there may be a sudden and sharp shift in the object survival
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2870
  // profile, and updating the counts at the end of a scavenge
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2871
  // may not be quick enough, giving rise to large scavenge pauses
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2872
  // during these phase changes. It is beneficial to detect such
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2873
  // changes on-the-fly during a scavenge and avoid such a phase-change
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2874
  // pothole. The following code is a heuristic attempt to do that.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2875
  // It is protected by a product flag until we have gained
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2876
  // enough experience with this heuristic and fine-tuned its behaviour.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2877
  // WARNING: This might increase fragmentation if we overreact to
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2878
  // small spikes, so some kind of historical smoothing based on
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2879
  // previous experience with the greater reactivity might be useful.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2880
  // Lacking sufficient experience, CMSOldPLABResizeQuicker is disabled by
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2881
  // default.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2882
  if (ResizeOldPLAB && CMSOldPLABResizeQuicker) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2883
    size_t multiple = _num_blocks[word_sz]/(CMSOldPLABToleranceFactor*CMSOldPLABNumRefills*n_blks);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2884
    n_blks +=  CMSOldPLABReactivityFactor*multiple*n_blks;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2885
    n_blks = MIN2(n_blks, CMSOldPLABMax);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2886
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2887
  assert(n_blks > 0, "Error");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2888
  _cfls->par_get_chunk_of_blocks(word_sz, n_blks, fl);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2889
  // Update stats table entry for this block size
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2890
  _num_blocks[word_sz] += fl->count();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2891
}
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2892
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2893
void CFLS_LAB::compute_desired_plab_size() {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2894
  for (size_t i =  CompactibleFreeListSpace::IndexSetStart;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2895
       i < CompactibleFreeListSpace::IndexSetSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2896
       i += CompactibleFreeListSpace::IndexSetStride) {
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2897
    assert((_global_num_workers[i] == 0) == (_global_num_blocks[i] == 0),
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2898
           "Counter inconsistency");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2899
    if (_global_num_workers[i] > 0) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2900
      // Need to smooth wrt historical average
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2901
      if (ResizeOldPLAB) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2902
        _blocks_to_claim[i].sample(
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2903
          MAX2((size_t)CMSOldPLABMin,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2904
          MIN2((size_t)CMSOldPLABMax,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2905
               _global_num_blocks[i]/(_global_num_workers[i]*CMSOldPLABNumRefills))));
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2906
      }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2907
      // Reset counters for next round
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2908
      _global_num_workers[i] = 0;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2909
      _global_num_blocks[i] = 0;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2910
      if (PrintOldPLAB) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2911
        gclog_or_tty->print_cr("[%d]: %d", i, (size_t)_blocks_to_claim[i].average());
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2912
      }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2913
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2914
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2915
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2916
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2917
void CFLS_LAB::retire(int tid) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2918
  // We run this single threaded with the world stopped;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2919
  // so no need for locks and such.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2920
#define CFLS_LAB_PARALLEL_ACCESS 0
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2921
  NOT_PRODUCT(Thread* t = Thread::current();)
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2922
  assert(Thread::current()->is_VM_thread(), "Error");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2923
  assert(CompactibleFreeListSpace::IndexSetStart == CompactibleFreeListSpace::IndexSetStride,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2924
         "Will access to uninitialized slot below");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2925
#if CFLS_LAB_PARALLEL_ACCESS
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2926
  for (size_t i = CompactibleFreeListSpace::IndexSetSize - 1;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2927
       i > 0;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2928
       i -= CompactibleFreeListSpace::IndexSetStride) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2929
#else // CFLS_LAB_PARALLEL_ACCESS
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2930
  for (size_t i =  CompactibleFreeListSpace::IndexSetStart;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2931
       i < CompactibleFreeListSpace::IndexSetSize;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2932
       i += CompactibleFreeListSpace::IndexSetStride) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2933
#endif // !CFLS_LAB_PARALLEL_ACCESS
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2934
    assert(_num_blocks[i] >= (size_t)_indexedFreeList[i].count(),
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2935
           "Can't retire more than what we obtained");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2936
    if (_num_blocks[i] > 0) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2937
      size_t num_retire =  _indexedFreeList[i].count();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2938
      assert(_num_blocks[i] > num_retire, "Should have used at least one");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2939
      {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2940
#if CFLS_LAB_PARALLEL_ACCESS
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2941
        MutexLockerEx x(_cfls->_indexedFreeListParLocks[i],
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2942
                        Mutex::_no_safepoint_check_flag);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2943
#endif // CFLS_LAB_PARALLEL_ACCESS
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2944
        // Update globals stats for num_blocks used
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2945
        _global_num_blocks[i] += (_num_blocks[i] - num_retire);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2946
        _global_num_workers[i]++;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2947
        assert(_global_num_workers[i] <= (ssize_t)ParallelGCThreads, "Too big");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2948
        if (num_retire > 0) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2949
          _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2950
          // Reset this list.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2951
          _indexedFreeList[i] = FreeList();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2952
          _indexedFreeList[i].set_size(i);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2953
        }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2954
      }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2955
      if (PrintOldPLAB) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2956
        gclog_or_tty->print_cr("%d[%d]: %d/%d/%d",
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2957
                               tid, i, num_retire, _num_blocks[i], (size_t)_blocks_to_claim[i].average());
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2958
      }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2959
      // Reset stats for next round
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2960
      _num_blocks[i]         = 0;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2961
    }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2962
  }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2963
}
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2964
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2965
void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, FreeList* fl) {
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2966
  assert(fl->count() == 0, "Precondition.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2967
  assert(word_sz < CompactibleFreeListSpace::IndexSetSize,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2968
         "Precondition");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2969
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2970
  // We'll try all multiples of word_sz in the indexed set, starting with
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2971
  // word_sz itself and, if CMSSplitIndexedFreeListBlocks, try larger multiples,
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2972
  // then try getting a big chunk and splitting it.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2973
  {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2974
    bool found;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2975
    int  k;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2976
    size_t cur_sz;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2977
    for (k = 1, cur_sz = k * word_sz, found = false;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2978
         (cur_sz < CompactibleFreeListSpace::IndexSetSize) &&
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2979
         (CMSSplitIndexedFreeListBlocks || k <= 1);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2980
         k++, cur_sz = k * word_sz) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2981
      FreeList* gfl = &_indexedFreeList[cur_sz];
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2982
      FreeList fl_for_cur_sz;  // Empty.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2983
      fl_for_cur_sz.set_size(cur_sz);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2984
      {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2985
        MutexLockerEx x(_indexedFreeListParLocks[cur_sz],
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2986
                        Mutex::_no_safepoint_check_flag);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2987
        if (gfl->count() != 0) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2988
          // nn is the number of chunks of size cur_sz that
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2989
          // we'd need to split k-ways each, in order to create
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2990
          // "n" chunks of size word_sz each.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2991
          const size_t nn = MAX2(n/k, (size_t)1);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2992
          gfl->getFirstNChunksFromList(nn, &fl_for_cur_sz);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2993
          found = true;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2994
          if (k > 1) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2995
            // Update split death stats for the cur_sz-size blocks list:
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2996
            // we increment the split death count by the number of blocks
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2997
            // we just took from the cur_sz-size blocks list and which
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2998
            // we will be splitting below.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  2999
            ssize_t deaths = _indexedFreeList[cur_sz].splitDeaths() +
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3000
                             fl_for_cur_sz.count();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3001
            _indexedFreeList[cur_sz].set_splitDeaths(deaths);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3002
          }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3003
        }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3004
      }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3005
      // Now transfer fl_for_cur_sz to fl.  Common case, we hope, is k = 1.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3006
      if (found) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3007
        if (k == 1) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3008
          fl->prepend(&fl_for_cur_sz);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3009
        } else {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3010
          // Divide each block on fl_for_cur_sz up k ways.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3011
          FreeChunk* fc;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3012
          while ((fc = fl_for_cur_sz.getChunkAtHead()) != NULL) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3013
            // Must do this in reverse order, so that anybody attempting to
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3014
            // access the main chunk sees it as a single free block until we
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3015
            // change it.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3016
            size_t fc_size = fc->size();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3017
            for (int i = k-1; i >= 0; i--) {
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3018
              FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3019
              ffc->setSize(word_sz);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3020
              ffc->linkNext(NULL);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3021
              ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3022
              // Above must occur before BOT is updated below.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3023
              // splitting from the right, fc_size == (k - i + 1) * wordsize
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3024
              _bt.mark_block((HeapWord*)ffc, word_sz);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3025
              fc_size -= word_sz;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3026
              _bt.verify_not_unallocated((HeapWord*)ffc, ffc->size());
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3027
              _bt.verify_single_block((HeapWord*)fc, fc_size);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3028
              _bt.verify_single_block((HeapWord*)ffc, ffc->size());
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3029
              // Push this on "fl".
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3030
              fl->returnChunkAtHead(ffc);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3031
            }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3032
            // TRAP
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3033
            assert(fl->tail()->next() == NULL, "List invariant.");
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3034
          }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3035
        }
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3036
        // Update birth stats for this block size.
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3037
        size_t num = fl->count();
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3038
        MutexLockerEx x(_indexedFreeListParLocks[word_sz],
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3039
                        Mutex::_no_safepoint_check_flag);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3040
        ssize_t births = _indexedFreeList[word_sz].splitBirths() + num;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3041
        _indexedFreeList[word_sz].set_splitBirths(births);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3042
        return;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3043
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3044
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3045
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3046
  // Otherwise, we'll split a block from the dictionary.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3047
  FreeChunk* fc = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3048
  FreeChunk* rem_fc = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3049
  size_t rem;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3050
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3051
    MutexLockerEx x(parDictionaryAllocLock(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3052
                    Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3053
    while (n > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3054
      fc = dictionary()->getChunk(MAX2(n * word_sz,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3055
                                  _dictionary->minSize()),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3056
                                  FreeBlockDictionary::atLeast);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3057
      if (fc != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3058
        _bt.allocated((HeapWord*)fc, fc->size());  // update _unallocated_blk
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3059
        dictionary()->dictCensusUpdate(fc->size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3060
                                       true /*split*/,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3061
                                       false /*birth*/);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3062
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3063
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3064
        n--;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3065
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3066
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3067
    if (fc == NULL) return;
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3068
    assert((ssize_t)n >= 1, "Control point invariant");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3069
    // Otherwise, split up that block.
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3070
    const size_t nn = fc->size() / word_sz;
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3071
    n = MIN2(nn, n);
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3072
    assert((ssize_t)n >= 1, "Control point invariant");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3073
    rem = fc->size() - n * word_sz;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3074
    // If there is a remainder, and it's too small, allocate one fewer.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3075
    if (rem > 0 && rem < MinChunkSize) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3076
      n--; rem += word_sz;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3077
    }
4577
18d854d28d4e 6912018: CMS: guarantee(head() != 0,"The head of the list cannot be NULL")
jmasa
parents: 4574
diff changeset
  3078
    // Note that at this point we may have n == 0.
18d854d28d4e 6912018: CMS: guarantee(head() != 0,"The head of the list cannot be NULL")
jmasa
parents: 4574
diff changeset
  3079
    assert((ssize_t)n >= 0, "Control point invariant");
18d854d28d4e 6912018: CMS: guarantee(head() != 0,"The head of the list cannot be NULL")
jmasa
parents: 4574
diff changeset
  3080
18d854d28d4e 6912018: CMS: guarantee(head() != 0,"The head of the list cannot be NULL")
jmasa
parents: 4574
diff changeset
  3081
    // If n is 0, the chunk fc that was found is not large
18d854d28d4e 6912018: CMS: guarantee(head() != 0,"The head of the list cannot be NULL")
jmasa
parents: 4574
diff changeset
  3082
    // enough to leave a viable remainder.  We are unable to
18d854d28d4e 6912018: CMS: guarantee(head() != 0,"The head of the list cannot be NULL")
jmasa
parents: 4574
diff changeset
  3083
    // allocate even one block.  Return fc to the
18d854d28d4e 6912018: CMS: guarantee(head() != 0,"The head of the list cannot be NULL")
jmasa
parents: 4574
diff changeset
  3084
    // dictionary and return, leaving "fl" empty.
18d854d28d4e 6912018: CMS: guarantee(head() != 0,"The head of the list cannot be NULL")
jmasa
parents: 4574
diff changeset
  3085
    if (n == 0) {
18d854d28d4e 6912018: CMS: guarantee(head() != 0,"The head of the list cannot be NULL")
jmasa
parents: 4574
diff changeset
  3086
      returnChunkToDictionary(fc);
18d854d28d4e 6912018: CMS: guarantee(head() != 0,"The head of the list cannot be NULL")
jmasa
parents: 4574
diff changeset
  3087
      return;
18d854d28d4e 6912018: CMS: guarantee(head() != 0,"The head of the list cannot be NULL")
jmasa
parents: 4574
diff changeset
  3088
    }
18d854d28d4e 6912018: CMS: guarantee(head() != 0,"The head of the list cannot be NULL")
jmasa
parents: 4574
diff changeset
  3089
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3090
    // First return the remainder, if any.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3091
    // Note that we hold the lock until we decide if we're going to give
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3092
    // back the remainder to the dictionary, since a concurrent allocation
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3093
    // may otherwise see the heap as empty.  (We're willing to take that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3094
    // hit if the block is a small block.)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3095
    if (rem > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3096
      size_t prefix_size = n * word_sz;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3097
      rem_fc = (FreeChunk*)((HeapWord*)fc + prefix_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3098
      rem_fc->setSize(rem);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3099
      rem_fc->linkNext(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3100
      rem_fc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3101
      // Above must occur before BOT is updated below.
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3102
      assert((ssize_t)n > 0 && prefix_size > 0 && rem_fc > fc, "Error");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3103
      _bt.split_block((HeapWord*)fc, fc->size(), prefix_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3104
      if (rem >= IndexSetSize) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3105
        returnChunkToDictionary(rem_fc);
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3106
        dictionary()->dictCensusUpdate(rem, true /*split*/, true /*birth*/);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3107
        rem_fc = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3108
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3109
      // Otherwise, return it to the small list below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3110
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3111
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3112
  if (rem_fc != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3113
    MutexLockerEx x(_indexedFreeListParLocks[rem],
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3114
                    Mutex::_no_safepoint_check_flag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3115
    _bt.verify_not_unallocated((HeapWord*)rem_fc, rem_fc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3116
    _indexedFreeList[rem].returnChunkAtHead(rem_fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3117
    smallSplitBirth(rem);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3118
  }
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3119
  assert((ssize_t)n > 0 && fc != NULL, "Consistency");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3120
  // Now do the splitting up.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3121
  // Must do this in reverse order, so that anybody attempting to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3122
  // access the main chunk sees it as a single free block until we
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3123
  // change it.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3124
  size_t fc_size = n * word_sz;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3125
  // All but first chunk in this loop
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3126
  for (ssize_t i = n-1; i > 0; i--) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3127
    FreeChunk* ffc = (FreeChunk*)((HeapWord*)fc + i * word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3128
    ffc->setSize(word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3129
    ffc->linkNext(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3130
    ffc->linkPrev(NULL); // Mark as a free block for other (parallel) GC threads.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3131
    // Above must occur before BOT is updated below.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3132
    // splitting from the right, fc_size == (n - i + 1) * wordsize
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3133
    _bt.mark_block((HeapWord*)ffc, word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3134
    fc_size -= word_sz;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3135
    _bt.verify_not_unallocated((HeapWord*)ffc, ffc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3136
    _bt.verify_single_block((HeapWord*)ffc, ffc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3137
    _bt.verify_single_block((HeapWord*)fc, fc_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3138
    // Push this on "fl".
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3139
    fl->returnChunkAtHead(ffc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3140
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3141
  // First chunk
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3142
  fc->setSize(word_sz);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3143
  fc->linkNext(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3144
  fc->linkPrev(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3145
  _bt.verify_not_unallocated((HeapWord*)fc, fc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3146
  _bt.verify_single_block((HeapWord*)fc, fc->size());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3147
  fl->returnChunkAtHead(fc);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3148
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3149
  assert((ssize_t)n > 0 && (ssize_t)n == fl->count(), "Incorrect number of blocks");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3150
  {
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3151
    // Update the stats for this block size.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3152
    MutexLockerEx x(_indexedFreeListParLocks[word_sz],
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3153
                    Mutex::_no_safepoint_check_flag);
4574
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3154
    const ssize_t births = _indexedFreeList[word_sz].splitBirths() + n;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3155
    _indexedFreeList[word_sz].set_splitBirths(births);
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3156
    // ssize_t new_surplus = _indexedFreeList[word_sz].surplus() + n;
b2d5b0975515 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 2105
diff changeset
  3157
    // _indexedFreeList[word_sz].set_surplus(new_surplus);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3158
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3159
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3160
  // TRAP
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3161
  assert(fl->tail()->next() == NULL, "List invariant.");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3162
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3163
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3164
// Set up the space's par_seq_tasks structure for work claiming
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3165
// for parallel rescan. See CMSParRemarkTask where this is currently used.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3166
// XXX Need to suitably abstract and generalize this and the next
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3167
// method into one.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3168
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3169
CompactibleFreeListSpace::
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3170
initialize_sequential_subtasks_for_rescan(int n_threads) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3171
  // The "size" of each task is fixed according to rescan_task_size.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3172
  assert(n_threads > 0, "Unexpected n_threads argument");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3173
  const size_t task_size = rescan_task_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3174
  size_t n_tasks = (used_region().word_size() + task_size - 1)/task_size;
1372
654bcf7839bc 6722116: CMS: Incorrect overflow handling when using parallel concurrent marking
ysr
parents: 977
diff changeset
  3175
  assert((n_tasks == 0) == used_region().is_empty(), "n_tasks incorrect");
654bcf7839bc 6722116: CMS: Incorrect overflow handling when using parallel concurrent marking
ysr
parents: 977
diff changeset
  3176
  assert(n_tasks == 0 ||
654bcf7839bc 6722116: CMS: Incorrect overflow handling when using parallel concurrent marking
ysr
parents: 977
diff changeset
  3177
         ((used_region().start() + (n_tasks - 1)*task_size < used_region().end()) &&
654bcf7839bc 6722116: CMS: Incorrect overflow handling when using parallel concurrent marking
ysr
parents: 977
diff changeset
  3178
          (used_region().start() + n_tasks*task_size >= used_region().end())),
654bcf7839bc 6722116: CMS: Incorrect overflow handling when using parallel concurrent marking
ysr
parents: 977
diff changeset
  3179
         "n_tasks calculation incorrect");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3180
  SequentialSubTasksDone* pst = conc_par_seq_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3181
  assert(!pst->valid(), "Clobbering existing data?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3182
  pst->set_par_threads(n_threads);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3183
  pst->set_n_tasks((int)n_tasks);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3184
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3185
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3186
// Set up the space's par_seq_tasks structure for work claiming
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3187
// for parallel concurrent marking. See CMSConcMarkTask where this is currently used.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3188
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3189
CompactibleFreeListSpace::
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3190
initialize_sequential_subtasks_for_marking(int n_threads,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3191
                                           HeapWord* low) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3192
  // The "size" of each task is fixed according to rescan_task_size.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3193
  assert(n_threads > 0, "Unexpected n_threads argument");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3194
  const size_t task_size = marking_task_size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3195
  assert(task_size > CardTableModRefBS::card_size_in_words &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3196
         (task_size %  CardTableModRefBS::card_size_in_words == 0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3197
         "Otherwise arithmetic below would be incorrect");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3198
  MemRegion span = _gen->reserved();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3199
  if (low != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3200
    if (span.contains(low)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3201
      // Align low down to  a card boundary so that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3202
      // we can use block_offset_careful() on span boundaries.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3203
      HeapWord* aligned_low = (HeapWord*)align_size_down((uintptr_t)low,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3204
                                 CardTableModRefBS::card_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3205
      // Clip span prefix at aligned_low
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3206
      span = span.intersection(MemRegion(aligned_low, span.end()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3207
    } else if (low > span.end()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3208
      span = MemRegion(low, low);  // Null region
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3209
    } // else use entire span
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3210
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3211
  assert(span.is_empty() ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3212
         ((uintptr_t)span.start() %  CardTableModRefBS::card_size == 0),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3213
        "span should start at a card boundary");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3214
  size_t n_tasks = (span.word_size() + task_size - 1)/task_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3215
  assert((n_tasks == 0) == span.is_empty(), "Inconsistency");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3216
  assert(n_tasks == 0 ||
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3217
         ((span.start() + (n_tasks - 1)*task_size < span.end()) &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3218
          (span.start() + n_tasks*task_size >= span.end())),
1372
654bcf7839bc 6722116: CMS: Incorrect overflow handling when using parallel concurrent marking
ysr
parents: 977
diff changeset
  3219
         "n_tasks calculation incorrect");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3220
  SequentialSubTasksDone* pst = conc_par_seq_tasks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3221
  assert(!pst->valid(), "Clobbering existing data?");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3222
  pst->set_par_threads(n_threads);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3223
  pst->set_n_tasks((int)n_tasks);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3224
}