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